When the image has been downloaded, some of the images duplicates in the listview rows, even though some of the row has no ImageID, The adapter view duplicates the downloaded images, when i suddenly scroll the listview
My code in getView
public View getView(final int position, View convertView, ViewGroup parent) {
int anotherPosition = position;
if (inflater == null) {
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
final Holder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_item, null);
holder = new Holder();
holder.title = (TextView) convertView.findViewById(R.id.description);
holder.exp = (TextView) convertView.findViewById(R.id.expiration);
holder.someImages = (ImageView) convertView.findViewById(R.id.listview_image);
holder.isFavouriteImage = (ImageView) convertView.findViewById(R.id.isFavourite);
convertView.setTag(holder);
convertView.setTag(R.id.listview_image, holder.someImages);
convertView.setTag(R.id.description, holder.title);
convertView.setTag(R.id.expiration, holder.exp);
convertView.setTag(R.id.isFavourite, holder.isFavouriteImage);
} else {
holder = (Holder) convertView.getTag();
}
RowItemLoyalty rowItemLoyalty = data.get(position);
if(rowItemLoyalty != null) {
holder.someImages.setTag(position);
holder.someImages.setImageBitmap(null);
holder.title.setText(data.get(position).getDescription());
holder.exp.setText(data.get(position).getDateEnd());
Log.d("TrueOrFalse", String.valueOf(holder.someImages));
if(holder.someImages != null ) {
if (data.get(position).getImageId() != 0) {
data.get(position).setBitmap(email, password, data.get(position).getImageId(), data.get(position).getBitmap(), new RowItemLoyalty.RetrieveBitmapListener() {
#Override
public void onSuccess(Bitmap bitmap) {
Log.d("ImageID123", String.valueOf(data.get(position).getImageId()));
holder.someImages.setImageBitmap(null);
if (data.get(position).getBitmap() != null) {
Log.d("True", "True");
holder.someImages.setImageBitmap(bitmap);
}
}
});
}
} else if(holder.someImages == null ) {
Drawable placeholder = ContextCompat.getDrawable(context, R.drawable.placeholderwhite);
holder.someImages.setImageDrawable(placeholder);
Log.d("PlaceHolder2", String.valueOf(placeholder));
}
//----------- placeholder for imageview list -----------
//holder.someImages.setImageBitmap(null);
if (data.get(position).getBitmap() != null && holder.someImages != null) {
holder.someImages.setImageBitmap(data.get(position).getBitmap());
Log.d("PlaceHolder", "Implemented");
Log.d("PlaceHolder", String.valueOf(data.get(position)));
} else if (data.get(position).getBitmap() == null) {
Drawable placeholder = ContextCompat.getDrawable(context, R.drawable.placeholderwhite);
holder.someImages.setImageDrawable(placeholder);
Log.d("PlaceHolder2", String.valueOf(placeholder));
}
//------------ for favourite logo-------------
if (data.get(position).getIsFavorite() == false) {
Drawable placeholderIsNotFavourite = ContextCompat.getDrawable(context, R.drawable.ic_favourite_icon);
holder.isFavouriteImage.setImageDrawable(placeholderIsNotFavourite);
} else if (data.get(position).getIsFavorite() == true) {
Drawable favourited = ContextCompat.getDrawable(context, R.drawable.favourite_two);
holder.isFavouriteImage.setImageDrawable(favourited);
}
}
return convertView;
}
My Holder class
public static class Holder {
TextView title;
TextView exp;
TextView tokensFor;
ImageView promotionImages;
ImageView isFavouriteImage;
}
There are some useful libraries you can use to loading images like Glide
Also you can see this Picasso v/s Imageloader v/s Fresco vs Glide
Try using Universal Image Loader Universal Image Loader
to set image on ImageView
Remove checking convertView == null condition, like this:
convertView = inflater.inflate(R.layout.list_item, null);
holder = new Holder();
holder.title = (TextView) convertView.findViewById(R.id.description);
holder.exp = (TextView) convertView.findViewById(R.id.expiration);
holder.someImages = (ImageView) convertView.findViewById(R.id.listview_image);
holder.isFavouriteImage = (ImageView) convertView.findViewById(R.id.isFavourite);
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.
I have an custom list view.
it is laggy when if comes to the conditional statements part
public View getView(int position, View convertView, ViewGroup parent) {
View caloocanView = convertView;
ViewHolder holder = new ViewHolder();
if (caloocanView == null)
caloocanView = getLayoutInflater().inflate(R.layout.caloocan_list_view, parent, false);
restauInfoDB restaurant = Restau.get(position);
//ImageView from URL
holder.restauIcon = (ImageView) caloocanView.findViewById(R.id.imageView);
Glide.with(getContext()).load(restaurant.getUrl()).centerCrop()
.placeholder(R.drawable.six)
.crossFade()
.into(holder.restauIcon);
String x = "N";
Double hotCTR = 15.0;
String New = "N";
holder.healthyIcon = (ImageView) caloocanView.findViewById(R.id.healthyIcon);
//HEALTHY
if (x.equals(restaurant.getHealthy())) {
holder.healthyIcon.setVisibility(View.INVISIBLE);
}
else
{
holder.healthyIcon.setVisibility(View.VISIBLE);
}
//NEW
if (New.equals(restaurant.getNew())){
holder.newLabel = (ImageView) caloocanView.findViewById(R.id.newLabel);
holder.newLabel.setVisibility(View.INVISIBLE);
}
else {
holder.newLabel = (ImageView) caloocanView.findViewById(R.id.newLabel);
holder.newLabel.setVisibility(View.VISIBLE);
}
//HOT
if (hotCTR <= Double.valueOf(restaurant.getRating())) {
holder.hotIcon = (ImageView) caloocanView.findViewById(R.id.iconHot);
holder.hotIcon.setVisibility(View.VISIBLE);
}
else
{
holder.hotIcon = (ImageView) caloocanView.findViewById(R.id.iconHot);
holder.hotIcon.setVisibility(View.INVISIBLE);
}
String serving = "Serving: ";
// RESTAU NAME
holder.restauName = (TextView) caloocanView.findViewById(R.id.resnameTxt);
holder.restauName.setText(restaurant.getResname());
//FOOD TYPE
holder.oh = (TextView) caloocanView.findViewById(R.id.ophrTxt);
holder.oh.setText("Operating Hours: " +restaurant.getOh());
holder.resloc = (TextView) caloocanView.findViewById(R.id.reslocTxt);
holder.resloc.setText(restaurant.getResloc());
return caloocanView;
}`
and this is the static viewHolder
static class ViewHolder
{
ImageView restauIcon;
ImageView healthyIcon;
ImageView newLabel;
ImageView hotIcon;
TextView restauName;
TextView oh;
TextView resloc;
}
you are missing the point of using ViewHolder,the point is to minimize inflating new layouts and finding views in layout which are time consuming and make view laggy,but you are calling findViewById() every time.
try this code instead:
View caloocanView = convertView;
ViewHolder holder = new ViewHolder();
if (caloocanView == null) {
caloocanView = getLayoutInflater().inflate(R.layout.caloocan_list_view, parent, false);
holder.restauIcon = (ImageView) caloocanView.findViewById(R.id.imageView);
holder.healthyIcon = (ImageView) caloocanView.findViewById(R.id.healthyIcon);
holder.newLabel = (ImageView) caloocanView.findViewById(R.id.newLabel);
...
caloocanView.setTag(holder);
}else{
holder = (ViewHolder) caloocanView.getTag();
}
...
//HEALTHY
if (x.equals(restaurant.getHealthy())) {
holder.healthyIcon.setVisibility(View.INVISIBLE);
}
else
{
holder.healthyIcon.setVisibility(View.VISIBLE);
}
and reformat rest of your code
Try adding this line to your RecyclerView layout xml:
android:nestedScrollingEnabled="false"
It may be not affect older versions of Android, but in newer versions the lag is completely gone.
EDIT:by RecyclerView, I mean ListView
I m facing a problem when I want to load images from an adapter using the ion library.
In fact, I have items with a string corresponding to the url of the iconic image that I want to load for each item on my gridview.
The problem is due to the adapter view management (reusing existing view if I m not wrong), and I dont know how to bypass this...
For example, if I load 10 elements with an image, the first time it works. Then, when I scroll to bottom, and then I scroll to top, the image changes (due to the reuse of the existing view...)
Can you help me ?
This is my adapter code :
public class ProtocoleAdapter extends BaseAdapter {
private Context context;
private List<ProtocoleItem> mListe;
public ProtocoleAdapter(Context context, List<ProtocoleItem> liste) {
this.context = context;
this.mListe = liste;
}
private class ViewHolder {
TextView txtTitre;
ImageView img;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater
.inflate(R.layout.grid_item, null);
holder = new ViewHolder();
holder.txtTitre = (TextView) convertView
.findViewById(R.id.grid_item_label);
holder.img = (ImageView) convertView
.findViewById(R.id.grid_item_image);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
final ProtocoleItem rowItem = mListe.get(position);
boolean isLoaded = false;
try {
Bitmap bitmap = Ion.with(context)
.load(rowItem.getImage())
.asBitmap()
.get();
isLoaded = true;
holder.img.setImageBitmap(bitmap);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
if (!isLoaded) {
if (position % 5 == 0) {
holder.img.setBackgroundColor(0xff176799);
} else {
if (position % 4 == 0) {
holder.img.setBackgroundColor(0xff2F87B0);
} else {
if (position % 3 == 0) {
holder.img.setBackgroundColor(0xff42A4BB);
} else {
if (position % 2 == 0) {
holder.img.setBackgroundColor(0xff5BC0C4);
} else {
holder.img.setBackgroundColor(0xff78D6C7);
}
}
}
}
}
holder.txtTitre.setText(rowItem.getTitre());
return convertView;
}
Thanks for all !
Have a good day
Get the latest version of Ion and use the following.
Ion.with(holder.img)
.load(rowItem.getImage());
This method will load asynchronously.
Your current usage is blocking the UI thread. Ion should properly handle convertView recycling, so that is not an issue.
This is lazy loading problem, go with Universal image loader: https://github.com/nostra13/Android-Universal-Image-Loader
https://github.com/nostra13/Android-Universal-Image-Loader/blob/master/sample/src/com/nostra13/example/universalimageloader/ImagePagerActivity.java
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.
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();
}
}
});