如何刷新GridView?

我有一个非常类似于Google教程的GridView,只是我想在运行时添加ImageView(通过子活动)。 结果是好的,但视图的布局是乱七八糟的:GridView没有填充它的父母的内容,我该怎么做才能正确地devise它?

这里添加孩子的代码:

public void initializeWorkbench(GridView gv, Vector<String> items) { Prototype.workbench.setDimension(screenWidth, divider.height()+workbenchArea.height()); Prototype.workbench.activateWorkbench(); // this measures the workbench correctly Log.d(Prototype.TAG, "workbench width: "+Prototype.workbench.getMeasuredWidth()); // 320 Log.d(Prototype.TAG, "workbench height: "+Prototype.workbench.getMeasuredHeight()); // 30 ImageAdapter imgAdapter = new ImageAdapter(this.getContext(), items); gv.setAdapter(imgAdapter); gv.measure(screenWidth, screenHeight); gv.requestLayout(); gv.forceLayout(); Log.d(Prototype.TAG, "gv width: "+gv.getMeasuredWidth()); // 22 Log.d(Prototype.TAG, "gv height: "+gv.getMeasuredHeight()); // 119 Prototype.workbench.setDimension(screenWidth, divider.height()+workbenchArea.height()); } } 

在Workbench(GridView上方的LinearLayout)中的activateWorkbench,setDimension和measure:

 public void activateWorkbench() { if(this.equals(Prototype.workbench)) { this.setOrientation(VERTICAL); show = true; measure(); } } public void setDimension(int w, int h) { width = w; height = h; this.setLayoutParams(new LinearLayout.LayoutParams(width, height)); this.invalidate(); } private void measure() { if (this.getOrientation() == LinearLayout.VERTICAL) { int h = 0; int w = 0; this.measureChildren(0, 0); for (int i = 0; i < this.getChildCount(); i++) { View v = this.getChildAt(i); h += v.getMeasuredHeight(); w = (w < v.getMeasuredWidth()) ? v.getMeasuredWidth() : w; } if (this.equals(Prototype.tagarea)) height = (h < height) ? height : h; if (this.equals(Prototype.tagarea)) width = (w < width) ? width : w; } this.setMeasuredDimension(width, height); } 

ImageAdapter构造函数:

 public ImageAdapter(Context c, Vector<String> items) { mContext = c; boolean mExternalStorageAvailable = false; boolean mExternalStorageWriteable = false; String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state)) { // We can read and write the media mExternalStorageAvailable = mExternalStorageWriteable = true; } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { // We can only read the media mExternalStorageAvailable = true; mExternalStorageWriteable = false; } else { // Something else is wrong. It may be one of many other states, but // all we need // to know is we can neither read nor write mExternalStorageAvailable = mExternalStorageWriteable = false; } if (mExternalStorageAvailable && mExternalStorageWriteable) { for (String item : items) { File f = new File(item); if (f.exists()) { try { FileInputStream fis = new FileInputStream(f); Bitmap b = BitmapFactory.decodeStream(fis); bitmaps.add(b); files.add(f); } catch (FileNotFoundException e) { Log.e(Prototype.TAG, "", e); } } } } } 

和XML的布局:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:gravity="bottom" android:paddingLeft="0px" android:paddingTop="0px" android:paddingRight="0px"> <com.unimelb.pt3.ui.TransparentPanel android:id="@+id/workbench" android:layout_width="fill_parent" android:layout_height="10px" android:paddingTop="0px" android:paddingLeft="0px" android:paddingBottom="0px" android:paddingRight="0px"> <GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gridview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:columnWidth="90dp" android:numColumns="auto_fit" android:verticalSpacing="10dp" android:horizontalSpacing="10dp" android:stretchMode="columnWidth" android:gravity="center" /> </com.unimelb.pt3.ui.TransparentPanel> </LinearLayout> 

Solutions Collecting From Web of "如何刷新GridView?"

GridView有一个invalidateViews()方法。

当你调用这个方法时:“所有的视图都要重build和重绘”。 http://developer.android.com/reference/android/widget/GridView.html

我认为这是你需要的:)

您必须首先通知适配器通知数据已更改,然后再次将适配器设置为网格

 adapter.notifyDataChanged(); grid.setAdapter(adapter); 

这可能会有所帮助。 在对项目执行删除操作后,我刷新书籍图像缩略图的网格视图。 使用adapter.notifyDataChanged(); 如上所述,因为它在我的适配器中被调用,所以对我不起作用。

 //this is a call that retrieves cached data. //your constructor can be designed and used without it. final Object data = getLastNonConfigurationInstance(); 

我基本上只是重新加载适配器,并将其绑定到相同的观点。

 //reload the adapter adapter = new BooksAdapter(MyBooks.this, MyBooks.this, data, show_collection ); grid.invalidateViews(); grid.setAdapter(adapter); 

@flyerz @snagnever

你们一起得到了它。 它应该是:

 adapter.notifyDataChanged(); grid.invalidateViews(); 

这将标记适配器的数据已更改,然后在调用invalidateViews()方法之后,该适配器将传播到网格。

很高兴我发现这个问题,因为我不知道如何将项目添加到网格后,它已被呈现。

这些答案都没有为我工作,我不得不将所有这些都混合在一起。 要真正得到GridView更新,你需要这样做:

  adapter.notifyDataChanged(); grid.invalidateViews(); grid.setAdapter(adapter); 

希望这可以帮助那些无法获得其他解决scheme的人工作。

你不应该调用invalidateViewssetAdapter刷新你的grid view 。 这不是一个好主意,以保持您的grid view更新,如果你更新,这将花费大量的时间和内存。

如果您有机会查看getView方法,您将看到convertView只创build一次。 当你调用notifyDataChanged ,它会更新这个视图。 而如果你调用invalidateViews ,以前创build的视图将被重新创build。 这不是一个好的解决scheme。

当你调用notifyDataChanged时,你的getView方法被调用。 所以你的getView方法应该看起来像下面的代码。

 public List list; public class SimpleItemViewHolder extends Object { public TextView textView; public ImageView imageView; } public View getView(int position, View convertView, ViewGroup parent){ View itemView = convertView; SimpleItemViewHolder viewHolder; if(convertView==null) { viewHolder = (SimpleItemViewHolder)itemView.getTag(); }else{ LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); itemView = inflater.inflate(R.layout.layout_name, null); TextView labelField = (TextView) itemView.findViewById(R.id.label_field); labelField.setText(list.get(position).Name); //Typeface boldFont = Typeface.createFromAsset(context.getAssets(), "fonts/Font-Bold.ttf"); //labelField.setTypeface(boldFont); ImageView imageView = (ImageView) itemView.findViewById(R.id.image_view); //Bitmap bitmap = init your bitmap here; //imageView.setImageBitmap(bitmap); viewHolder = new SimpleItemViewHolder(); viewHolder.imageView = imageView; viewHolder.textView = labelField; itemView.setTag(viewHolder); } //don't create new views, instead use previous ones and update them. viewHolder.textView.setText(list.get(position).Name); //viewHolder.imageView.setImageBitmap(your_bitmap); return itemView; } 
 adapter.notifyDataChanged(); 

可能无法正常工作,因为适配器的数据是陈旧的(如果活动或片段未被销毁,并且已经坐在后台堆栈中)。

因此,如果首先刷新数据,那么它将工作。

您将GridView放在10px高的com.unimelb.pt3.ui.TransparentPanel中。

  • 你不应该使用px ,你应该使用dp
  • com.unimelb.pt3.ui.TransparentPanelandroid:layout_height="10px"更改为android:layout_height="fill_parent"

在你的适配器中:

 class MAdapter extends BaseAdapter{ List<Objects> mObjects; ... public void clearAdapter(){ mObjects.clear(); } public void addNewValues(List<Objects> mObjects){ this.mObjects = mObjects; } ... } adapter.clearAdapter(); // clear old values adapter.addNewValues(MObjects); adapter.notifyDataChanged();