Android上的GridView滚动问题

这一定是非常简单的,我忽略了,但是我有以下的问题(post比较冗长,但是我想提供尽可能多的信息:))。

我有一个在我的Android应用程序中的每个单元格持有自定义视图的GridView:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <GridView android:id = "@+id/photosGridView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:clickable="true" android:drawSelectorOnTop="true" android:focusable="true" android:focusableInTouchMode="true" android:numColumns="6" android:columnWidth="90dp" android:verticalSpacing="5dp" android:horizontalSpacing="5dp" android:stretchMode="columnWidth" > </GridView> </RelativeLayout> 

每个细胞都是

 <?xml version="1.0" encoding="utf-8"?> <com.myapp.widgets.ImageThumbView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background = "@android:color/transparent" android:paddingLeft = "1dip" android:paddingRight = "1dip" android:paddingTop = "2dip" android:paddingBottom = "2dip" > <ImageView android:id="@+id/thumbImage" android:layout_width="fill_parent" android:layout_height = "fill_parent" android:src="@drawable/icon_small" /> <RelativeLayout android:layout_width="fill_parent" android:layout_height = "fill_parent" android:background = "@android:color/transparent" > <ImageView android:id="@+id/iconRight" android:layout_width="40px" android:layout_height = "40px" android:src="@drawable/album_check" android:visibility="gone" android:layout_alignParentTop = "true" android:layout_alignParentRight = "true" /> <ImageView android:id="@+id/iconLeft" android:src="@drawable/album_check" android:visibility="gone" android:layout_width = "40px" android:layout_height="40px" android:layout_alignParentTop = "true" android:layout_alignParentLeft = "true" /> </RelativeLayout> </com.myapp.widgets.ImageThumbView> 

我的适配器看起来像这样:

 public class ImageAdapter extends BaseAdapter { private List<String> mPictures = null; public ImageAdapter(List<String> pictures) { mPictures = pictures; } public int getCount() { return mPictures != null ? mPictures.size() : 0; } public Object getItem(int position) { return mPictures != null ? mPictures.get(position) : null; } public long getItemId(int position) { return mPictures != null ? position : -1; } @Override public View getView(int position,View convertView,ViewGroup parent) { ImageThumbView i = null; try { Thread.sleep(100); if (convertView == null) { String path = mPictures.get(position); Log.d(((Integer)position).toString(), path); i = addSingleView(_li, path); TextView idx = (TextView) i.findViewById(R.id.caption); if (idx != null) idx.setText(((Integer)position).toString()); } else { Log.d(((Integer)position).toString(), "ALREADY NOT NULL"); i = (ImageThumbView) convertView; // These 2 lines were added only in desperate attempt to get it working, but it makes no difference String path = mPictures.get(position); i.updateView(path); } } catch(InterruptedException ie) { ie.printStackTrace(); } return i; } } 

所以最初它工作正常,即它显示前18个图像,从下一行几个像素。 但是当我开始滚动gridvew时,图像开始随机出现,也就是最后一个图像从头开始几乎看不见,等等。 出于好奇,我已经尝试了这样一些样本: http : //androidsamples.blogspot.com/2009/06/how-to-display-thumbnails-of-images.html …并看到相同的结果。

那么,我做错了什么? 为什么GridView显示更多的项目比它应该做的? 为什么项目出现在错误的位置?

BR,Alex

Solutions Collecting From Web of "Android上的GridView滚动问题"

其实这里的问题是你在if或else中设置“convertView”的内容。 或者,在实例化视图之后,如果它是空的,则应该始终这样做,并在返回视图之前仅设置内容。

因此,您确定视图的内容总是正确的,使用位置进行更新,而不是错误的回收视图。

所以你一般应该这样做:
(基于Android Guide的教程)

 public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView; if (convertView == null) { imageView = new ImageView(mContext); //just creating the view if not already present } else { imageView = (ImageView) convertView; //re-using if already here } //here is the tricky part : set the content of the view out of the if, else //just before returning the view imageView.setImageResource(mThumbIds[position]); return imageView; } 

答案是查看回收。

一般来说,你的getView应该总是这样的forms:

 public class ImageAdapter extends BaseAdapter { private List<String> mUrls; // put your urls here private Map<String, Drawable> mImages; // cache your images here public ImageAdapter() { ... mUrls = new ArrayList<String>(); mImages = new HashMap<String, Drawable>(); } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; // Use the ViewHolder pattern for efficiency if (convertView == null) { // first time this view has been created so inflate our layout convertView = View.inflate(this, R.layout.my_grid_item, null); holder = new ViewHolder(); holder.image = convertView.findViewById(R.id.image); holder.text = convertView.findViewById(R.id.text); convertView.setTag(holder); // set the View holder } else { holder = (ViewHolder) convertView.getTag(); } // update the current view - this must be done EVERY // time getView is called due to view recycling holder.text.setText(Integer.toString(position)); // check our cache for the downloaded image final String url = mUrls.get(position); if (mImages.get(url) != null) holder.image.setImageDrawable(mImages.get(url)); else loadImage(url, holder.image); // return our view return convertView; } public loadImage(final String url, final ImageView image) { // load an image (maybe do this using an AsyncTask // if you're loading from network } ... } 

你的ViewHolder类看起来像什么

 public class ViewHolder { ImageView thumbImage; TextView text; } 

那么你不应该遇到任何问题。 此外,我不知道为什么你需要睡在你的getView? 这会减慢你的GridView的滚动速度。

使用标准的Lazy Loader获取图像,但从不更新onpostexecute,这会导致图像更新速度过快,并获得您不想要的随机性。

我甚至使用了代码:

 if (result != null && !mFlinging && myPosition < 12) { imageView.setImageBitmap(result); } 

int onpostexecute然后会更新图像正确的第一个屏幕,但如果你扔图像屏幕然后回来太快到第一个屏幕再次获得随机性,所以我现在使用:

 mPhotoView.setOnScrollListener(new OnScrollListener() { public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // TODO Auto-generated method stub } public void onScrollStateChanged(AbsListView view, int scrollState) { // TODO Auto-generated method stub if(scrollState != SCROLL_STATE_IDLE) { mAdapter.setFlinging(true); } else { mAdapter.setFlinging(false); } int first = view.getFirstVisiblePosition(); int count = view.getChildCount(); if (scrollState == SCROLL_STATE_IDLE || (first + count > mAdapter.getCount()) ) { mPhotoView.invalidateViews(); } } }); 

更新视图。

我遇到了同样的问题。 我正朝着在后台渲染视图的方向前进。

我正在学习这些代码,如果应该帮助:

http://blog.tomgibara.com/post/7665158012/android-adapter-view-rendering

https://github.com/desertjim/LazyLoadingGridView

大家避免这个问题总是返回新创build的对象在getView()

 public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView; TextView textView; LinearLayout linearlayout = new LinearLayout(mContext); //if (convertView == null) { imageView = new ImageView(mContext); textView = new TextView(mContext); //imageView.setLayoutParams(new GridView.LayoutParams(85, 85)); imageView.setAdjustViewBounds(false); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); imageView.setPadding(4, 8, 8, 8); imageView.setBackgroundResource(mThumbIds[position]); textView.setText(mThumbText[position]); textView.setGravity(0x01); textView.setMaxLines(2); //textView.setPadding(20, 0, 0, 0); linearlayout.addView(imageView,0); linearlayout.addView(textView,1); linearlayout.setPadding(4, 4, 4, 4); linearlayout.setOrientation(LinearLayout.VERTICAL); linearlayout.setGravity(0x01); // } else { //linearlayout = (LinearLayout) convertView; //} return linearlayout; }