CheckedTextViewアイコンがGridViewのさまざまな要素にジャンプするのはなぜですか?
-
27-10-2019 - |
質問
私は持っています GridView
その要素はaに基づいています FrameLayout
を含む ImageView
そしてa CheckedTextView
. 。 FrameLayoutのXMLファイルは次のとおりです。
<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>
編集:これはアダプターのものです getView()
各要素に使用する方法:
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;
}
アクティビティクラスでは、コンテキストメニューをロードし、オプションを選択したら CheckedTextView
そのために見える GridView
そうするような要素:
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);
したがって、この時点から2つのことが発生する可能性があります。
1)位置0で要素を選択したとしましょう。CheckedTextViewが表示されますが、GridViewを下にスクロールすると、別の要素(位置17)にCheckedTextViewが表示されます。これは、底に向かって下にスクロールするときにランダムな要素で続きます。
2)下部に向かって要素を選択した場合は、上部に戻ってスクロールし、すべてのCheckedTextViewの目に見えないようにする方法の1つを実行します。 NullPointerException
下部の要素のために投げられます。これはこの時点で起こります: View selected =gridView.getChildAt(position);
選択した場所はnullになります。
何が起きてる?なぜこれらのランダムCheckedTextViewが表示されるのか、なぜ例外を取得するのですか?
解決
問題は、チェックされたアイテムを追跡する方法にあります。
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
コンテンツにスクロールしてアダプターの位置でインデックスを付けている場合、正しいビューは表示されません。でアクティブビューを参照する場合 GridView
また ListView
あなたはこのようなことをしたい:
final int index = position - gridView.getFirstVisiblePosition();
View selected = gridView.getChildAt(index);
その理由はあなたのものです GridView
現在表示されているアダプターアイテムの子供ビューのみを保持します。要素0〜3が以前に上部からスクロールされた場合、要素4〜23の子どもの視界のみがある場合があります。
これが、あなたがそうするとき、あなたが例外を取得している理由です View selected =gridView.getChildAt(position);
その位置のビューは、それが画面外のときに実際には存在しないので、したがって getChildAt
戻り値 null
.
2)a ListView
また GridView
コンテンツが変更されているか、それ以外の場合は子供のビューを再レイアウトする必要があります。 convertView
アダプターへのパラメーター。あなたのアダプターがあなたのアイテムビューのチェック状態を決して調整しないので、チェックされたビューを再利用することができます したほうがいい 後でチェックされていない。
これを解決するには、アダプターが提示するデータモデルを使用して、アイテムビューに頼るのではなく、アイテムのチェック状態を追跡する必要があります。これは、アダプターが常にアイテムのチェック状態を確認/設定する必要があることを意味します。 getView
. 。それは次のように見えるかもしれません:
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);
}
次に、オプションを選択したときに、上記のコードスニペットの代わりに、アイテムのチェック状態を変更する必要があります。
data.setItemChecked(position, true);
adapter.notifyDataSetChanged();
notifyDataSetChanged()
教えます GridView
アイテムビューを再バインドする必要があり、それはあなたを持っています getView
メソッドチェック状態を適切に修正します。