ListView getChildAt возвращает значение null для видимых дочерних элементов
Я получаю какое-то странное поведение от метода listview/getChildAt.
у меня есть HashSet, iconsToUpdate, значков, которые были изменены в базе данных. Я хочу перебрать видимые строки, чтобы увидеть, нужно ли обновлять какие-либо из их значков, чтобы отразить новые значки. Мне не нужно проверять значки, которые в настоящее время не отображаются, поскольку они будут правильно нарисованы при визуализации.
моя проблема заключается в том, что getChildAt возвращает null, когда кажется, что это не должно. I знайте, что getChildAt может возвращать только видимые в данный момент представления, но возвращает значение null для некоторых видимых строк.
вот мой код, который перебирает все строки:
Logger.debug("First visible index: " + f_listView.getFirstVisiblePosition());
Logger.debug("Last visible index: " + f_listView.getLastVisiblePosition());
for (int i = f_listView.getFirstVisiblePosition(); i <= f_listView.getLastVisiblePosition(); i++) {
String tag = "asdf"; // Remove when bug is fixed.
if (f_listView == null) {
Logger.debug("f_listView is null");
} else if (f_listView.getChildAt(i) == null) {
Logger.debug("Child at index " + i + " is null");
} else {
tag = (String) f_listView.getChildAt(i).getTag();
Logger.debug("Successful at index " + i + ", tag is: " + tag);
}
if (iconsToUpdate.contains(tag)) {
setIcon(i, f_aim.getInHouseIcon(tag));
}
}
вот журнал, соответствующий запуску этого цикла:
D/...: First visible index: 3
D/...: Last visible index: 8
D/...: Successful at index 3, tag is: ...
D/...: Successful at index 4, tag is: ...
D/...: Successful at index 5, tag is: ...
D/...: Child at index 6 is null
D/...: Child at index 7 is null
D/...: Child at index 8 is null
следует отметить, что первый и последний видимые индексы правильно сообщаются, так как я просматриваю строки 3-8, когда я запускаю это. Строки 6, 7, 8 отображаются правильно. Как они отображается, если они равны нулю?
кроме того, я не знаю, если это важно, но строка 5 является последней видимой строкой, когда я нахожусь в верхней части listview.
любая информация о том, почему эти строки возвращаются как null, будет очень признательна.
спасибо!
8 ответов:
listView.getChildAt (i) работает там, где 0-самая первая видимая строка и (n-1) - последняя видимая строка (где n-количество видимых представлений, которые вы видите).
get last / first visible возвращает позицию в адаптере данных, который у вас есть. Итак, вы начинаете с позиции 3, с тем, что выглядит как 6 видимых видов, вот когда get для позиций 6-8 вы получаете null.
в вашем примере getChildAt(0) вернет позицию 3. То, что я обычно делаю, это хранить позицию на моем представления, так что я могу искать на моем dataAdapter позже, если мне нужны значения.
Я думаю, что ваш цикл должен выглядеть так:
for (int i = 0; i <= f_listView.getLastVisiblePosition() - f_listView.getFirstVisiblePosition(); i++)надеюсь, что это помогает.
попробовать
f_listView.getChildAt(positionOfChildYouWantGet - f_listView.getFirstVisiblePosition());
когда вы называете
listView1.getLastVisiblePosition()иlistView1.getFirstVisiblePosition()наlistviewвозвращает позиции элементов, которые частично видны в ListView. Например, первый элемент может быть наполовину видимым, а последний элемент может быть наполовину видимым. В этом случае, даже если вы можете увидеть часть элемента в ListView, адаптер пока не называютgetView()функция для элемента, и поэтому элемент по-прежнему считается нулевым.
в моем случае у меня есть
listViewи первый элемент полностью виден, но когда я делаюgetFirstVisiblePosition()результат 1 !это становится более странным, когда я прокручиваю и делаю первый элемент наполовину видимым, а затем мой
getViewпоказать, чтоgetFirstVisiblePosition()равен 0.Это мой код :
public View getView(final int position, View convertView, final ViewGroup parent) { row = convertView; final AtomPaymentHolder holder = new AtomPaymentHolder(); LayoutInflater inflater = ((Activity) context).getLayoutInflater(); row = inflater.inflate(layoutResourceId, parent, false); row.setTag(items.get(position)); holder.songitem = items.get(position); final int firstPosition = MainActivity.listviewSong.getFirstVisiblePosition() - MainActivity.listviewSong.getHeaderViewsCount(); final int lastPosition = MainActivity.listviewSong.getLastVisiblePosition(); if(MusicService.indexService>= firstPosition && MusicService.indexService<= lastPosition){ MainActivity.listviewSong.getChildAt(MusicService.indexService-firstPosition).setBackgroundColor(getContext().getResources().getColor(R.color.pressed_color)); }(когда я выбрал следующий элемент и прокрутите, он работает хорошо)
возможно, они частично видны. Но когда getView () пытается переработать представления, он становится полностью видимым, другие принимают их как null. например, если вы прокручиваете список, и верхний элемент частично виден, а нижний частично виден, так что это нули, но вы все еще видите их.
Я пытался когда-либо иметь в виду в OnListItemClickListener(),но не удается. Наконец-то я внес некоторые изменения в мой настроенный адаптер для элемента управления ListView. Здесь, в getView (), я применяю clickListener к элементу, который я часто добавлял в список. а все необходимые функции есть. Вот мой код, где я добавляю представление изображения в список n, поэтому примените прослушиватель на imageview.
Я думаю, что это поможет тем, кто хочет изменить цвет, когда конкретный элемент списка >выбрать. идти за оно..
в getView () настроенного адаптера //---------------------------------код------------------------------------------
LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.icon_image_layout, parent, false); ImageView imageView = (ImageView) rowView.findViewById(R.id.Icon_ImageView); imageView.setClickable(true); final int pos=position; imageView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub // TODO Auto-generated method stub try{ if(previous_view!=null) previous_view.setBackgroundColor(Color.WHITE); }catch (Exception e) { System.out.println("Exception Occurs Previous View"); } v.setBackgroundColor(Color.RED); MainActivity.imageView.setImageResource(MainActivity.Image_Name[pos]); previous_view=v; return false; } });
Я знаю, что это очень старый пост. Но я отвечаю, потому что люди все еще ищут работу на ListView
getChildAt()исключение нулевого указателя.это связано с тем, что ArrayApdater удаляет и повторно использует представления, которые еще не видны в ListView из-за высоты. Так что если у вас есть 10 видов элементов, и ListView может отображать 4-5 в то время:
адаптер удалить вид элемента в позиции 5 до 9, так что любая попытка
adapter.getChildAt(5... to 9)будет вызвать исключение нулевого указателяадаптер также перерабатывает представление элемента, так что любая ссылка, сделанная на позиции 3, например, будет потеряна при прокрутке вниз до 5 до 9, а также любые входные данные, которые вы делаете на позиции 3 (EditText, Checkbox и т. д.) будет переработан при прокрутке вниз до 5 до 9 и будет повторно использоваться в другой позиции позже (например, позиция 1, 2 или 3 и т. д.) с тем же значением
единственный способ, который я нашел, чтобы контролировать это, чтобы забыть о получении представления и иметь:
атрибут
HashMap<Integer, ImageView> iconViewsили любой тип вы хотите для обработки значений, которые вы хотите использовать для каждого элемента в списке. Первый тип должен быть уникальным для элемента типаitem->getId()илиposition. Инициализируйте его с помощьюnew HashMap<>()в конструкторе; в getViews сделатьiconViews.put(position, iconView);Запретите адаптеру использовать переработанный convertView, удалите условиеif(convertView == null)так что адаптер всегда раздувает новый экземпляр представления. Поскольку экземпляр представления является новым каждый раз, вы должны установить значение из HashMap каждый время также нравится, если оно уже содержит ключif(iconViews.containsKey(position)){iconView = iconViews.get(position))};. Вероятно, в этом случае нет тонны элементов, так что плавная прокрутка не будет обязательной.и, наконец, создать общедоступные методы, чтобы получить значения за пределами адаптера передачи
item->getId()целое число в качестве параметра. Например:public ImageView getIconViewAt(int position) { return iconViews.get(position); }. Тогда будет легко выбрать элемент из адаптераПосмотреть больше от моего ответ.
разве это не потому, что вы говорите
f_listView.getChildAt(i)и вы должны получать элемент в этой позиции?
f_listView.getItemAtPosition(i)
Comments