这是我的Gallery的适配器,我在其上显示ImageViews(页面的拇指)
我想加载图像ASync(有时这可能来自网络),所以我做了那个代码:
public View getView(int position, View convertView, ViewGroup parent) {
final ImageView image = convertView != null ? convertView : new ImageView(getContext());
final PageInfo page = getItem(position);
image.setBackgroundColor(Color.WHITE);
image.setLayoutParams(new Gallery.LayoutParams(96, 170));
new AsyncTask<Void, Void, Bitmap>() {
@Override
protected Bitmap doInBackground(Void... arg0) {
try {
File thumbnail = page.thumbnail();//Thumbnail download the image if not available
return BitmapFactory.decodeStream(new FileInputStream(thumbnail));
} catch (ApplicationException e) {
return null;
} catch (NetworkException e) {
return null;
}
}
protected void onPostExecute(Bitmap result) {
if (result == null)
return;
image.setImageBitmap(result);
};
}.executeOnExecutor(executor);
return image;
}
这样可行,但是如果我拖动画廊的视图(当切换到真正的Bitmap时)会“跳”到厨房内的另一个位置,这会让它变得怪异。
我该如何避免?或者我可以在不请求ViewGroup布局的情况下更改ImageView的图像吗?
编辑:关于Google开发群体的类似问题 http://code.google.com/p/android/issues/detail?id=15526
答案 0 :(得分:4)
Gallery小部件有一个已知错误,导致它始终返回null convertView。这意味着每次调用getView时,您都会创建一个新的ImageView,这可能会导致您看到的问题。
第三方创建了修复回收错误的图库,在线搜索EcoGallery,您可以找到如何实现它。当您滚动图库时,它会显着提高图形性能。
答案 1 :(得分:3)
如果你没有让它正常工作,我曾经做过一个可能会有帮助的黑客。
在doInBackground()
结束时,就在您返回之前,请执行:
int viewsOnScreen = 3;
while(viewsOnScreen >= 1){ //adapt the numbers so that they work with your gallery, this is for a gallery with one visible child.
viewsOnScreen = getLastVisiblePosition() - getFirstVisiblePosition();
SystemClock.sleep(100);
}
这将等待更新您的图片,直到您只显示一个视图(或您指定的任何数字,关键是您没有在屏幕上有任何部分视图),导致& #39;跳&#39;没有注意到。如果您的问题还涉及跳转到图库中完全不同的位置,我建议您在加载之前检查您选择了哪个对象,并在加载后找到该对象所处的位置,并将setSelection()
调用到该位置。
但首先尝试所有其他解决方案 ...
答案 2 :(得分:2)
如果你还没有找到解决方案,那么就是我的。
您需要CustomGallery,它几乎是1:1的默认Android图库。但是你不能扩展Gallery,你必须将整个源代码复制到你的班级。您需要对CustomAbsSpinner和CustomAdapterView类执行相同的操作。所有这些只改变一行代码...... 在CustomGallery类中,将onLayout()方法更改为:
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
/*
* Remember that we are in layout to prevent more layout request from
* being generated.
*/
mInLayout = true;
/*
* Add if condition to avoid calling layout() unnecessarily:
* -when children calls onLayout after loading imageview
*/
if(changed || mDataChanged)
layout(0, false);
mInLayout = false;
}
这将导致layout()
仅在实际需要时被调用。
图库行为中还有另一个已知错误,导致notifyDataSetChanged()
上的图库跳转。如果您遇到此错误,只需在CustomAdapterView类中注释掉一行:
@Override
public void onChanged() {
mDataChanged = true;
mOldItemCount = mItemCount;
mItemCount = getAdapter().getCount();
// Detect the case where a cursor that was previously invalidated has
// been repopulated with new data.
if (CustomAdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
&& mOldItemCount == 0 && mItemCount > 0) {
CustomAdapterView.this.onRestoreInstanceState(mInstanceState);
mInstanceState = null;
} else {
rememberSyncState();
}
checkFocus();
//comment this line to avoid gallery snap on notyfiDataSetChanged
//requestLayout();
}
无论如何,好主题马科斯!谢谢带领我找到解决方案。 如果您需要自定义类的来源,请告诉我。
编辑(由Marcos Vasconcelos撰写):为了获得这些类的R修复,需要复制一些样式的东西。
对于那些正在搜索Android 2.2源代码的人(没有res文件夹,如果有人发现它请通知我们),可以在这里找到: http://en.newinstance.it/2010/12/01/android-sdk-2-2_r2-sources/
对于更新版本的API,这可以通过SDK Manager完成,并将位于/ sources / android -
答案 3 :(得分:1)
如果你(a)滚动得非常慢,或者(b)不回收convertView,那么它是否有用?
我会走出困境并猜测它确实......
原因是当您从之前的getItem()调用中回收ImageView时,您没有取消关联的AsyncTask。您将有多个任务更新相同的ImageView,这可能是您描述的行为。
答案 4 :(得分:1)
你可以使用LazyList的概念,它从互联网上获取图像并暂时放入本地缓存中,间接导致Gallery中的图像保存为本地保存的图像
这是链接https://github.com/thest1/LazyList或http://androidsnips.blogspot.com/2010/08/lazy-loading-of-images-in-list-view-in.html
答案 5 :(得分:0)
您可以在开始下载实际图像之前设置默认位图。这将确保空视图不会被错误的位图设置。
// load defaultBmp in constructor.
image.setBackgroundColor(Color.WHITE);
image.setLayoutParams(new Gallery.LayoutParams(96, 170));
image.setImageBitmap(defaultBmp); // set the default bitmap (could be white).
// execute AsyncTask here.