Abdul Ahad
Abdul Ahad

Reputation: 540

Recycler View Shuffles Images On Scroll

I have a recycler view, and it is being populated using Universal Image Loader.

@Override
public MasonryView onCreateViewHolder(ViewGroup parent, int viewType) {
    View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.grid_item, parent, false);
    MasonryView masonryView = new MasonryView(layoutView);
    //layoutView.setOnClickListener(new MyOnClickListener());
    //imageLoader.destroy();
    imageLoader.init(ImageLoaderConfiguration.createDefault(context));
    options = new DisplayImageOptions.Builder()
            .cacheInMemory(true)
            .resetViewBeforeLoading(true)
            .cacheOnDisk(true)
            .considerExifParams(false)
            .bitmapConfig(Bitmap.Config.RGB_565)
            .build();

    return masonryView;
}

@Override
public void onBindViewHolder(final MasonryView holder, int position) {

    imageLoader
            .displayImage(IMAGE_URLS[position], holder.imageView, options, new SimpleImageLoadingListener() {
                @Override
                public void onLoadingStarted(String imageUri, View view) {
                    holder.donut_progress.setVisibility(View.VISIBLE);
                    holder.donut_progress.setProgress(0);
                }

                @Override
                public void onLoadingFailed(String imageUri, View view, FailReason failReason) {

                    holder.onLoadImage.setVisibility(View.GONE);
                }

                @Override
                public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
                    holder.onLoadImage.setVisibility(View.GONE);
                    holder.donut_progress.setVisibility(View.GONE);
                }
            }, new ImageLoadingProgressListener() {
                @Override
                public void onProgressUpdate(String imageUri, View view, int current, int total) {
                    holder.donut_progress.setProgress(Math.round(100.0f * current / total));
                }
            });


}

As you can see that imageloader and the DisplayOptions are defined in the CreateView.

The Images Are displayed successfully but, when it is being scrolled the images are shuffling.

Following is my xml for custom_recycler_grid_item

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00000000"
android:orientation="vertical">

    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"/>
    !-- android:scaleType="centerCrop" --!


    <ImageView
        android:id="@+id/onLoadImage"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:src="@drawable/camera_cross"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="50dp"
        android:visibility="gone"/>

    <progressIndicators.DonutProgress
        android:layout_marginLeft="50dp"
        android:layout_marginTop="50dp"
        android:id="@+id/donut_progress"
        android:layout_width="50dp"
        android:layout_height="50dp"
        custom:donut_unfinished_stroke_width="1dp"
        custom:donut_finished_stroke_width="1dp"
        custom:donut_progress="50"/>

</FrameLayout>

My Main Fragment, that has the recyclerView

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView
    android:id="@+id/masonry_grid"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="0.1"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />


</LinearLayout>

However, I have also set adapter.setHasStableIds(true);

Upvotes: 3

Views: 1254

Answers (4)

rana
rana

Reputation: 1862

the problem is with

holder.onLoadImage.setVisibility(View.GONE);

You have to cautious how you are setting visibility gone and then making it visible. At the end , it is the same view holder for which visibility is shown and not shown. If you ensure the

holder.onLoadImage.setVisibility(View.VISIBLE)

at the begining of the onBindHolder() .You should be fine

Upvotes: 0

Abdul Ahad
Abdul Ahad

Reputation: 540

I solved this issue completely.

The issue was with my RecyclerWidget height and width.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView
    android:id="@+id/masonry_grid"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="0.1"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />


</LinearLayout>

I had to set my height and width to wrap content.

Upvotes: 2

P Yellappa
P Yellappa

Reputation: 436

Display the placeholder until original image loads, same problem occurred in my case also, so i followed this approach.

Do this in your Launcher(First) activity

// customise display options

    DisplayImageOptions options = new DisplayImageOptions.Builder()
        .showImageOnFail(R.drawable.placeholder_steve)
        .showImageForEmptyUri(R.drawable.placeholder_steve)
        .showImageOnLoading(R.drawable.placeholder_steve)
        .bitmapConfig(Bitmap.Config.RGB_565)
        .considerExifParams(true)
        .cacheInMemory(true)
        .cacheOnDisk(true)
        .build(); 

// configure

    ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
        .defaultDisplayImageOptions(options)
      /*.diskCache(lruDiskCache)*/
        .build();
ImageLoader.getInstance().init(config);

Upvotes: 0

Naruto-Uzumaki
Naruto-Uzumaki

Reputation: 21

Universal image Loader Async Task operation. inside Universal image loader they have used OkHTTP client server operation. that is the reason your images getting shuffled. Try to use Glide to load images it is better approach. And also Go through this Example here.

Simple and easy and faster way to load image. Glide.with(itemView.getContext()).load(Datas.getRequestURL()).centerCrop().into(mStaticMap);

Upvotes: 0

Related Questions