Как я могу получить положение элемента в списке, когда я нажимаю на конкретный вид? - PullRequest
3 голосов
/ 04 марта 2011

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

Предположим, у меня есть следующий код в методе 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: неверно.

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

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

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

Спасибо.

Ответы [ 4 ]

7 голосов
/ 04 марта 2011

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

* 1003 например *

    if (convertView == null){
        holder = new ViewHolder ();
        ...
    }else{
        holder = (ViewHolder)convertView.getTag ();
    }
 holder.iconWait.setTag (position);
3 голосов
/ 04 марта 2011

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

Сделайте 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 ...
    }
});
0 голосов
/ 03 октября 2013

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

holder.iconWait.setTag ("String data here");
0 голосов
/ 04 марта 2011

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

...