GridView scrollBar: erratic behavior when dynamically adding images

I am trying to create some kind of image gallery where images are loaded in the background and dynamically added to the gridView when they finish loading. Image loading works well enough, but the gridView scrolling behavior will not work properly if the images inside the gridView are larger than the screen height.

For testing purposes, I upload 15 dummy images, aligend in two columns. After loading all the images, the height of the gridView corresponds to the height of its content (8 images or rows in the left column) according to the scrollBar on the right. But if I try to scroll the 4th row element to get to the bottom of the view (line 5/6/7/8), scrollBar indicates that the height of the gridView has changed and the bottom of the view is reached. Scrolling past the 4th line is not possible. If I scroll the page again, the gridView seems to contain 8 rows again.

same gridView with different content size

Left view : gridView seems to contain 15 images. Right view : gridView seems to contain only 8 images

, ExpandableHeightViewGrid, , . gridView (, listView), , 15 , .

:

photo_gallery.xml

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

    <!-- This is basically a HorizontalScrollView where i add some buttons -->
    <com.my.HorizontalButtonScrollList
        android:id="@+id/horizontalButtonScrollList"
        android:layout_width="match_parent"
        android:layout_height="50dip">
    </com.my.HorizontalButtonScrollList>

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipeRefreshLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <GridView
            android:id="@+id/gridView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:columnWidth="100dp"
            android:numColumns="2"
            android:verticalSpacing="0dp"
            android:horizontalSpacing="0dp"
            android:stretchMode="columnWidth"
            android:gravity="center"
            android:scrollbars="vertical">
        </GridView>

    </android.support.v4.widget.SwipeRefreshLayout>

</LinearLayout>

PhotoGalleryActivity.java( )

public class PhotoGalleryActivity extends myBaseView {

    private GridView gridView;
    private PhotoGalleryImageAdapter imageAdapter;
    private PhotoGalleryModel[] photoGalleryModels;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.photo_gallery);
        gridView = (GridView) findViewById(R.id.gridView);

        loadImages();
    }

    void loadImages() {

        photoGalleryModels = PhotoGalleryModel.getFakeData();
        imageAdapter = new PhotoGalleryImageAdapter(this, photoGalleryModels);
        gridView.setAdapter(imageAdapter);
    }
}

PhotoGalleryImageAdapter ( )

public class PhotoGalleryImageAdapter extends BaseAdapter {

    private Context mContext;
    private PhotoGalleryModel[] photoGalleryModels;

    public PhotoGalleryImageAdapter(Context c, PhotoGalleryModel[] models){
        mContext = c;
        photoGalleryModels = models;
    }

    @Override
    public int getCount() { return photoGalleryModels.length; }

    @Override
    public Object getItem(int position) { return null; }

    @Override
    public long getItemId(int position) { return 0; }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        final ImageView imageView = new ImageView(mContext);    
        DownloadImageWithURL(photoGalleryModels[position].thumb_image_url, new MyHttpCallback() {
            @Override
            public void MyHttpCallback_OnSuccess(Object data, String responseString)
            {
                if(data instanceof Bitmap) {
                    imageView.setImageBitmap((Bitmap)data);
                }
            }

            @Override
            public void MyHttpCallback_OnError(String responseString, ErrorDataModel error)
            {}
        });

        convertView = imageView;    
        return convertView;
    }
}

, - gridView, .

+4
1

, , , . , gridView, , , LruCache ( Android- ), . gridView.

:

PhotoGalleryImageAdapter ( )

public class PhotoGalleryImageAdapter extends BaseAdapter {

    private Context mContext;
    private PhotoGalleryModel[] photoGalleryModels;
    private LruCache<String, Bitmap> mMemoryCache;

    public PhotoGalleryImageAdapter(Context c, PhotoGalleryModel[] models){
        mContext = c;
        photoGalleryModels = models;

        final int maxMemory = (int)(Runtime.getRuntime().maxMemory() / 1024);
        final int cacheSize = maxMemory / 8;

        mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
            @Override
        protected int sizeOf(String key, Bitmap bitmap) {
                return bitmap.getByteCount() / 1024;
            }
        };
    }

    @Override
    public int getCount() { return photoGalleryModels.length; }

    @Override
    public Object getItem(int position) { return null; }

    @Override
    public long getItemId(int position) { return 0; }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        final ImageView imageView = new ImageView(mContext);
        final String imageKey = photoGalleryModels[position].thumb_image_url;
        final Bitmap bitmapImage = mMemoryCache.get(imageKey);

        if (bitmapImage != null) {
            imageView.setImageBitmap(bitmapImage);
        }
        else {

            DownloadImageWithURL(photoGalleryModels[position].thumb_image_url, new MyHttpCallback() {
                @Override
                public void MyHttpCallback_OnSuccess(Object data, String responseString) {
                    if (data instanceof Bitmap) {
                        mMemoryCache.put(imageKey, (Bitmap)data);
                        imageView.setImageBitmap((Bitmap)data);
                    }
                }

                @Override
                public void MyHttpCallback_OnError(String responseString, ErrorDataModel error)
                {}
            });
        }

        convertView = imageView;
        return convertView;
    }

}

, gridView, , , , , . , imageView imageAdapter getView() . gridView , , - . , :)

UPDATE:

- . PhotoGalleryImageAdapter:

public View getView(int position, View convertView, ViewGroup parent) {

    final ImageView imageView;
       // set the imagge bounds if it is not loaded yet
    if (convertView == null) {
        imageView = new ImageView(mContext);
        imageView.setLayoutParams(new ViewGroup.LayoutParams(imageSize, imageSize));
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        imageView.setPadding(0, 0, 0, 0);
    }
    else {
        imageView = (ImageView) convertView;
    }

    final String imageKey = photoGalleryModels[position].thumb_image_url;
    final Bitmap bitmapImage = mMemoryCache.get(imageKey);

    if (bitmapImage != null) {
        imageView.setImageBitmap(bitmapImage);
    }
    else {
        imageView.setImageBitmap(emptyBitmap);
        DownloadImageWithURL(photoGalleryModels[position].thumb_image_url, new MyHttpCallback() {
            @Override
            public void MyHttpCallback_OnSuccess(Object data, String responseString) {
                    if (data instanceof Bitmap) {
                    mMemoryCache.put(imageKey, (Bitmap)data);
                    imageView.setImageBitmap((Bitmap)data);
                }
            }

            @Override
            public void MyHttpCallback_OnError(String responseString, ErrorDataModel error)
            {}
        });
    }
    convertView = imageView;
    return convertView;
}

, , .

gridView numColumns "auto_fit", / (100dp + stretchMode columnWidth) :

int imagesPerRow = screenSize.x / (int)(100 * mContext.getResources().getDisplayMetrics().density);
imageSize = screenSize.x / imagesPerRow;

imageView bitmapImage imageView ( ):

emptyBitmap = Bitmap.createBitmap(imageSize, imageSize, Bitmap.Config.ARGB_8888);

gridView , , LruCache . , , , , .

0

Source: https://habr.com/ru/post/1629214/


All Articles