Как я могу получить позицию элемента в списке, когда я нажимаю на конкретное представление?

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

Предположим, у меня есть следующий код в методе getView () из ArrayAdapter:

... holder = new ViewHolder (); holder.iconAction = (ImageView)convertView.findViewById (R.id.download_item_iconAction); holder.iconAction.setOnClickListener (new View.OnClickListener(){ @Override public void onClick (View v){ //Item X is clicked } }); ... 

Внутри onClick () я знаю точку зрения, которая нажата, v, но я не знаю позицию элемента.

Давайте сделаем трюк. Я собираюсь сохранить позицию в ViewHolder, когда getView () создает представление:

 public View getView (int position, View convertView, ViewGroup parent){ ViewHolder holder; if (convertView == null){ holder = new ViewHolder (); holder.iconAction = (ImageView)convertView.findViewById (id); holder.iconAction.setOnClickListener (new View.OnClickListener(){ @Override public void onClick (View v){ int pos = (Integer)v.getTag (); } }); holder.iconWait.setTag (position); ... }else{ holder = (ViewHolder)convertView.getTag (); } ... } 

Этот код работает … но не всегда. Если вам нужно прокрутить список, чтобы просмотреть все элементы, которые просматриваются в режиме просмотра. Предположим, что список имеет 10 элементов и только 5 видимых (видимое означает: если мы видим 1 пиксельную строку элемента, то этот элемент виден). Теперь, если мы прокрутим вниз, мы увидим шестой элемент, но первый (0) все еще будет виден. Мы прокручиваем еще немного, и первый элемент будет скрыт, и мы увидим, что появится седьмой элемент, но вид этого нового элемента – это вид первого элемента (0).
Поэтому я сохраняю позиции: 0, 1, 2, 3, 4 и 5. Седьмой элемент (6) сохранит позицию 0: Неправильно.

Другой способ получить обратный вызов щелчка – использовать ListView OnItemClickListener:

 listView = getListView (); listView.setOnItemClickListener (new AdapterView.OnItemClickListener(){ @Override public void onItemClick (AdapterView<?> parentView, View childView, int position, long id){ ... } }); 

Если я прокручиваю вниз, я получаю точную позицию, но таким образом я получаю обратные вызовы, когда элемент щелкнут, независимо от того, как щелкнул дочерний вид.

Благодарю.

Вы почти там, все, что вам нужно сделать, это установить тег после предложения if / else. Это делается для того, чтобы тег обновлялся при повторном просмотре представления, а также при создании из нового.

например

  if (convertView == null){ holder = new ViewHolder (); ... }else{ holder = (ViewHolder)convertView.getTag (); } holder.iconWait.setTag (position); 

Локальные анонимные классы могут ссылаться на конечные локальные переменные.

Сделайте position окончательной, изменив метод getView() образом:

 public View getView (final int position, View convertView, ViewGroup parent) { 

И тогда вы можете ссылаться на позицию внутри OnClickListener :

 holder.iconAction.setOnClickListener (new View.OnClickListener(){ @Override public void onClick (View v){ ... use position here ... } }); 

Ваш второй ответ (установка тега на элементе) будет работать нормально, если вы переместили holder.iconWait.setTag (position) вне инструкции if / then, то есть вы должны также установить тег на переработанные строки, а не только на Вновь завышенные.

Мне также нужно было добавить другие данные, чтобы перейти к onClick, и он также работал со строками.

 holder.iconWait.setTag ("String data here");