加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – GridView scrollBar:动态添加图像时的不稳定行为

发布时间:2020-12-15 02:13:14 所属栏目:Java 来源:网络整理
导读:我正在尝试制作某种图像库,其中图像在后台加载,并在完成加载后动态添加到gridView.图像加载效果很好,但如果gridView中的图像超出屏幕高度,则gridView的滚动行为将无法按预期工作. 出于测试目的,我正在加载15个虚拟图像,两列中的aligend.加载完所有图像后,根
我正在尝试制作某种图像库,其中图像在后台加载,并在完成加载后动态添加到gridView.图像加载效果很好,但如果gridView中的图像超出屏幕高度,则gridView的滚动行为将无法按预期工作.

出于测试目的,我正在加载15个虚拟图像,两列中的aligend.加载完所有图像后,根据右侧的scrollBar,gridView的高度似乎符合其内容高度(左侧列中的8个图像或行).但是,如果我尝试滚动到第4行项目以到达视图的底部(第5/6/7/8行),则scrollBar指示gridView的高度已更改并且已到达视图的底部.滚过第4行是不可能的.如果我再次向上滚动,gridView似乎再次包含8行.

same gridView with different content size

左视图:gridView似乎包含15个图像.
右视图:gridView突然似乎只包含8个图像

我已经尝试过使用不同的方法,如here提到的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 (I simplified the code for better readability)

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 (also simplified)

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之后,因为我不知道该怎么做,我实现了使用LruCache缓存图像(如Android开发人员的 training page所示)以节省一些内存.突然,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,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,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);
    }
    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,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现在都可以正常工作.我不知道对一个人自己的问题是否是常见做法,但在这样做时我认为它可以帮助那些面临类似问题的人.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读