I am having issues with androids grid view. When I scroll, some text views disappear. I have a conditional statement that checks a value in the database and hides the text views based on that. But that conditional statement is only meant to be for the views in the grid that meet the criteria. However, when scrolling all views seem to change.
Here is my custom array adapter (I have also attached an image to show what I mean):
![public class ArrayAdapterHandler extends ArrayAdapter<Day> {
public Context context;
int layoutResourceId;
ArrayList<Day> days = new ArrayList<Day>();
public ArrayAdapterHandler(Context context, int dayId,
ArrayList<Day> days) {
super(context, dayId, days);
this.layoutResourceId = dayId;
this.context = context;
this.days = days;
}
/*private view holder class*/
private class ViewHolder {
TextView day_text;
TextView situps_text;
TextView crunches_text;
TextView legRaises_text;
TextView plank_text;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
Day day = days.get(position);
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.day_row, null);
if (position % 2 == 0) {
convertView.setBackgroundColor(0x30BFFF1E);
} else {
convertView.setBackgroundColor(0x30CCCCCC);
}
holder = new ViewHolder();
holder.day_text = (TextView) convertView.findViewById(R.id.day_text);
holder.situps_text = (TextView) convertView.findViewById(R.id.situps_text);
holder.crunches_text = (TextView) convertView.findViewById(R.id.crunches_text);
holder.legRaises_text = (TextView) convertView.findViewById(R.id.legRaise_text);
holder.plank_text = (TextView) convertView.findViewById(R.id.plank_text);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.day_text.setText(String.valueOf(day.getDay()));
if (day.isCompleted() == 1 || day.isRestDay() == 1) {
// Hide all the activity values which are 0 anyway.
holder.situps_text.setVisibility(4);
holder.legRaises_text.setVisibility(4);
holder.plank_text.setVisibility(4);
}
if (day.isRestDay() == 1) {
holder.crunches_text.setText("REST DAY");
} else if(day.isCompleted() == 1) {
holder.crunches_text.setText("COMPLETED!");
} else {
holder.situps_text.setText(String.valueOf(day.getSitups()) + " situps");
holder.crunches_text.setText(String.valueOf(day.getCrunches()) + " crunches");
holder.legRaises_text.setText(String.valueOf(day.getLegRaises()) + " leg raises");
holder.plank_text.setText(String.valueOf(day.getPlanks()) + "sec planks");
}
return convertView;
}
}
![Scrolling issue image]: http://i.stack.imgur.com/zB3uL.png
Thankyou.
Related
GridView item color changes randomly whenever I scroll.
Every item color is based on the status of the SQLite database, but when I tried to scroll multiple times it change the color of the item randomly. Is there any way to solve this? This is what it looks like.
Here is the code
GetView
private class ViewHolder{
ImageView imageView, mPreviewCashCard;
TextView txtName, txtPrice, txtSeriesNo;
}
#Override
public View getView(int position, View view, ViewGroup viewGroup) {
Cursor cursor = MainActivity.sqLiteHelper.getData("SELECT id,status FROM DarkMode");
while (cursor.moveToNext()) {
DarkModeStatus = cursor.getString(1);
}
View row = view;
ViewHolder holder = new ViewHolder();
if(row == null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(layout, null);
holder.txtName = (TextView) row.findViewById(R.id.txtName);
holder.txtPrice = (TextView) row.findViewById(R.id.txtPrice);
holder.txtSeriesNo = (TextView) row.findViewById(R.id.txtSeriesNumber);
holder.imageView = (ImageView) row.findViewById(R.id.imgFood);
holder.mPreviewCashCard = (ImageView) row.findViewById(R.id.imgId);
row.setTag(holder);
}
else {
holder = (ViewHolder) row.getTag();
}
Inventory inventory = inventoryList.get(position);
holder.txtName.setText(inventory.getName());
holder.txtPrice.setText(inventory.getPrice());
holder.txtSeriesNo.setText(inventory.getSeriesNumber());
int status = inventory.getStatus();
if (status==0 && DarkModeStatus.matches("false")){
row.setBackgroundColor(Color.parseColor("#FEF8DD"));
}
else if(status==0 && DarkModeStatus.matches("true")){
row.setBackgroundColor(Color.parseColor("#282828"));
}
byte[] CashCardImage = inventory.getImage();
byte[] idImage = inventory.getIdImage();
if(CashCardImage.length > 1)
{
Bitmap bitmap = BitmapFactory.decodeByteArray(CashCardImage, 0, CashCardImage.length);
holder.imageView.setImageBitmap(bitmap);
}
else{
holder.imageView.setImageResource(R.drawable.ic_image);
}
if(idImage.length > 1)
{
Bitmap bitmap2 = BitmapFactory.decodeByteArray(idImage, 0, idImage.length);
holder.mPreviewCashCard.setImageBitmap(bitmap2);
}
else{
holder.mPreviewCashCard.setImageResource(R.drawable.ic_image);
}
return row;
}
Try adding an else condition to your if-else block handling backgrounds.
if (status==0 && DarkModeStatus.matches("false")){
row.setBackgroundColor(Color.parseColor("#FEF8DD"));
}
else if(status==0 && DarkModeStatus.matches("true")){
row.setBackgroundColor(Color.parseColor("#282828"));
}else {
row.setBackgroundColor(Color.parseColor("#FFFFFF")); // white or whichever default background color you are using
}
From my understanding this could fix the issue.
What is want is to update total number in textview in one activity. i have a custom adapter which calls Arraylist in this activity then populates in listview, this adapter also has image view which removes the list item and does notifydatasetchanged().
this is my customadapter
private ArrayList<DataModel> dataSet;
Context mContext;
private static class ViewHolder {
TextView txtName;
TextView txtType;
Button remove;
}
public CustomAdapterForData(ArrayList<DataModel> data, Context context) {
super(context, R.layout.fields, data);
this.dataSet = data;
this.mContext=context;
}
#Override
public void onClick(View view) {
int position = (Integer) view.getTag();
Object object = getItem(position);
DataModel dataModel = (DataModel) object;
switch (view.getId())
{
case R.id.btnRemove:
remove(dataModel);
// dataSet.remove(position);
//dataSet.remove(position);
notifyDataSetChanged();
break;
}
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
DataModel dataModel = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
ViewHolder viewHolder; // view lookup cache stored in tag
final View result;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.fields, parent, false);
viewHolder.txtName = (TextView) convertView.findViewById(R.id.fieldName);
viewHolder.txtType = (TextView) convertView.findViewById(R.id.tvPrize);
viewHolder.remove = (Button) convertView.findViewById(R.id.btnRemove);
result=convertView;
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
result=convertView;
}
viewHolder.txtName.setText(dataModel.getFieldName());
viewHolder.txtType.setText(dataModel.getType());
viewHolder.remove.setOnClickListener(this);
viewHolder.remove.setTag(position);
return convertView;
}
after that this is my onstart()
protected void onStart() {
//if ((dataModels.size()!=0)){
ListView listView = (ListView) findViewById(R.id.listView);
adapter = new CustomAdapterForData(dataModels, getApplicationContext());
listView.setAdapter(adapter);
dataModelsnew = dataModels;
TextView tv = (TextView) findViewById(R.id.textViewTotal);
double sum = 0;
for (int i = 0 ; i < dataModelsnew.size(); i++){
sum = sum + dataModelsnew.get(i).getPrize();
}
tv.setText("Total : " + String.valueOf(Math.round(sum)*100d/100d));
//}
super.onStart();
}
what i want is populate latest value in textview which is sum of double (one element of ArrayList).Please help me to resolve this.
Thanks in advance. The variable i want to update after i remove something from list view otherwise it is working fine.
You can use DataSetObservers to detect any changes in your data:
final TextView tv = (TextView) findViewById(R.id.textViewTotal);
adapter.registerDataSetObserver(new DataSetObserver() {
#Override
public void onChanged() {
super.onChanged();
double sum = 0;
for (int i = 0 ; i < dataModels.size(); i++){
sum = sum + dataModels.get(i).getPrize();
}
tv.setText("Total : " + String.valueOf(Math.round(sum)*100d/100d));
}
});
I have made a custom adapter for a autocompletetextview, but it's not filtering on the text and inputting weird strings when you select a item. Like this string:
listadapters.LocatieRowItem#BSE433q4e30
I have made this adapter so the first item of the autocompletetextview could have a image and a different color then the rest.
Here is my custom adapter:
public class LocatieAdapter extends ArrayAdapter<LocatieRowItem> {
Context context;
private List<LocatieRowItem> items;
public LocatieAdapter(Context context, int resourceId, List<LocatieRowItem> items) {
super(context, resourceId, items);
this.context = context;
this.items = items;
}
/*private view holder class*/
private class ViewHolder {
ImageView imageView;
TextView txtTitle;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
LocatieRowItem rowItem = items.get(position);
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.locatieitem, null);
holder = new ViewHolder();
holder.txtTitle = (TextView) convertView.findViewById(R.id.text1);
holder.imageView = (ImageView) convertView.findViewById(R.id.logo);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
if(rowItem.getTitle().equals("huidige locatie")) {
if (holder.imageView.getVisibility() != View.VISIBLE) {
holder.imageView.setVisibility(View.VISIBLE);
holder.txtTitle.setTextColor(Color.parseColor("#33B5E5"));
holder.txtTitle.setPadding(40, 10, 5, 5);
}
} else {
holder.imageView.setVisibility(View.GONE);
holder.txtTitle.setTextColor(Color.parseColor("#333333"));
holder.txtTitle.setPadding(10, 10, 10, 10);
}
holder.txtTitle.setText(rowItem.getTitle());
//convertView.setBackgroundColor(position % 2 == 0 ? Color.WHITE : Color.parseColor("#F8F8F8"));
return convertView;
}
}
If I scroll through my ListView one TextView (expiresIn) in an listview item gets copied into others randomly. I'm guessing this has to do with the ViewHolder but I really can't see where i'm going wrong, and its only the expiresIn TextView I have the problem with:
public class MySyncListAdapter extends CouchbaseViewListAdapter {
protected MainActivity parent;
private CouchDbConnector db;
private static final String TAG = "MySyncListAdapter";
public MySyncListAdapter(MainActivity parent, CouchDbConnector couchDbConnector, ViewQuery viewQuery) {
super(couchDbConnector, viewQuery, true);
this.parent = parent;
this.db = couchDbConnector;
Log.d(TAG, "in constructor");
}
private static class ViewHolder {
ImageView img;
TextView label;
TextView dateAdded;
TextView expiresIn;
}
#Override
public View getView(int position, View itemView, ViewGroup parent) {
Log.d(TAG, "in getView");
View v = itemView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.list_item, null);
ViewHolder vh = new ViewHolder();
vh.label = (TextView) v.findViewById(R.id.label);
vh.img = (ImageView) v.findViewById(R.id.img);
vh.dateAdded = (TextView) v.findViewById(R.id.tvDateAdded);
vh.expiresIn = (TextView) v.findViewById(R.id.tvExpiresInList);
v.setTag(vh);
}
TextView label = ((ViewHolder)v.getTag()).label;
TextView dateAdded = ((ViewHolder)v.getTag()).dateAdded;
TextView expiresIn = ((ViewHolder)v.getTag()).expiresIn;
ImageView img = ((ViewHolder)v.getTag()).img;
Row row = getRow(position);
JsonNode item = row.getValueAsNode();
JsonNode itemText = item.get("header");
JsonNode dateAddedText = item.get("dateAdded");
JsonNode expiryDateText = item.get("expiryDate");
JsonNode attachmentText = item.get("_attachments");
ViewHolder holder = (ViewHolder) v.getTag();
if(label != null) {
holder.label.setText(itemText.getTextValue());
}
if(dateAdded != null) {
Log.d(TAG, "in dateAdded getView");
if(CompareDate.isDateAddedToday(dateAddedText.getTextValue())){
holder.dateAdded.setText(R.string.today);
}
else if (CompareDate.isDateAddedYesterday(dateAddedText.getTextValue())){
holder.dateAdded.setText(R.string.yesterday);
}
else{
String age = String.valueOf(CompareDate.getAgeInDays(dateAddedText.getTextValue()));
holder.dateAdded.setText( age + " " + parent.getResources().getString(R.string.days_ago));
}
}
if(!expiryDateText.isNull() && expiresIn != null){
long noDays = CompareDate.getDaysUntil(expiryDateText.getTextValue());
if(noDays<6){
holder.expiresIn.setTextColor(Color.parseColor("#ff4444"));
}
holder.expiresIn.setText(String.valueOf(noDays) + " " + parent.getResources().getString(R.string.days_until_expiry));
}
if(img != null){
//bitmap stuff
holder.img.setImageBitmap(bitmap);
}
return v;
}
Update
Solved it by adding an else statement an specifically setting expiresIn to "". Would love an explaination however why if I don't specifically set it, it uses another item's textview.
if(!expiryDateText.isNull() && expiresIn != null){
long noDays = CompareDate.getDaysUntil(expiryDateText.getTextValue());
if(noDays<6){
holder.expiresIn.setTextColor(Color.parseColor("#ff4444"));
}
holder.expiresIn.setText(String.valueOf(noDays) + " " + parent.getResources().getString(R.string.days_until_expiry));
}
else {
holder.expiresIn.setText("");
}
Is it possible to get an item view based on its position in the adapter and not in the visible views in the ListView?
I am aware of functions like getChildAt() and getItemIdAtPosition() however they provide information based on the visible views inside ListView. I am also aware that Android recycles views which means that I can only work with the visible views in the ListView.
My objective is to have a universal identifier for each item since I am using CursorAdapter so I don't have to calculate the item's position relative to the visible items.
Here's how I accomplished this. Within my (custom) adapter class:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
LayoutInflater inflater = context.getLayoutInflater();
view = inflater.inflate(textViewResourceId, parent, false);
final ViewHolder viewHolder = new ViewHolder();
viewHolder.name = (TextView) view.findViewById(R.id.name);
viewHolder.button = (ImageButton) view.findViewById(R.id.button);
viewHolder.button.setOnClickListener
(new View.OnClickListener() {
#Override
public void onClick(View view) {
int position = (int) viewHolder.button.getTag();
Log.d(TAG, "Position is: " +position);
}
});
view.setTag(viewHolder);
viewHolder.button.setTag(items.get(position));
} else {
view = convertView;
((ViewHolder) view.getTag()).button.setTag(items.get(position));
}
ViewHolder holder = (ViewHolder) view.getTag();
return view;
}
Essentially the trick is to set and retrieve the position index via the setTag and getTag methods. The items variable refers to the ArrayList containing my custom (adapter) objects.
Also see this tutorial for in-depth examples. Let me know if you need me to clarify anything.
See below code:
public static class ViewHolder
{
public TextView nm;
public TextView tnm;
public TextView tr;
public TextView re;
public TextView membercount;
public TextView membernm;
public TextView email;
public TextView phone;
public ImageView ii;
}
class ImageAdapter extends ArrayAdapter<CoordinatorData>
{
private ArrayList<CoordinatorData> items;
public FoodDriveImageLoader imageLoader;
public ImageAdapter(Context context, int textViewResourceId,ArrayList<CoordinatorData> items)
{
super(context, textViewResourceId, items);
this.items = items;
}
public View getView(int position, View convertView, ViewGroup parent)
{
View v = convertView;
ViewHolder holder = null;
if (v == null)
{
try
{
holder=new ViewHolder();
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader = new FoodDriveImageLoader(FoodDriveModule.this);
v = vi.inflate(R.layout.virtual_food_drive_row, null);
//System.out.println("layout is null.......");
holder.nm = (TextView) v.findViewById(R.id.name);
holder.tnm = (TextView) v.findViewById(R.id.teamname);
holder.tr = (TextView) v.findViewById(R.id.target);
holder.re = (TextView) v.findViewById(R.id.received);
holder.membercount = new TextView(FoodDriveModule.this);
holder.membernm = new TextView(FoodDriveModule.this);
holder.email = new TextView(FoodDriveModule.this);
holder.phone = new TextView(FoodDriveModule.this);
holder.ii = (ImageView) v.findViewById(R.id.icon);
v.setTag(holder);
}
catch(Exception e)
{
System.out.println("Excption Caught"+e);
}
}
else
{
holder=(ViewHolder)v.getTag();
}
CoordinatorData co = items.get(position);
holder.nm.setText(co.getName());
holder.tnm.setText(co.getTeamName());
holder.tr.setText(co.getTarget());
holder.re.setText(co.getReceived());
holder.ii.setTag(co.getImage());
imageLoader.DisplayImage(co.getImage(), FoodDriveModule.this , holder.ii);
if (co != null)
{
}
return v;
}
}
A better option is to identify using the data returned by the CursorAdapter rather than visible views.
For example if your data is in a Array , each data item has a unique index.
Here, Its very short described code, you can simple re-use viewholder pattern to increase listview performance
Write below code in your getview() method
ViewHolder holder = new ViewHolder();
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.skateparklist, null);
holder = new ViewHolder();
holder.headlineView = (TextView) convertView
.findViewById(R.id.textView1);
holder.DistanceView = (TextView) convertView
.findViewById(R.id.textView2);
holder.imgview = (NetworkImageView) convertView
.findViewById(R.id.imgSkatepark);
convertView.setTag(holder); //PLEASE PASS HOLDER AS OBJECT PARAM , CAUSE YOU CAN NOY PASS POSITION IT WILL BE CONFLICT Holder and Integer can not cast
//BECAUSE WE NEED TO REUSE CREATED HOLDER
} else {
holder = (ViewHolder) convertView.getTag();
}
// your controls/UI setup
holder.DistanceView.setText(strDistance);
......
return convertview
Listview lv = (ListView) findViewById(R.id.previewlist);
final BaseAdapter adapter = new PreviewAdapter(this, name, age);
confirm.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
View view = null;
String value;
for (int i = 0; i < adapter.getCount(); i++) {
view = adapter.getView(i, view, lv);
Textview et = (TextView) view.findViewById(R.id.passfare);
value=et.getText().toString();
Toast.makeText(getApplicationContext(), value,
Toast.LENGTH_SHORT).show();
}
}
});