Search code examples
androidandroid-viewpagerandroid-volleyandroid-progressbar

Volley ImageRequest won't always replace progress spinner with image inside ViewPagerAdapter


I would like to be able to load images into a ViewPager with volley and a progress spinner.

My issue is sometimes the image shows and sometimes the progress spinner goes on forever. Generally if it takes less than a second to load the image, it loads properly and the image shows, otherwise the progress spinner goes on forever if it takes any longer.

Here is my PagerAdapter code in the instantiateItem method:

    @Override
public Object instantiateItem(ViewGroup container, int position) {
    LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
    viewGroup = container;

    view = inflater.inflate(R.layout.photo_pager_layout, container, false);
    progressLayout = (LinearLayout) view.findViewById(R.id.photoProgress);

    imageView  = (TouchImageView) view.findViewById(R.id.photo);
    RequestQueue queue = Volley.newRequestQueue(activity);
    Display display = activity.getWindowManager().getDefaultDisplay();
    Point size = new Point();
    display.getSize(size);

    String url = photos.get(position).getPhotoUrl();
    url = url.replaceAll(activity.getString(R.string.flickr_photo_link_fifth), activity.getString(R.string.flickr_photo_link_sixth));

    progressLayout.setVisibility(View.VISIBLE);
    imageView.setVisibility(View.GONE);

    ImageRequest imageRequest = new ImageRequest(url, new Response.Listener<Bitmap>() {
        @Override
        public void onResponse(Bitmap response) {
            progressLayout.setVisibility(View.GONE);
            imageView.setVisibility(View.VISIBLE);
            imageView.setImageBitmap(response);


        }
    }, 1600, 1600, ImageView.ScaleType.FIT_XY, Bitmap.Config.ARGB_8888, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            error.printStackTrace();
            progressLayout.setVisibility(View.GONE);
        }
    });
    queue.add(imageRequest);
    container.addView(view);

    return view;
}

any help is appreciated, thanks.


Solution

  • So, I went looking hard for a while, and this worked really well!

    1. I used Universal Image Loader for loading the image. You can find this here: https://github.com/nostra13/Android-Universal-Image-Loader, and to add it to your project you need to add this line to your Build.Gradle file:

      compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'

    2. I used an extension of Fresco's (by Facebook) ZoomableDraweeView to hold the image, found that zooming still didn't work, so I looked more in depth. It's still really useful for holding loaded photos without fail, so I'll post it here: https://github.com/ibosong/CommentGallery/tree/master/frescozoomablelib/, and you can add this to your Build.Gradle dependencies to use it:

      compile 'com.github.ibosong.CommentGallery:frescozoomablelib:1.0.1'

    3. I found a PhotoViewAttacher that works really well for zooming in and out of the photos here: https://github.com/chrisbanes/PhotoView, and you can add this to you Build.Gradle dependencies to use it:

      compile 'com.commit451:PhotoView:1.2.4'

      You also need to add this to your Build.Gradle repositories:

      maven { url 'https://jitpack.io' }

    I can confirm that this works really well with a ViewPager, implementation is posted below:

    PhotoPagerActivity:

    private PhotoPagerAdapter mAdapter;
    private ViewPager mPager;
    private Activity activity;
    private DisplayImageOptions options;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.photo_pager_activity);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    
        // Show the Up button in the action bar.
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
        }
    
        activity = this;
    
        options = new DisplayImageOptions.Builder()
                .resetViewBeforeLoading(true)
                .imageScaleType(ImageScaleType.EXACTLY)
                .bitmapConfig(Bitmap.Config.RGB_565)
                .considerExifParams(true)
                .displayer(new FadeInBitmapDisplayer(300))
                .build();
    
        Bundle extras = getIntent().getExtras();
        int position = extras.getInt("pos");
        String title = extras.getString("AlbumTitle");
        setTitle(title);
    
        ArrayList<Photo> photos = PhotoAlbumActivity.getPhotos();
        mPager = (ViewPager) findViewById(R.id.photoPager);
        mAdapter = new PhotoPagerAdapter(photos, activity, options);
        mPager.setAdapter(mAdapter);
        mPager.setCurrentItem(position);
    }
    

    PhotoPagerAdapter:

    private ArrayList<Photo> images;
    private View v;
    private LayoutInflater inflater;
    private ZoomableDraweeView mImageView;
    private Activity activity;
    private ImageLoader imageLoader;
    private DisplayImageOptions options;
    
    PhotoPagerAdapter(ArrayList<Photo> images, Activity activity, DisplayImageOptions options) {
        super();
        this.images = images;
        this.activity = activity;
        ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Builder(activity).build();
        ImageLoader.getInstance().init(configuration);
        imageLoader = ImageLoader.getInstance();
        this.options = options;
    }
    
    @Override
    public Object instantiateItem(final ViewGroup container, int position) {
        inflater = LayoutInflater.from(activity);
        v = inflater.inflate(R.layout.photo_pager_layout, container, false);
    
        String url = images.get(position).getPhotoUrl().replaceAll(activity.getString(R.string.flickr_photo_link_fifth), activity.getString(R.string.flickr_photo_link_sixth));
        mImageView = (ZoomableDraweeView) v.findViewById(R.id.photo);
        PhotoViewAttacher pAttacher;
        pAttacher = new PhotoViewAttacher(mImageView);
        pAttacher.update();
    
    
        imageLoader.displayImage(url, mImageView, options, new SimpleImageLoadingListener() {
            @Override
            public void onLoadingStarted(String imageUri, View view) {
    
            }
    
            @Override
            public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
                String message = null;
                switch (failReason.getType()) {
                    case IO_ERROR:
                        message = "Input/Output error";
                        break;
                    case DECODING_ERROR:
                        message = "Image can't be downloaded";
                        break;
                    case NETWORK_DENIED:
                        message = "Downloads are denied";
                        break;
                    case OUT_OF_MEMORY:
                        message = "Out Of Memory error";
                        break;
                    case UNKNOWN:
                        message = "Unknown error";
                        break;
                }
    
                Toast.makeText(v.getContext(), message, Toast.LENGTH_SHORT).show();
            }
    
            @Override
            public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
            }
        });
    
        container.addView(v, 0);
        return v;
    }
    

    and photo_pager_layout:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="1dp">
    
        <ProgressBar
            android:id="@+id/pbHeaderProgress"
            style="@style/SpinnerAsEditText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"/>
    
        <com.bosong.frescozoomablelib.zoomable.ZoomableDraweeView
            android:id="@+id/photo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:scaleType="fitXY"
            android:layout_gravity="center"/>
    
    </FrameLayout>
    

    The layout for the activity just contains a viewpager and some other stuff that are unimportant. Hope this helps someone!