Domanda

Ho un GridView i cui elementi si basano su a FrameLayout contenente un ImageView e a CheckedTextView. Il file XML per il framelayout è il seguente:

<FrameLayout
xmlns:android = "http://schemas.android.com/apk/res/android"
android:id="@+id/gridImage"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:gravity="center_horizontal">
<ImageView
android:id="@+id/image"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:adjustViewBounds="false">
</ImageView>
<CheckedTextView
android:id="@+id/imageTick"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:layout_gravity="center_horizontal|bottom"
android:checkMark="@drawable/icon"
android:checked="false"
android:visibility="invisible"
>
</CheckedTextView>
</FrameLayout>

EDIT: questo è l'adattatore getView() Metodo che uso per ogni elemento:

public View getView(int position, View convertView, ViewGroup parent) {
        Log.d("getView()", position+"");
        View v;
        ImageView imageView;
        if(convertView == null) {

            v = LayoutInflater.from(mContext).inflate(R.layout.photo_text_view, null);
            v.setLayoutParams(new GridView.LayoutParams(100,100));
        }
        else
        {
            v = convertView;

        }
        imageView = (ImageView) v.findViewById(R.id.image);
        imageView.setImageBitmap(mThumbsIds.get().get(position));

        v.setPadding(8, 8, 8, 8);
        return v;
    }

Nella mia classe di attività, carico un menu contestuale e una volta selezionato un'opzione faccio il CheckedTextView visibile per questo GridView elemento così:

GridView gridView = (GridView) findViewById(R.id.gridview);
    View selected =gridView.getChildAt(position);
    CheckedTextView selectedCheck = (CheckedTextView)selected.findViewById(R.id.imageTick);
    selectedCheck.setChecked(true);
    selectedCheck.setVisibility(View.VISIBLE);

Quindi due cose possono potenzialmente accadere da questo punto:

1) Diciamo che ho scelto l'elemento nella posizione 0, il controllo di TEXTVIEW diventa visibile, ma quando scorro verso il basso la mia gridview, un altro elemento (ad esempio posizione 17) ha anche il suo visibile Visible di controllo. Questo continua su elementi casuali mentre scorro verso il basso verso il basso.

2) Se scelgo un elemento verso il basso, scorri indietro verso la parte superiore ed eseguo uno dei metodi per rendere invisibile di tutti gli anni di controllo, a NullPointerException viene lanciato per l'elemento in basso. Questo accade a questo punto: View selected =gridView.getChildAt(position); dove selezionato diventa nullo.

Cosa sta succedendo qui? Perché questi casuali che controdtextView sono diventati visibili e perché ricevo eccezioni?

È stato utile?

Soluzione

I problemi si trovano nel modo in cui tieni traccia degli elementi controllati:

GridView gridView = (GridView) findViewById(R.id.gridview);
View selected =gridView.getChildAt(position);
CheckedTextView selectedCheck = (CheckedTextView)selected.findViewById(R.id.imageTick);
selectedCheck.setChecked(true);
selectedCheck.setVisibility(View.VISIBLE);

1) getChildAt Non ti darà la vista corretta se hai scorrere il contenuto e stai indicizzando la posizione dell'adattatore. Quando si fa riferimento a una vista attiva in a GridView o ListView Vuoi fare qualcosa del genere:

final int index = position - gridView.getFirstVisiblePosition();
View selected = gridView.getChildAt(index);

Il motivo è che il tuo GridView Mantiene solo le viste dei bambini per gli articoli dell'adattatore che sta attualmente visualizzando. Può avere una vista sui figli solo per gli elementi da 4 a 23 se gli elementi da 0 a 3 sono stati scorrelati dalla parte superiore in precedenza.

Questo è il motivo per cui stai ricevendo eccezioni quando lo fai View selected =gridView.getChildAt(position); Una vista per quella posizione non esiste effettivamente quando è fuori dallo schermo, quindi getChildAt ritorna null.

2) Quando a ListView o GridView ha il suo cambio di contenuto o altrimenti deve riorganizzare le opinioni dei suoi figli, lo fa ri-vincolando le viste esistenti usando il convertView parametro al tuo adattatore. Il tuo adattatore non regola mai lo stato controllato delle viste degli articoli, quindi una vista controllata può essere riutilizzata per un articolo che dovrebbe Sii incontrollato più tardi.

Per risolvere ciò dovresti avere il tuo modello di dati che l'adattatore presenta traccia lo stato controllato dei tuoi articoli piuttosto che fare affidamento sulle viste degli articoli per farlo. Ciò significa che il tuo adattatore dovrebbe sempre verificare/impostare lo stato controllato dell'articolo in getView. Può assomigliare a questo:

imageView = (ImageView) v.findViewById(R.id.image);
imageView.setImageBitmap(mThumbsIds.get().get(position));

CheckedTextView checkView = (CheckedTextView) v.findViewById(R.id.imageTick);

if (mData.isItemChecked(position)) {
    checkView.setChecked(true);
    checkView.setVisibility(View.VISIBLE);
} else {
    checkView.setVisibility(View.GONE);
}

Quindi quando viene selezionata l'opzione che dovrebbe modificare lo stato controllato di un elemento, anziché lo snippet di codice sopra, fai qualcosa di simile:

data.setItemChecked(position, true);
adapter.notifyDataSetChanged();

notifyDataSetChanged() lo dirà GridView che dovrebbe rinnovare le viste dell'oggetto, che avrà il tuo getView Metodo Correggi correttamente gli stati controllati.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top