android gallery view “stutters” with deferred image loading adapter

后端 未结 3 1192
广开言路
广开言路 2020-12-30 15:30

I would like to create an deferred loading adapter for use with a Gallery widget.

That is to say getView() returns an ImageView

3条回答
  •  野趣味
    野趣味 (楼主)
    2020-12-30 16:24

    I have an answer for you!

    When any of the setImage... methods are called on ImageView in internally a layout pass is requested, for example, setImageBitmap() as above is defined as such

    public void setImageBitmap(Bitmap bm) {
        setImageDrawable(new BitmapDrawable(mContext.getResources(), bm));
    }
    

    which calls

    public void setImageDrawable(Drawable drawable) {
        if (mDrawable != drawable) {
            mResource = 0;
            mUri = null;
            updateDrawable(drawable);
            requestLayout(); //layout requested here!
            invalidate();
        }
    }
    

    which has the effect of the gallery 'snapping' to the center of the image thats currently closest to the center of the gallery.

    What I have done to prevent this is have the View thats loading into the Gallery have a explicit height and width (in dips) and using an ImageView subclass that ignores layout requests. This works as the gallery still has a layout pass initially but does not bother doing this every time an image in the gallery changes, which I imagine would only need to happen if the gallery views had their width and height set to WRAP_CONTENT, which we dont. Note that as invalidate() is still called in setImageDrawable() the image will still be drawn when set.

    My very simple ImageView subclass below!

    /**
     * This class is useful when loading images (say via a url or file cache) into
     * ImageView that are contained in dynamic views (Gallerys and ListViews for
     * example) The width and height should be set explicitly instead of using
     * wrap_content as any wrapping of content will not be triggered by the image
     * drawable or bitmap being set (which is normal behaviour for an ImageView)
     * 
     */
    public class ImageViewNoLayoutRefresh extends ImageView
    {
        public ImageViewNoLayoutRefresh(Context context, AttributeSet attrs, int defStyle)
        {
            super(context, attrs, defStyle);
        }
    
        public ImageViewNoLayoutRefresh(Context context, AttributeSet attrs)
        {
            super(context, attrs);
        }
    
        public ImageViewNoLayoutRefresh(Context context)
        {
            super(context);
        }
    
        @Override
        public void requestLayout()
        {
            // do nothing - for this to work well this image view should have its dims
            // set explicitly
        }
    }
    

    edit: i should mention that the onItemSelected approaches can also work, but as I needed to hook into that while flinging was taking place I came up with the above, which I think is more flexible approach

提交回复
热议问题