22 / 7 / 2
Регистрация: 26.10.2012
Сообщений: 212
Записей в блоге: 1
1

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

19.04.2018, 17:00. Показов 2365. Ответов 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
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
19.04.2018, 17:00
Ответы с готовыми решениями:

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

В чем разница между запуском сервера через mysqld_safe и mysql.exe ?
Привет . В книге написано что mysqld_safe использують для повышения защиты системы в целом. ...

Где окажется спутник через 3 года, в чем качественная разница между различными режимами движения?
Здравствуйте. Помогите решить проблему. Задача:

Отслеживание нажатий RecyclerView в диалогом окне
Создал диалоговое окно в которое заношу в view recyclerview адаптер recyclerview: public class...

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


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

В общем да, ещё 2 варианта, выбор всё больше и больше.
0
30 / 28 / 8
Регистрация: 07.01.2017
Сообщений: 205
19.04.2018, 20:12 4
Основной выбор наверное надо делать из личных нужн и предпочтений.
В основном это как правило интерфейс
Что бы понять какой элемент был нажат есть метод getAdapterPosition
0
2883 / 2295 / 769
Регистрация: 12.05.2014
Сообщений: 7,978
20.04.2018, 15:59 5
проще всего сделать холдеру implements OnClickListener и прокидывать ему при создании слушатель (свой интерфейс)
как и написал Mail-up
0
22 / 7 / 2
Регистрация: 26.10.2012
Сообщений: 212
Записей в блоге: 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
30 / 28 / 8
Регистрация: 07.01.2017
Сообщений: 205
20.04.2018, 17:19 7
Забыли установить слушатель view. SetOnClickListener(this)
1
22 / 7 / 2
Регистрация: 26.10.2012
Сообщений: 212
Записей в блоге: 1
20.04.2018, 17:22  [ТС] 8
Цитата Сообщение от Mail-up Посмотреть сообщение
Забыли установить слушатель view. SetOnClickListener(this)
А, да да, теперь всё завелось, спасибо!
0
2883 / 2295 / 769
Регистрация: 12.05.2014
Сообщений: 7,978
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
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.04.2018, 18:38
Помогаю со студенческими работами здесь

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

В чем разница между [] и * ?
Думал, что ни в чем, но когда попытался сделать так: (в файле 1) char lc; в файле 2: extern...

В чем разница между ^p и ^13
Заменой сделал строку с ^p и строку с ^13 с Подстановочными знаками. Если поместить курсор на...

В чем разница между С++ и С?
Чем отличается С и С++, кроме того что С++ есть ООП?

В чем разница между С и С++
Возник вопрос в чем жи разница между С и С++ кроме того, что в С++ есть классы а в С их нету ?

В чем разница между X x; и X x()?
Корректный ли этот ответ?


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru