Skip to content Skip to sidebar Skip to footer

How To Avoid Image Flickering In A Listview

I have a listivew that display a bunch of images. am using Universal Image Loader to load this images from files to imageviews. This images have different dimensions and i want all

Solution 1:

After hours of research, i was able to know the method that i can use to calculate new imageview height while maintaining image aspect ratio.

    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;

//Returns null, sizes are in the options variable
BitmapFactory.decodeFile("/sdcard/image.png", options);
int width = options.outWidth;
int height = options.outHeight;

//calculating image aspect ratio
float ratio =(float) height/(float) width;

//calculating my image height since i want it to be 360px wide
int newHeight = Math.round(ratio*360);

//setting the new dimentions
 imageview.getLayoutParams().width = 360;
 imageview.getLayoutParams().height = newHeight;

 //i'm using universal image loader to display image
 imaheview.post(new Runnable(){
  ImageLoader.getInstance().displayImage(imageuri,imageview,displayoptions);
 });

Solution 2:

You can do something like this :

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;

//Returns null, sizes are in the options variable
BitmapFactory.decodeFile("/sdcard/image.png", options);
int width = options.outWidth;
int height = options.outHeight;
//If you want, the MIME type will also be decoded (if possible)
String type = options.outMimeType;

Solution 3:

How I solved it was by creating a Bitmap[] array variable to store images, then in adapter's getView(), I used position to check if image in Bitmap[] array is null or has value. If it is has value, then I use the value instead of calling the new DownloadImageTask() construct again.

For example:

YourCustomArrayAdapter.java

public class MyCustomArrayAdapter extends ArrayAdapter {
   private static Bitmap[] myListViewImageViewsArray = new Bitmap[listViewItemsArray.length];
   private String[] myListViewImageURLsArray = new String[listViewItemsArray.length]{
      "image_url_1",
      "image_url_2",
      ...
      ...
   };


   @Override
   public View getView(int position, View view, ViewGroup parent){
       CustomViewHolder vHolder;
        if(view == null){
            view = inflater.inflate(R.layout.movies_coming_soon_content_template, null, true);
            vHolder = new CustomViewHolder();
            vHolder.imageView = (AppCompatImageView) view.findViewById(R.id.my_cutom_image);
            vHolder.imageUrl = "";
            view.setTag(vHolder);
        }
        else{
            vHolder = (CustomViewHolder)view.getTag();
            // -- Set imageview src to null or some predefined placeholder (this is not really necessary but it might help just to flush any conflicting data hanging around)
            vHolder.imageView.setImageResource(null);
        }

       // ... 


       // -- THIS IS THE MAIN PART THAT STOPPED THE FLICKERING FOR ME
       if(myListViewImageViewsArray[position] != null){
          vHolder.imageView.setImageBitmap(myListViewImageViewsArray[position]);
       }else{
          new DownloadImageTask(position, vHolder.imageView).execute(vHolder.imageUrl);
       }
       // -- END OF THE FLICKERING CONTROL    
   }
}

Then, in your image downloader construct, after downloading the image, make an insertion into the Bitmap[] image array for that position. For example:

YourImageDownloaderClass.java

public class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
   AppCompatImageView imageView;
   int position;

   public DownloadImageTask(int position, AppCompatImageView imageView){
       this.imageView = imageView;
       this.position = position;
   }

   @Override
   protected Bitmap doInBackground(String...urls) {

       String urlOfImage = urls[0];
       Bitmap logo = null;
       try{            
           logo = BitmapFactory.decodeStream((InputStream) new URL(urlOfImage).getContent());
       }catch(Exception e){
           e.printStackTrace();            
       }
       return logo;
   }

   @Override
   protected void onPostExecute(Bitmap result){
       if(result != null) {
          YourCustomArrayAdapter.myListViewImageViewsArray [position] = result;
          imageView.setImageBitmap(result);                    
       }else{
          YourCustomArrayAdapter.myListViewImageViewsArray [position] = null;
          imageView.setImageResource(null);                  
       }
    }
}

Solution 4:

my suggestion is to use grid view to avoid flickering of images it will load at first time if it is same url , it will load from cache

 Glide.with(mContext)
            .load(item.getImageUrl())
            .into(holder.mIVGridPic);

Post a Comment for "How To Avoid Image Flickering In A Listview"