Frage

Ich habe ein GridView deren Elemente auf a basieren FrameLayout enthält eine ImageView und ein CheckedTextView.Die XML-Datei für das FrameLayout lautet wie folgt:

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

BEARBEITEN:Das ist der Adapter getView() Methode, die ich für jedes Element verwende:

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

In meiner Aktivitätsklasse lade ich ein Kontextmenü und sobald ich eine Option auswähle, mache ich das CheckedTextView dafür sichtbar GridView Element wie folgt:

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

Von diesem Punkt an können also möglicherweise zwei Dinge passieren:

1) Nehmen wir an, ich habe das Element an Position 0 ausgewählt, die CheckedTextView wird sichtbar, aber wenn ich in meiner GridView nach unten scrolle, wird ein anderes Element (z. B.Position 17) hat auch seine CheckedTextView sichtbar.Dies setzt sich bei zufälligen Elementen fort, während ich nach unten scrolle.

2) Wenn ich ein Element unten auswähle, scrolle zurück nach oben und führe eine der Methoden aus, um alle CheckedTextViews unsichtbar zu machen, a NullPointerException wird für das Element unten geworfen.Das passiert an dieser Stelle: View selected =gridView.getChildAt(position); wo ausgewählt wird null.

Was ist denn hier los?Warum werden diese zufälligen CheckedTextViews sichtbar und warum erhalte ich Ausnahmen?

War es hilfreich?

Lösung

Die Probleme liegen in der Art und Weise, wie Sie überprüfte Artikel verfolgen:

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 erhalten Sie nicht die richtige Ansicht, wenn Sie in den Inhalt gescrollt haben und nach Adapterposition indizieren.Beim Verweisen auf eine aktive Ansicht in a GridView oder ListView Sie möchten so etwas tun:

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

Der Grund ist, dass Ihr GridView Behält nur untergeordnete Ansichten für Adapterelemente bei, die gerade angezeigt werden.Es darf nur dann untergeordnete Ansichten für die Elemente 4 bis 23 geben, wenn die Elemente 0 bis 3 zuvor von oben gescrollt wurden.

Aus diesem Grund erhalten Sie in diesem Fall Ausnahmen View selected =gridView.getChildAt(position); Eine Ansicht für diese Position ist also nicht wirklich vorhanden, wenn sie sich außerhalb des Bildschirms befindet getChildAt kehrt zurück null.

2) Wenn a ListView oder GridView Wenn sich der Inhalt ändert oder die untergeordneten Ansichten aus anderen Gründen neu gestaltet werden müssen, erfolgt dies durch erneutes Binden vorhandener Ansichten mithilfe von convertView Parameter für Ihren Adapter.Ihr Adapter passt niemals den geprüften Status Ihrer Artikelansichten an, sodass eine geprüfte Ansicht für einen Artikel wiederverwendet werden kann sollen später deaktiviert werden.

Um dieses Problem zu lösen, sollten Sie dafür sorgen, dass Ihr Datenmodell, das Ihr Adapter präsentiert, den geprüften Status Ihrer Artikel verfolgt, anstatt sich dabei auf die Artikelansichten zu verlassen.Das bedeutet, dass Ihr Adapter immer den geprüften Status des Artikels überprüfen/einstellen sollte getView.Es könnte etwa so aussehen:

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

Wenn dann Ihre Option ausgewählt ist, die den aktivierten Status eines Elements ändern soll, führen Sie anstelle des obigen Codeausschnitts etwas aus wie:

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

notifyDataSetChanged() Werde es dem erzählen GridView dass es die Artikelansichten neu binden sollte, die Ihre haben werden getView Die Methode korrigiert die überprüften Zustände ordnungsgemäß.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top