GridView滚动条:动态添加图片时表现不稳定

4
我正在尝试制作一种图像库,其中图像在后台加载,并在完成加载后动态添加到gridView中。 图像加载效果很好,但是如果gridView中的图像超过屏幕高度,则gridView的滚动行为无法按预期工作。
为测试目的,我加载了15个虚拟图像,分为两列对齐。 当所有图像加载完成后,似乎gridView的高度适合其内容高度(左列上有8个图像或行),根据右侧的滚动条。 但是,如果我尝试向下滚动以达到视图底部(第5/6/7/8行),则滚动条指示gridView的高度已更改并且已到达视图底部。 无法滚动到第4行之后。 如果我再次向上滚动,则gridView似乎又包含8行。

same gridView with different content size

左视图: gridView 似乎包含 15 张图片。 右视图: gridView 突然只包含 8 张图片。
我已经尝试过不同的方法,比如在 这里 提到的 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,这样我就可以像预期的那样滚动浏览所有加载的图片,我会非常高兴。


你尝试过将GridView的layout_height设置为match_parent吗? - Doug Stevenson
1
是的,但那也没有起作用 :-/ - Petzy Bär
1个回答

0

嗯,看来我通过忽略它自己解决了这个问题。在跳过修复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终于可以工作了,但是我不满意的是没有缓存图片它就不能正常工作。我应该在imageAdapter的getView()方法中设置imageView的边界,然后再加载图片。如果有人面临同样的问题,我会尝试修复gridView而不使用缓存,并更新我的答案。在那之前,我很高兴我成功让它工作 :)

更新:

我最终使它能够在有或没有缓存的情况下工作。这是我的更新后的PhotoGalleryImageAdapter:

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

    final ImageView imageView;
       // set the imagge's 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(在这里找到了代码here):
emptyBitmap = Bitmap.createBitmap(imageSize, imageSize, Bitmap.Config.ARGB_8888);

现在,无论是否使用LruCache,gridView都可以正常工作。我不知道回答自己的问题是否是一种常见做法,但这样做可能会帮助那些遇到类似问题的人。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接