Подтвердить что ты не робот

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

У меня есть GridView, который очень похож на учебник Google, за исключением того, что я хочу добавить ImageViews во время выполнения (через subactivity). Результаты в порядке, но макет 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());
    }
}

activateWorkbench, setDimension и измерение в верстаке (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>
4b9b3361

Ответ 1

У GridView есть метод invalidateViews().

когда вы вызываете этот метод: "все виды, которые нужно перестроить и перерисовать". http://developer.android.com/reference/android/widget/GridView.html

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

Ответ 2

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

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

Ответ 3

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

Ответ 4

@flyerz @snagnever

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

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

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

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

Ответ 5

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

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

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

Ответ 6

Вы не должны звонить 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;
}

Ответ 7

adapter.notifyDataChanged();

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

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

Ответ 8

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

  • Вы не должны использовать px, вы должны использовать dp.
  • Измените com.unimelb.pt3.ui.TransparentPanel android:layout_height="10px" на android:layout_height="fill_parent"

Ответ 9

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

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