Android: доступ до дитячих подань із ListView


108

Мені потрібно з'ясувати положення пікселя одного елемента у списку, який відображається за допомогою ListView. Здається, я повинен отримати один із TextView, а потім використовувати getTop(), але я не можу зрозуміти, як отримати уявлення про дитину ListView.

Оновлення: діти ViewGroupне відповідають 1-на-1 пунктам у списку, для а ListView. Натомість ViewGroupдітям відповідають лише ті погляди, які видно зараз. Таким чином, getChildAt()працює на індексі, який є внутрішнім ViewGroupі не обов'язково має нічого спільного з положенням у списку, який ListViewвикористовує.

Відповіді:


215

Дивіться: Android ListView: отримати індекс даних видимого предмета та поєднати з частиною відповіді Ноги вище, може дати вам щось на зразок:

int wantedPosition = 10; // Whatever position you're looking for
int firstPosition = listView.getFirstVisiblePosition() - listView.getHeaderViewsCount(); // This is the same as child #0
int wantedChild = wantedPosition - firstPosition;
// Say, first visible position is 8, you want position 10, wantedChild will now be 2
// So that means your view is child #2 in the ViewGroup:
if (wantedChild < 0 || wantedChild >= listView.getChildCount()) {
  Log.w(TAG, "Unable to get view for desired position, because it's not being displayed on screen.");
  return;
}
// Could also check if wantedPosition is between listView.getFirstVisiblePosition() and listView.getLastVisiblePosition() instead.
View wantedView = listView.getChildAt(wantedChild);

Перевага полягає в тому, що ви не повторюєте дітей на ListView, що може спричинити успіх у виконанні.


10
Чудова відповідь, але це не дуже добре, якщо у списку є перегляди заголовків. Завданням firstPositionмає бути int firstPosition = listView.getFirstVisiblePosition() - listView.getHeaderViewsCount();виправлення цього.
pospi

@pospi: спасибі, хороший момент! Я оновив свою відповідь, щоб повідомити про це.
Джо

Хороша відповідь і працює в більшості випадків, але я не розумію, чому ви вважаєте, що дитячі погляди відображаються в тому порядку, який вони є в масиві дитячих поглядів. Оскільки перегляди можна використовувати повторно, як ми можемо бути впевнені, що перший погляд не відображає останнього видимого подання?
Віктор Денисов

2
@VictorDenisov: це може статися лише в потоці інтерфейсу користувача; тому потік інтерфейсу буде заблокований під час виконання цього коду, таким чином, дочірні подання є нерухомими та не змінюватимуться. ListViewвже обробляє "переміщення" дочірніх поглядів після переробки старих convertViews тощо, тому ви можете гарантувати, що ListView.getChildAt(0) це фактично перший доданий вид від адаптера. Він може бути не повністю видимим (а може і зовсім не видно, залежно від ListViewпорогу "видимості" перед переробкою подання, яке він вважає "прокрученим з виду")
Джо

1
@Matheus так не працює Android ListView. Якщо елемент списку поза екраном, його перегляд уже перероблено та використано для одного з інших елементів списку, які знаходяться на екрані. Вам слід переосмислити, як ви використовуєте ListView, якщо це вимога.
Джо

17

Цей код простіший у використанні:

 View rowView = listView.getChildAt(viewIndex);//The item number in the List View
    if(rowView != null)
        {
           // Your code here
        }

9
працює не завжди. getChildAt рахується з першого видимого рядка, а не з верхньої частини даних.
SteelBytes

13
Аргумент ViewID заплутаний. Це індекс (або позиція). Ідентифікатор подання - це цілком довільне ціле число, породжене інструментом aapt.
Йохан Пелгрім

6

Швидкий пошук документів для класу ListView виявив методи getChildCount () та getChildAt (), успадковані від ViewGroup. Чи можете ви повторити їх за допомогою цих? Я не впевнений, але варто спробувати.

Знайшов його тут


1
Я спробував це, роблячи вибір. Зазвичай працює, але іноді трапляються поодинокі помилки, і це не є надійним. Я б не рекомендував це.
Timmmm

Дякую Тімммм, я насправді не пробував, просто знайшов його в документах.
Ноги

5
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, final View view, int position, long id) {
        View v;
        int count = parent.getChildCount();
        v = parent.getChildAt(position);
        parent.requestChildFocus(v, view);
        v.setBackground(res.getDrawable(R.drawable.transparent_button));
        for (int i = 0; i < count; i++) {
            if (i != position) {
                v = parent.getChildAt(i);
                v.setBackground(res.getDrawable(R.drawable.not_clicked));
            }
        }
    }
});

В основному створіть два малюнки - один, який є прозорим, а інший - потрібного кольору. Попросіть фокус у позиції, що натиснув ( int positionяк визначено), і змініть колір зазначеного рядка. Потім пройдіться по батькові ListViewта змініть всі інші рядки відповідно. Це пояснюється, коли користувач listviewдекілька разів клацає . Це робиться за допомогою власної розкладки для кожного рядка в полі ListView. (Дуже просто, просто створіть новий файл макета за допомогою TextView- не встановлюйте фокусируемость або натискання!).

Не потрібний спеціальний адаптер - використовуйте ArrayAdapter


getChildAt відносно поточних прокручених елементів. Це припинить роботу, якщо ви прокрутите список лише трохи.
Нуреттін


-9

Це передбачає, що ви знаєте положення елемента в ListView:

  View element = listView.getListAdapter().getView(position, null, null);

Тоді ви повинні мати можливість викликати getLeft () та getTop () для визначення елементів на екрані.


43
getView()викликається внутрішньо ListView при заповненні списку. Не слід використовувати його для отримання представлення даних у цій позиції у списку, оскільки виклик getView()з null convertViewвикликає те, що адаптер надуває новий вид з ресурсу компонування адаптера (не отримує представлення, яке вже відображається).
Джо

1
Рівне положення буде позицією на візуальному екрані, а не в позиції джерела даних адаптера.
Вікас

@jasonhudgins Це метод, яким я користувався, я вважав, що це найкраще, але коли я намагаюся зробити панель прогресу в дитячому поданні невидимою, але натомість це зробило всі смуги прогресу в listvew невидимими ........ все в всі прийняті відповіді зробили трюк
Edijae Crusar
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.