ListView getChildAt возвращает null для видимых детей

Я получаю странное поведение из метода listview/getChildAt.

У меня есть HashSet, iconsToUpdate, значков, которые были изменены в базе данных. Я хочу перебирать видимые строки, чтобы увидеть, нужно ли обновлять их значки, чтобы отображать новые значки. Мне не нужно проверять значки, которые в настоящее время не отображаются, поскольку они будут правильно нарисованы при визуализации.

Моя проблема в том, что getChildAt возвращает null, когда кажется, что он не должен. Я знаю, что 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 является последней видимой строкой, когда я находится в верхней части списка.

Любая информация о том, почему эти строки возвращаются как null, будет с благодарностью.

Спасибо!

Ответ 1

listView.getChildAt(i) работает там, где 0 - первая видимая строка, а (n-1) - последняя видимая строка (где n - количество видимых видов, которые вы видите).

Получите последний/первый видимый результат в позиции вашего адаптера dataAdapter. Итак, с тех пор, как вы начинаете с позиции 3, с тем, что выглядит как 6 видимых просмотров, что при получении для позиций 6-8 вы получаете нулевое значение.

В вашем примере getChildAt (0) вернет позицию 3. То, что я обычно делаю, это сохранить позицию в моих представлениях, чтобы затем я мог искать свой файл данных позже, если мне нужны значения.

Я думаю, что ваш цикл for должен выглядеть так:

for (int i = 0; i <= f_listView.getLastVisiblePosition() - f_listView.getFirstVisiblePosition(); i++) 

Надеюсь, что это поможет.

Ответ 2

Try

f_listView.getChildAt(positionOfChildYouWantGet - f_listView.getFirstVisiblePosition());

Ответ 3

Когда вы вызываете listView1.getLastVisiblePosition() и listView1.getFirstVisiblePosition(), listview возвращает позиции элементов, которые частично отображаются в списке. Например, первый элемент может быть наполовину видимым, и последний элемент может быть наполовину видимым. В этом случае, даже если вы видите часть элемента в списке, адаптер еще не вызвал функцию getView() для элемента, и поэтому элемент по-прежнему считается нулевым.

Ответ 4

В моем случае у меня есть 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));
        }

(когда я выбрал следующий элемент и прокрутку, он работает хорошо)

Ответ 5

Возможно, они частично видимы. Но когда getView() пытается переработать представления, они становятся полностью видимыми, другие принимают их как null. например, если вы прокручиваете список, и верхний элемент частично виден, а нижняя часть частично видима, поэтому они являются нулями, но вы все еще видите их.

Ответ 6

Я пробовал когда-нибудь в OnListItemClickListener(), но терпел неудачу. Наконец, я внес некоторые изменения в свой адаптированный адаптер для listview. Здесь, в getView(), я применяю clickListener к элементу, который я часто добавлял в список. n выполняйте все необходимые функции. Вот мой код, где я добавляю Image View в список n, так что применяйте прослушиватель к просмотру изображения.

Думаю, это поможет тем, кто хочет изменить цвет, когда выбран определенный элемент списка. Пойдите для этого..

В getView() настраиваемого адаптера // ---------------------------------код-------------- ----------------------------

Контекст LayoutInflater inflater = (LayoutInflater)               .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; } });

Ответ 7

Разве это не потому, что вы говорите

f_listView.getChildAt(i) 

И вы должны получать элемент в этой позиции?

f_listView.getItemAtPosition(i)