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, будет очень признательна.



спасибо!

592   8  

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

    Ничего не найдено.