Почему мой значок FectedTextView поднимается на разные элементы в моей GridView?
-
27-10-2019 - |
Вопрос
у меня есть GridView
чьи элементы основаны на FrameLayout
содержащий ImageView
и CheckedTextView
. Анкет XML -файл для Framelayout выглядит следующим образом:
<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);
Так что с этого момента может произойти две вещи:
1) Допустим, я выбрал элемент в позиции 0, CheckedTextView становится видимым, но когда я прокручиваю вниз по своей Gridview, еще один элемент (например, позиция 17) имеет свой проверенный текст. Это продолжается на случайных элементах, когда я прокручиваю вниз к дну.
2) Если я выберу элемент внизу, прокрутите обратно вверх и запустите один из методов, чтобы сделать все невидимые. NullPointerException
брошен для элемента внизу. Это происходит на данный момент: View selected =gridView.getChildAt(position);
где выбран становится нулевым.
Что тут происходит? Почему эти случайные проверки текста становятся видимыми, и почему я получаю исключения?
Решение
Проблемы заключаются в том, как вы отслеживаете проверенные элементы:
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
Сохраняет представление о детских предметах для адаптеров, которые он в настоящее время отображает. У него могут быть только дети для детей с 4 по 23, если элементы от 0 до 3 были прокручены из вершины ранее.
Вот почему вы получаете исключения, когда делаете View selected =gridView.getChildAt(position);
Представление на эту позицию на самом деле не существует, когда она вне экрана, поэтому getChildAt
возврат null
.
2) Когда 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
Метод исправьте проверенные состояния должным образом.