Как обновить GridView? - PullRequest
       7

Как обновить GridView?

30 голосов
/ 14 декабря 2010

У меня есть GridView, который очень похож на учебник Google, за исключением того, что я хочу добавить ImageViews во время выполнения (через подчиненную активность).С результатами все в порядке, но компоновка View испорчена: GridView не заполняет содержимое своего родителя, что мне нужно сделать, чтобы правильно его спроектировать?

Вот код добавлениядети:

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());
    }
}

activWorkbench, setDimension и measure в рабочей среде (LinearLayout над GridView):

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>

Ответы [ 9 ]

42 голосов
/ 08 января 2011

GridView имеет метод invalidateViews ().

при вызове этого метода: «все представления должны быть перестроены и перерисованы». http://developer.android.com/reference/android/widget/GridView.html

Я думаю, это то, что вам нужно:)

34 голосов
/ 23 июня 2011

Вы должны сначала сказать адаптеру уведомить, что данные изменились, и снова установить адаптер в сетку

adapter.notifyDataChanged();
grid.setAdapter(adapter);
18 голосов
/ 29 декабря 2011

Это может быть полезно.Я обновляю сетку просмотра миниатюр изображений книг после того, как выполняется удаление элемента.Использование 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);
10 голосов
/ 18 июля 2011

@ flyerz @ snagnever

Вместе вы, ребята, получили это. Должно быть:

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

Это пометит адаптеру, что его данные были изменены, которые затем будут распространяться в сетку всякий раз, когда вызывается метод invalidateViews ().

Рад, что нашел этот вопрос, потому что я не мог понять, как добавить элементы в сетку после ее рендеринга.

9 голосов
/ 17 сентября 2013

Ни один из этих ответов на самом деле не работал для меня, и мне пришлось смешать их все вместе. Чтобы фактически обновить GridView, вам нужно сделать следующее:

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

Надеюсь, это поможет любому, кто не сможет заставить работать другие решения.

5 голосов
/ 01 июля 2015

Вам не следует звонить invalidateViews и setAdapter, чтобы обновить grid view. Не стоит обновлять grid view, если вы обновляете его таким образом, это потребует много времени и памяти.

Если у вас есть возможность взглянуть на метод getView, вы увидите, что convertView создается только один раз. Когда вы звоните notifyDataChanged, он обновит это представление. Принимая во внимание, что если вы позвоните invalidateViews, ранее созданные представления будут воссозданы. Это не хорошее решение.

Ваш метод getView вызывается при вызове notifyDataChanged. Поэтому ваш метод 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;
}
2 голосов
/ 11 апреля 2015
adapter.notifyDataChanged();

может не работать только потому, что данные для адаптера устарели (например, если активность или фрагмент не были уничтожены и находились в заднем стеке).

Итак, если сначала обновите данные,потом после того как будет работать.

0 голосов
/ 28 февраля 2015

В вашем адаптере:

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();
0 голосов
/ 14 декабря 2010

Вы помещаете GridView внутри com.unimelb.pt3.ui.TransparentPanel, который 10px высотой.

  • Вы не должны использовать px, вы должны использовать dp.
  • Изменить com.unimelb.pt3.ui.TransparentPanel android:layout_height="10px" на android:layout_height="fill_parent"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...