Форум программистов, компьютерный форум, киберфорум
Наши страницы
Программирование Android
Войти
Регистрация
Восстановить пароль
 
arvalon
21 / 6 / 2
Регистрация: 26.10.2012
Сообщений: 192
Записей в блоге: 1
1

В чём разница между обработчиками нажатий RecyclerView через OnItemTouchListener и в адаптере?

19.04.2018, 17:00. Просмотров 356. Ответов 8

Доброго дня.
Существуют два способа написания обработчика кликов по элементам RecyclerView. Оба без проблем находятся в поисковиках. Итак, способ первый - написание своего RecyclerTouchListener'а с GestureDetector'ом:
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import...
 
public class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {
 
    public interface ClickListener {
        void onClick(View view, int position);
        void onLongClick(View view, int position);
    }
 
    private GestureDetector gestureDetector;
 
    private ClickListener clickListener;
 
    public RecyclerTouchListener(Context context,
                                 final RecyclerView recyclerView,
                                 final ClickListener clickListener) {
 
        this.clickListener = clickListener;
 
        gestureDetector = new GestureDetector(context,
                new GestureDetector.SimpleOnGestureListener() {
 
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                return true;
            }
 
            @Override
            public void onLongPress(MotionEvent e) {
                View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
                if (child != null && clickListener != null) {
                    clickListener.onLongClick(child, recyclerView.getChildPosition(child));
                }
            }
        });
    }
 
    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
 
        View child = rv.findChildViewUnder(e.getX(), e.getY());
        if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
            clickListener.onClick(child, rv.getChildPosition(child));
        }
        return false;
    }
 
    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {
    }
 
    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
 
    }
}

Тогда на RecyclerView можно повесить этот listener:
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
RecyclerView RV = findViewById(R.id.recycler_view);
RV.addOnItemTouchListener(new RecyclerTouchListener(
                getApplicationContext(),
                RV,
                new RecyclerTouchListener.ClickListener() {
 
                    @Override
                    public void onClick(View view, int position) {
                        Toast...;
 
                    }
                    @Override
                    public void onLongClick(View view, int position) {
                        Toast...;
                    }
                }));

Второй способ, можно добавлять listener'ы в адаптере в методах onCreateViewHolder/onBindViewHolder:
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import...
 
public class MoviesAdapter extends RecyclerView.Adapter<MoviesAdapter.MovieHolder> {
 
    private List<Movie> moviesList;
 
    static class MovieHolder extends RecyclerView.ViewHolder {
        public TextView title, year, genre;
 
        public MovieHolder(View view) {
            super(view);
            //boilerplate 
        }
    }
 
    public MoviesAdapter(List<Movie> moviesList) {
        this.moviesList = moviesList;
    }
 
    @Override
    public MovieHolder onCreateViewHolder(ViewGroup parent, int viewType) {
 
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.movie_list_row, parent, false);
 
        itemView.setOnClickListener(view -> {Log.d(TAG," onCreateViewHolder onClick, TAG: "+view.getTag()+" Id: "+view.getId());});
 
        return new MovieHolder(itemView);
    }
 
    @Override
    public void onBindViewHolder(MovieHolder holder, int position) {
 
        //boilerplate
        holder.itemView.setTag(movie);
        holder.itemView.setId(position);
 
        holder.itemView.setOnClickListener(view -> {
            Log.d(TAG,"onBindViewHolder onClick");
        });
    }
 
    @Override
    public int getItemCount() {
        return moviesList.size();
    }
}

Причём если сделать повесить listener в обоих методах (onBindViewHolder/onCreateViewHolder) останется только тот listener что был повешен в onBindViewHolder т.к. этот метод отрабатывает после onCreateViewHolder. Listener может быть только один и последний замещает предыдущий.
Так же в onBindViewHolder'ре у view можно указать Tag/Id что бы потом получать их если listener вешается в onCreateViewHolder. Но это уже детали второго способа. А главное - оба способа работают и не вышибают друг друга - если совместить listener на уровне всего RecyclerView и какой-нибудь из адаптера (OnItemTouchListener отработает раньше чем из onCreateViewHolder/onBindViewHolder).
А как правильно (и в чём в итоге разница) не понятно. Какие подводные камни? Может отказаться так что один - это "мейнстрим", "единственно верный способ" а другой - костыль страшный, который ещё выстрелит когда что-нибудь случиться.

Кто как делает вообще (и почему), просвятите!
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.04.2018, 17:00
Ответы с готовыми решениями:

NullPointerException в адаптере RecyclerView
Здравствуйте уважаемые форумчане! Столкнулся с такой проблемой, в RecyclerView создаю адаптер для...

В чём разница между position и id в OnItemSelectedListener в Spinner'e
Есть спиннер с листеренером spinner.setOnItemSelectedListener(new...

В чём разница между .each() и $.each()
читаю про jquery и там есть .each() и $.each() в чем разница? Где можно прочитать про тонкости...

В чём разница между корпусами?
Я нашёл два схожих корпуса и никакой разницы, кроме как в цене не нашёл, может кто найдёт или...

В чём разница между заголовками <c***> и <***.h>?
Пробовал несколько несложных примеров применения обоих вариантов. Результат выполнения идентичен....

8
Mail-up
30 / 28 / 8
Регистрация: 07.01.2017
Сообщений: 205
19.04.2018, 20:04 2
Я делаю интерфейс и на него вешается клик. В активити/фрагменте.


Или вьюхолдеру дописываю implements onclickListener то есть стандартный интерфейс и вешаю как обычно в адаптере
0
arvalon
21 / 6 / 2
Регистрация: 26.10.2012
Сообщений: 192
Записей в блоге: 1
19.04.2018, 20:10  [ТС] 3
Цитата Сообщение от Mail-up Посмотреть сообщение
Я делаю интерфейс и на него вешается клик. В активити/фрагменте
А, это есть применить интерфейс OnClickListener к Активности/Фрагменту и в методе onClick уже разбираться кто к нам пришёл. И тогда у элементу View надо бы тоже Tag установить что бы в итоге понять какой из элементов был нажат в случае если это не одиночная кнопка и т.д. а элемент какого-нибудь списка. Да, забыл об этом.
Цитата Сообщение от Mail-up Посмотреть сообщение
Или вьюхолдеру дописываю implements onclickListener и вешаю как обычно в адаптере
И это тоже забыл, где-то мелькал код, надо будет тоже попробовать.

В общем да, ещё 2 варианта, выбор всё больше и больше.
0
Mail-up
30 / 28 / 8
Регистрация: 07.01.2017
Сообщений: 205
19.04.2018, 20:12 4
Основной выбор наверное надо делать из личных нужн и предпочтений.
В основном это как правило интерфейс
Что бы понять какой элемент был нажат есть метод getAdapterPosition
0
Pablito
2812 / 2236 / 754
Регистрация: 12.05.2014
Сообщений: 7,824
Завершенные тесты: 1
20.04.2018, 15:59 5
проще всего сделать холдеру implements OnClickListener и прокидывать ему при создании слушатель (свой интерфейс)
как и написал Mail-up
0
arvalon
21 / 6 / 2
Регистрация: 26.10.2012
Сообщений: 192
Записей в блоге: 1
20.04.2018, 17:16  [ТС] 6
Цитата Сообщение от Pablito Посмотреть сообщение
проще всего сделать холдеру implements OnClickListener и прокидывать ему при создании слушатель (свой интерфейс)
Хм, так и сделал, что-то не срабатывает:
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static class MovieHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
        public TextView title, year, genre;
 
        public MovieHolder(View view) {
            super(view);
            title = view.findViewById(R.id.title);
            genre = view.findViewById(R.id.genre);
            year = view.findViewById(R.id.year);
        }
 
        @Override
        public void onClick(View v) {
            Log.d(TAG,getClass().getSimpleName()+" onClick "+v.getTag());
        }
    }
0
Mail-up
30 / 28 / 8
Регистрация: 07.01.2017
Сообщений: 205
20.04.2018, 17:19 7
Забыли установить слушатель view. SetOnClickListener(this)
1
arvalon
21 / 6 / 2
Регистрация: 26.10.2012
Сообщений: 192
Записей в блоге: 1
20.04.2018, 17:22  [ТС] 8
Цитата Сообщение от Mail-up Посмотреть сообщение
Забыли установить слушатель view. SetOnClickListener(this)
А, да да, теперь всё завелось, спасибо!
0
Pablito
2812 / 2236 / 754
Регистрация: 12.05.2014
Сообщений: 7,824
Завершенные тесты: 1
20.04.2018, 18:38 9
Java
1
2
3
4
 @Override
        public void onClick(View v) {
            Log.d(TAG,getClass().getSimpleName()+" onClick "+getAdapterPosition());
        }
и вот то, что вернет getAdapterPosition() и пробрасывать в свой слушатель
0
20.04.2018, 18:38
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.04.2018, 18:38

В чём разница между is и declare?
Всем привет! Объясните, пожалуйста, в чём разница при объявлении plsql блока в is и declare. так...

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

Не объясните в чём разница между случаями
Привет! Тут вот небольшой вопросик по поводу. Читаю книжку Страуструпа нашего и возник вопросик. ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru