我正在尝试制作某种图像库,其中图像在后台加载,并在完成加载后动态添加到gridView。图像加载效果很好,但如果gridView中的图像超出屏幕高度,gridView的滚动行为将无法正常工作。
出于测试目的,我正在加载15个虚拟图像,两列中的aligend。加载完所有图像后,根据右侧的scrollBar,gridView的高度似乎符合其内容高度(左侧列中的8个图像或行)。但是,如果我尝试滚动到第4行项目以到达视图的底部(第5/6/7/8行),则scrollBar指示gridView的高度已更改并且已到达视图的底部。滚过第4行是不可能的。如果我再次向上滚动,gridView似乎又包含8行。
左视图 :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(我简化了代码以提高可读性)
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以便能按预期滚动浏览所有已加载的图像,我将非常高兴。
答案 0 :(得分:0)
好吧,我似乎忽略了自己解决了这个问题。在我跳过修复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, 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现在都可以正常工作。我不知道一个人自己的问题是否是常见的做法,但这样做我认为它可以帮助那些面临类似问题的人。