it-swarm.dev

Jak obnovit GridView?

Mám GridView, který je docela podobný Google tutorial, kromě toho, že chci přidat ImageViews na runtime (přes subaktivitu). Výsledky jsou v pořádku, ale rozvržení pohledu je zkazené: GridView nevyplňuje obsah svého rodiče, co musím udělat, abych ho správně navrhl?

Zde je kód přidávání dětí:

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

aktivovatWorkbench, setDimension a měření v pracovním stole (LinearLayout nad 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);
}

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

Rozvržení 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>
29
Daniel

gridView má metodu invalidateViews (). 

když voláte tuto metodu: "všechny pohledy, které mají být znovu sestaveny a překresleny." http://developer.Android.com/reference/Android/widget/GridView.html

myslím, že to je to, co potřebujete :)

41
flyerz

Musíte nejprve říct adaptéru upozornit na změnu dat a nastavit adaptér znovu do mřížky

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

To může být užitečné. Po provedení vymazání na položce obnovuji zobrazení náhledu miniatur obrázků knih. Použití adapter.notifyDataChanged (); jak je uvedeno výše, nefungovalo pro mě, jak se to nazývá v mém adaptéru.

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

V podstatě jen znovu načíst adaptér a vázat ji na stejné zobrazení.

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

@flyerz @snagnever

Společně jste to dostali. To by mělo být:

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

To bude příznak adaptéru, že jeho data změnila, které budou potom šířeny do mřížky vždy po volání metody invalidateViews (). 

Jsem rád, že jsem našel tuto otázku, protože jsem nemohl přijít na to, jak přidat položky do mřížky poté, co byly vykresleny.

10
Hobo

Žádná z těchto odpovědí ve skutečnosti nepracovala pro mě a musela jsem všechny z nich rozmačkat. Chcete-li program GridView aktualizovat, musíte to provést takto:

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

Doufám, že to pomůže každému, kdo nemohl dostat další řešení do práce.

9
edwoollard

Neměli byste volat invalidateViews a setAdapter aktualizovat grid view. To není dobrý nápad, aby vaše grid view aktualizován, pokud aktualizujete tímto způsobem by stálo hodně času a paměti. 

Pokud máte možnost podívat se na metodu getView, uvidíte, že convertView je vytvořeno pouze jednou. Když zavoláte notifyDataChanged, aktualizuje toto zobrazení. Zatímco pokud zavoláte invalidateViews, budou vytvořená zobrazení znovu vytvořena. To není dobré řešení. 

Metoda getView se nazývá při volání notifyDataChanged. Metoda getView by tedy měla vypadat jako kód níže.

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;
}
5
aytek
adapter.notifyDataChanged();

nemusí fungovat jen proto, že data pro adaptér jsou zastaralá (pokud nebyla aktivita nebo fragment zničena a například seděla v zadním zásobníku).

Pokud tedy nejdříve obnovíte data, pak bude fungovat.

2
Andrey

Ve vašem adaptéru:

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
Gilberto Ibarra

Umístíte GridView uvnitř com.unimelb.pt3.ui.TransparentPanel, což je 10px tall.

  • Neměli byste px používat, měli byste použít dp.
  • Změnit com.unimelb.pt3.ui.TransparentPanel 's Android:layout_height="10px" na Android:layout_height="fill_parent"
0
Macarse