RecyclerView onClick


583

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



4
RecyclerViewDemo Я вважав цей проект чудовим, використовуючи інтерфейси для надання більш вільних дій.
MewX

2
перевірити цей підручник wiki.workassis.com/android-recyclerview-example
Bikesh M

Простий і простий у використанні - github.com/rahulkapoor1/ClickableAdapter
Рахул

stackoverflow.com/a/31199564/5788247
Шому

Відповіді:


477

Оскільки API докорінно змінилися, мене не здивувало, якби ви створили OnClickListenerдля кожного елемента. Але це не так вже й багато клопоту. При здійсненні програми RecyclerView.Adapter<MyViewHolder>ви повинні мати:

private final OnClickListener mOnClickListener = new MyOnClickListener();

@Override
public MyViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
    View view = LayoutInflater.from(mContext).inflate(R.layout.myview, parent, false);
    view.setOnClickListener(mOnClickListener);
    return new MyViewHolder(view);
}

onClickметод:

@Override
public void onClick(final View view) {
    int itemPosition = mRecyclerView.getChildLayoutPosition(view);
    String item = mList.get(itemPosition);
    Toast.makeText(mContext, item, Toast.LENGTH_LONG).show();
}

32
що робити, якщо я хочу видалити рядок при її натисканні?
Піюш Кукадія

20
Мені подобається ця відповідь краща за ту, яку ви пов’язали. Хто хоче написати слухач жестів і виявити поле натискання, щоб вирішити це. Google--
Lo-Tan

17
getChildPosition (view) застарілий метод
Jigar

45
Ви не хочете сказати, в яких класах у ваших фрагментах? onClick(), Приналежність до якого OnClickListenerможна долучити до будь-якого перегляду Ціле питання тут яке! Будь ласка, докладіть зусиль, метод ідентифікується не лише іменем, а й принаймні класом. Якщо ви не скажете, що ваш код потрібно додати до адаптера, ваша відповідь не дуже допоможе.
Вінс

16
Чи має бути метод onClick у фрагменті, що містить RecyclerView? Оскільки ви посилаєтесь на mRecyclerView у вашому класі MyOnClickListener. Звідки ви взяли посилання на цей об’єкт?
Ced

605

Ось краще і менш тісно пов'язані способом реалізувати OnClickListenerдля RecyclerView.

Фрагмент використання:

RecyclerView recyclerView = findViewById(R.id.recycler);
recyclerView.addOnItemTouchListener(
    new RecyclerItemClickListener(context, recyclerView ,new RecyclerItemClickListener.OnItemClickListener() {
      @Override public void onItemClick(View view, int position) {
        // do whatever
      }

      @Override public void onLongItemClick(View view, int position) {
        // do whatever
      }
    })
);

RecyclerItemClickListener реалізація:

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;


public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
  private OnItemClickListener mListener;

  public interface OnItemClickListener {
    public void onItemClick(View view, int position);

    public void onLongItemClick(View view, int position);
  }

  GestureDetector mGestureDetector;

  public RecyclerItemClickListener(Context context, final RecyclerView recyclerView, OnItemClickListener listener) {
    mListener = listener;
    mGestureDetector = 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 && mListener != null) {
                mListener.onLongItemClick(child, recyclerView.getChildAdapterPosition(child));
            }
        }
    });
}

  @Override public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
    View childView = view.findChildViewUnder(e.getX(), e.getY());
    if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
      mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
      return true;
    }
    return false;
  }

  @Override public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { }

  @Override
  public void onRequestDisallowInterceptTouchEvent (boolean disallowIntercept){}
}

85
Це не дасть жодної підказки про те, на яку кнопку або перегляд (у межах елемента) було натиснуто. Але для загального клацання товару це добре.
Ніранджан

27
Коментар ngen правильний - якщо ви хочете приєднати слухача onClick до певного елемента в межах перегляду елемента, ви, ймовірно, повинні зробити це у своєму адаптері, в onBindViewHolder або в самому вашому переглядачі.
Яків Табак

16
Одна з проблем цього методу полягає в тому, що ви робите щось, що займає кілька сотень мілісекунд, як початок діяльності. При натисканні на елемент та його анімації, що натиснув, помітна затримка між натисканням та переглядом анімації.
Gak2

20
Це рішення відчуває себе надзвичайно химерно, є певна затримка при обробці "клацання", і відчуття не просто нормально
wasyl

6
Чи може хтось мені пояснити, чому це рішення з GestureDetector має бути кращим рішенням, ніж просто використання "setOnClickListener" всередині onBindViewHolder () в адаптері до відповідного елемента? Таким чином мені потрібно менше коду, ніж для рішення GestureDetector. Дякую за пояснення.
e-nature

115

Я роблю це таким чином, без зайвих занять, детекторів тощо. Простий код всередині нашого адаптера. Особливо краще рішення для longClick, ніж представлено раніше.

public class PasswordAdapter extends RecyclerView.Adapter<PasswordAdapter.ViewHolder> {
    private static ClickListener clickListener;

    public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
        TextView name;

        public ViewHolder(View itemView) {
            super(itemView);
            itemView.setOnClickListener(this);
            itemView.setOnLongClickListener(this);
            name = (TextView) itemView.findViewById(R.id.card_name);
        }

        @Override
        public void onClick(View v) {
            clickListener.onItemClick(getAdapterPosition(), v);
        }

        @Override
        public boolean onLongClick(View v) {
            clickListener.onItemLongClick(getAdapterPosition(), v);
            return false;
        }
    }

    public void setOnItemClickListener(ClickListener clickListener) {
        PasswordAdapter.clickListener = clickListener;
    }

    public interface ClickListener {
        void onItemClick(int position, View v);
        void onItemLongClick(int position, View v);
    }
}

Потім всередині фрагмента чи активності просто натисніть:

PasswordAdapter mAdapter = ...;

mAdapter.setOnItemClickListener(new PasswordAdapter.ClickListener() {
    @Override
    public void onItemClick(int position, View v) {
        Log.d(TAG, "onItemClick position: " + position);
    }

    @Override
    public void onItemLongClick(int position, View v) {
        Log.d(TAG, "onItemLongClick pos = " + position);
    }
});

замість OurAdapter.clickListener я думаю, що Марурбан означає PasswordAdapter.clickListener, а замість TrainingAdapter.ClickListener (), має бути PasswordAdapter.ClickListener (). Крім того, чудове рішення Марурбан! працював на мене
номер

Слухач onItemClick також активується при тривалому натисканні.
Рашад.З

10
Для найкращої продуктивності ViewHolder повинен бути статичним. це не є гарною відповіддю.
Гілберто Ібарра

10
Статичний clickListener створює витік пам'яті. Оголосіть слухача нестатичним і замість цього прив’яжіть його до ViewHolder.
BladeCoder

1
@AJW Найпростіший спосіб - рано ініціалізувати слухача і передавати його як аргумент конструктору Adapter, а потім конструктору ViewHolder.
BladeCoder

97

Ознайомтесь із подібним запитанням @ CommonsWare коментарі посилаються на це , що реалізує OnClickListenerінтерфейс у viewHolder.

Ось простий приклад ViewHolder:

    TextView textView;//declare global with in adapter class

public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

      private ViewHolder(View itemView) {
            super(itemView);
            itemView.setOnClickListener(this);
            textView = (TextView)view.findViewById(android.R.id.text1);

      }

      @Override
      public void onClick(View view) {
            Toast.makeText(view.getContext(), "position = " + getLayoutPosition(), Toast.LENGTH_SHORT).show();

         //go through each item if you have few items within recycler view
        if(getLayoutPosition()==0){
           //Do whatever you want here

        }else if(getLayoutPosition()==1){ 
           //Do whatever you want here         

        }else if(getLayoutPosition()==2){

        }else if(getLayoutPosition()==3){

        }else if(getLayoutPosition()==4){

        }else if(getLayoutPosition()==5){

        }

        //or you can use For loop if you have long list of items. Use its length or size of the list as 
        for(int i = 0; i<exampleList.size(); i++){

        }


      }
  }

AdapterТоді виглядає наступним чином :

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view =LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false);

        return new ViewHolder(view);
    }

14
Це, здається, йде в неправильному напрямку. Якщо вам потрібно повторно використовувати перегляд рециркулятора в іншому фрагменті / діяльності, адаптер / переглядач тепер визначає логіку кліків замість того, що їх містить. Клацання дійсно слід обробляти безпосередньо або опосередковано екземпляром, що містить. Здається, що слухач дотику - це єдиний ефективний спосіб зробити це.
ian.shaun.thomas

18
@tencent Я не бачу, у чому ця проблема. Якщо сам ViewHolder містить всю інформацію щодо того, які дані вибираються при натисканні на сам елемент, то єдиною відповідальністю контейнера є відображення N елементів, а не обробка виділення конкретного i-го елемента з N елементів. Це ListViewвже було проблематично, якщо вам довелося створити список складніших об'єктів, ніж просто прості рядки. Що робити, якщо вам потрібно обробляти різні події залежно від того, де ви натискаєте елемент у ListView? Ви накручені. Тут у вас є кожен слухач.
EpicPandaForce

2
Я погоджуюся з @EpicPandaForce щодо цього. Я також прийшов, щоб підтвердити цю відповідь, прочитавши розділ книги Commonsware про обробку кліків у RecyclerViews. Це до цього часу для мене спрацювало чудово.
AdamMc331

1
findViewById використовується тут лише для створення власників представлення даних (звідси onCreateViewHolder). Власник перегляду призначений для запобігання пошуку представлення кожного разу, коли предмет прив'язується до власника, а не при первинному створенні.
stuckj

2
getPosition()застаріло, використовуйте getAdapterPosition()або getLayoutPosition()замість цього.
K Neeraj Lal

94

На підставі відповіді Якова Табака (+1 для нього) я зміг додати слухача onLongClick:

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
    public interface OnItemClickListener {
        void onItemClick(View view, int position);

        void onItemLongClick(View view, int position);
    }

    private OnItemClickListener mListener;

    private GestureDetector mGestureDetector;

    public RecyclerItemClickListener(Context context, final RecyclerView recyclerView, OnItemClickListener listener) {
        mListener = listener;

        mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                return true;
            }

            @Override
            public void onLongPress(MotionEvent e) {
                View childView = recyclerView.findChildViewUnder(e.getX(), e.getY());

                if (childView != null && mListener != null) {
                    mListener.onItemLongClick(childView, recyclerView.getChildAdapterPosition(childView));
                }
            }
        });
    }

    @Override
    public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
        View childView = view.findChildViewUnder(e.getX(), e.getY());

        if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
            mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
        }

        return false;
    }

    @Override
    public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {
    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
    }
}

Тоді ви можете використовувати його так:

recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(getActivity(), recyclerView, new RecyclerItemClickListener.OnItemClickListener() {
    @Override
    public void onItemClick(View view, int position) {
        // ...
    }

    @Override
    public void onItemLongClick(View view, int position) {
        // ...
    }
}));

1
Зайняв деякий час, щоб адаптуватись до мого додатка, а також вирівняти і відформатувати код до стандартів Java / Android, але з часом він спрацював чудово.
milosmns

Як додати анімацію для тривалого клацання?
Джон

1
@ Eng.Fouad натискання ефекту не працює, використовуючи це, хоча якщо ми встановимо прослуховувач
клацань

4
Ви також повинні перемогтиpublic void onRequestDisallowInterceptTouchEvent (boolean disallowIntercept){}
Паоло Ротоло,

Чомусь він не повертає переглянуте кнопку. У моєму випадку я натискаю прапорець, але даний вид - це щось інше. Як я перевіряю:view.getId() == R.id.selection
dVaffection

63

Це те, що працювало для мене. Прикріпити OnClickListenerдо onBindView. Я не знаю, чи це вплине на продуктивність, але, схоже, це спрацює з невеликим кодом.

public void onBindViewHolder(ViewHolder holder, final int position) {
    holder.view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(context, "Recycle Click" + position, Toast.LENGTH_SHORT).show();
            }
    });
}

5
у моєму випадку власник.itemView.setOnClickListener (..)
D4rWiNS

18
в моєму випадку він названий "itemView" замість "view", просто кажучи для початківців, деякі з них не розуміють, що вони копіюють, і не можуть зрозуміти, чому це не працює
D4rWiNS

3
Його розташування
Bubunyo Nyavor

1
для мене це, здається, стосується лише останнього видимого предмета, а не натиснутого
Nasz Njoka Sr.

2
Це рішення здається найкращим для мене, але чим це відрізняється від відповіді @bolot в термінах продуктивності? Він реалізував View.OnClickListener безпосередньо на класі ViewHolder, який, ніж окремо, виплющує метод onClick. Яке найкраще рішення?
Едмонд Тамас

46

Мені було настільки важко мати слухача кліків на елементі в процесі діяльності, а також слухача клацань для одиничного перегляду елемента, який не запускатиметься на слухача клацання елемента. Погравши з відповіддю Якова Табака, я поважаю його відповідь на натискання предмета, якщо ніяких інших сенсорних дій всередині предмета не представлено.

У мене є власний OnClickListenerінтерфейс, який містить події клацання на елементі, яка містить перегляд натиснутого елемента та позицію елемента з адаптера. Я представляю його екземпляр у конструкторі (або це може бути із сеттером) і додаю його до слухача кліків контейнера для перегляду.

У мене також є інший слухач клацань у адаптері (може бути у власнику перегляду), який буде обробляти поточний клік View із контейнера.

 public class MyRecyclerAdapter extends RecyclerView.Adapter<MyViewHolder> {

private ArrayList<String> mData;
private OnItemClickListener mOnItemClickListener;

public interface OnItemClickListener {
    public void onItemClick(View view, int position);
}

public MyRecyclerAdapter(ArrayList<String> itemsData,
        OnItemClickListener onItemClickListener) {
    mOnItemClickListener = onItemClickListener;
    this.mData = itemsData;
}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent,
        int viewType) {

    View layoutView = LayoutInflater.from(mContext).inflate(
            R.layout.list_item, parent, false);

    final MyViewHolder viewHolder = new MyViewHolder(layoutView);

    viewHolder.container.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            mOnItemClickListener.onItemClick(v, viewHolder.getAdapterPosition());
        }
    });

    viewHоlder.button.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            //do button click work here with
            // mData.get( viewHolder.getAdapterPosition() );
        }
    });

    return viewHolder;
}

@Override
public int getItemCount() {
    return mData.size();
}}

У цій діяльності вам потрібно ініціалізувати адаптер, передаючи екземпляр OnItemClickListener

public class FeedActivity extends ActionBarActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    ...

    RecyclerView recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);

    .....

    MyRecyclerAdapter adapter = new MyRecyclerAdapter(new ArrayList<String>(), new OnItemClickListener() {

        @Override
        public void onItemClick(View view, int position) {

            ///list item was clicked
        }
    });

    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.setAdapter(mFeedsAdapter);
}

І мій ViewHolder

public class MyViewHolder extends RecyclerView.ViewHolder {

public Button button;
public View container;

public MyViewHolder(View itemLayoutView) {
    super(itemLayoutView);

    container = itemLayoutView;
    button = (Button) itemLayoutView.findViewById(R.id.button);
}}

Такий підхід для мене добре працював - це означає, що ви можете обробляти кліки в діяльності, а не всередині сітки
листопад

3
Де я можу дати вам гроші. 4 години пошуку, а потім я прочитав ваш пост. Дякуємо за витрачений час для публікації цього повідомлення.
Брендон

3
Це звучить нерозумно, але чи має ця пам'ять чи ефективність, як проблема? Тому що ми призначаємо прослуховувача кліків щоразу, коли перегляд переглядається правильно?
rgv

1
@Raghav так щоразу, коли перегляд прив'язується, призначається новий слухач клацань, але це стандартний потік. Але mOnItemClickListener створюється лише один раз для адаптера, просто перегляд і його положення відрізняються при кожному натисканні елемента;)
Сер Ніколай Сезар Перший

3
Чудовий приклад, щоб знищити продуктивність додатків і створити надмірне використання пам'яті! У цьому прикладі вам просто потрібно прокрутити, щоб створити сотні марних об'єктів, які за мить стануть марними і до них доведеться звертатися як до гарбігу. @NoobDogg правильно. Ніякі ClickListeners не повинні створюватися в onBindView. Слухач клацань повинен бути створений один раз у onCreateView (або конструкторі власника), і він існує, поки нам потрібен екран із цим адаптером.
Микола Тичина

36

Це те, що мені закінчилося потрібним, якщо хтось вважає це корисним:

public static class ViewHolder extends RecyclerView.ViewHolder {

    public ViewHolder(View item) {

        super(item);
        item.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("RecyclerView", "onClick:" + getAdapterPosition());
            }
        });

    }
}

Джерело: http://blog.csdn.net/jwzhangjie/article/details/36868515


З усіх версій, які я спробував, це ця, з якою я працював. Але чи добре це робити так? Або є кращий спосіб, як найкраща практика?
Маттіас Лойбл

1
Наскільки я міг сказати, це був єдиний спосіб. Перевірте це для отримання детальної інформації! stackoverflow.com/a/24933117/1508887
Fifer Sheep

Як я можу відкрити новий фрагмент методом "onclick" всередині?
хеш

5
getAdapterPosition () замінює getPosition ()
Кеннеді Няга

27

У мене є гарне рішення для RecyclerView'sonItemClickListener для предметів і підпунктів

Крок 1 - Створіть інтерфейс

public interface OnRecyclerViewItemClickListener
{
    /**
     * Called when any item with in recyclerview or any item with in item
     * clicked
     * 
     * @param position
     *            The position of the item
     * @param id
     *            The id of the view which is clicked with in the item or
     *            -1 if the item itself clicked
     */
    public void onRecyclerViewItemClicked(int position, int id);
}

Крок 2. Потім використовуйте його в onBindViewHolderметоді адаптера наступним чином

/**
     * Custom created method for Setting the item click listener for the items and items with in items
     * @param listener OnRecyclerViewItemClickListener 
     */
    public void setOnItemClickListener(OnRecyclerViewItemClickListener listener)
    {
        this.listener = listener;
    }

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, final int position)
    {

        // viewHolder.albumBg.setBackgroundResource(_itemData[position]
        // .getImageUrl());

        viewHolder.albumName.setText(arrayList.get(position).getName());
        viewHolder.artistName.setText(arrayList.get(position).getArtistName());
        String imgUrl = arrayList.get(position).getThumbImageUrl();

        makeImageRequest(imgUrl, viewHolder);
        viewHolder.parentView.setOnClickListener(new View.OnClickListener()
        {

            @Override
            public void onClick(View v)
            {
                listener.onRecyclerViewItemClicked(position, -1);
            }
        });
        viewHolder.settingButton.setOnClickListener(new View.OnClickListener()
        {

            @Override
            public void onClick(View v)
            {
                listener.onRecyclerViewItemClicked(position, v.getId());
            }
        });

    }

    // class to hold a reference to each item of RecyclerView
    public static class ViewHolder extends RecyclerView.ViewHolder
    {

        public TextView albumName, artistName;
        public ImageView albumIcon, settingButton;
        public LinearLayout parentView;

        public ViewHolder(View itemLayoutView)
        {
            super(itemLayoutView);
            // albumBg = (LinearLayout) itemLayoutView
            // .findViewById(R.id.albumDlbg);
            albumName = (TextView) itemLayoutView.findViewById(R.id.albumName);
            artistName = (TextView) itemLayoutView
                    .findViewById(R.id.artistName);
            albumIcon = (ImageView) itemLayoutView.findViewById(R.id.albumIcon);
            parentView = (LinearLayout) itemLayoutView
                    .findViewById(R.id.albumDlbg);
            settingButton = (ImageView) itemLayoutView
                    .findViewById(R.id.settingBtn);
        }

    }

Крок 3 - знайдіть і налаштуйте перегляд рециркулятора в діяльності чи фрагменті, де ви це використовуєте

recyclerView = (RecyclerView) rootview.findViewById(R.id.vmtopsongs);

        lm = new LinearLayoutManager(mActivity);
        lm.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(lm);
        recyclerView.addItemDecoration(
                new HorizontalDividerItemDecoration.Builder(getActivity())
                        .paint(Utils.getPaint()).build());
        PopularSongsadapter mAdapter = new PopularSongsadapter(gallery,
                mActivity, true);
        // set adapter
        recyclerView.setAdapter(mAdapter);
        mAdapter.setOnItemClickListener(this);
        // set item animator to DefaultAnimator
        recyclerView.setItemAnimator(new DefaultItemAnimator());

Крок 4- Нарешті, реалізуйте інтерфейс у діяльності чи фрагменті, де ви використовуєте перегляд рециркуляторів

@Override
    public void onRecyclerViewItemClicked(int position, int id)
    {
        if(id==-1){
            Toast.makeText(mActivity, "complete item clicked", Toast.LENGTH_LONG).show();
        }else{
            Toast.makeText(mActivity, "setting button clicked", Toast.LENGTH_LONG).show();
        }
    }

2
Це найкраще рішення, оскільки нам зазвичай потрібно багато властивостей від діяльності / фрагмента на нашому onItemClickListener, і немає сенсу називати це безпосередньо від переглядача (мені доведеться створити спеціальний конструктор для кожного адаптера). До речі, ваш код трохи розширений, я пропоную вам скоротити його до найважливішої частини (setOnItemClickListener).
sagits

це хороший простий підхід для розмежування рядка / елемента від підпунктів
Nigel Savage

17

Ось що я зробив. Це рішення підтримує як onClick, так і onLongClick як для елементів RecyclerView, так і для представлень RecyclerView (внутрішні подання).

Я тегую viewHolder на переглядах, які я вибрав:

public RecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_item, null);
    ViewHolder viewHolder = new ViewHolder(itemView);

    itemView.setOnClickListener( this);
    itemView.setOnLongClickListener(this);
    viewHolder.imageIV.setOnClickListener(this);
    viewHolder.imageIV.setOnLongClickListener(this);

    viewHolder.imageIV.setTag(viewHolder);
    itemView.setTag(viewHolder);

    return viewHolder;
}

І я використовую hold.getPosition () для отримання позиції методом onClick () (onLongClick схожий):

public void onClick(View view) {
    ViewHolder holder = (ViewHolder) view.getTag();
    int position = holder.getPosition();

    if (view.getId() == holder.imageIV.getId()){
        Toast.makeText(context, "imageIV onClick at" + position, Toast.LENGTH_SHORT).show();
    } else {
        Toast.makeText(context, "RecyclerView Item onClick at " + position, Toast.LENGTH_SHORT).show();
    }
}

Також працює варіант з getChildPosition. Зверніть увагу, що для внутрішніх представлень даних в onClick () використовуйте:

int position = recyclerView.getChildPosition((View)view.getParent());

На мій погляд, перевага цього рішення полягає в тому, що при натисканні на зображення викликається лише слухач зображення onclick (), тоді як коли я поєднав рішення Якова для перегляду пункту RecyclerView і моє рішення для внутрішніх поглядів, вигляд предмета RecyclerView onclick ( ) також називається (при натисканні на зображення).


11

Є набагато простіший спосіб зробити це. Просто застосуйте при натисканні onBindViewHolderна перегляд кореня.

Подумайте, це ваш погляд на адаптер,

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/linearlayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

        <TextView
            android:id="@+id/textview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="1dp"
            android:textSize="15sp" />
</LinearLayout>

Потім виконайте наступні дії у своєму адаптері

//get the layout and make view holder
@Override
public RVAdapter.ViewHolder1 onCreateViewHolder(ViewGroup parent, int viewType) {

    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_layout, null);
    ViewHolder1 viewHolder = new ViewHolder1(view);
    return viewHolder;
}

@Override
public void onBindViewHolder(RVAdapter.ViewHolder1 holder, int position) {

    //apply on click on your root view
    holder.linearlayout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //Do on click stuff
        }
    });
}

//make references to views in layout including root view
public class ViewHolder1 extends RecyclerView.ViewHolder {

    protected LinearLayout linearlayout = null
    protected TextView textview = null;

    public CareerLinksViewHolder(View itemView) {
        super(itemView);

        this.linearlayout = (LinearLayout) itemView.findViewById(R.id.linearlayout);
        this.tvCompName = (TextView) itemView.findViewById(R.id.textview);
    }
}

9

Ви можете перейти clickListenerдо Adapter.

У вашому Activity:

private View.OnClickListener mItemClick = new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        Intent intent = null;
        int position = list.getChildPosition(v);
        switch (position) {
            case 0:
                intent = new Intent(MainActivity.this, LeakCanaryActivity.class);
                break;
            case 1:
                intent = new Intent(MainActivity.this, ButterKnifeFragmentActivity.class);
                break;
        }
        if (intent != null) {
            MainActivity.this.startActivity(intent);
        }
    }
};

потім передайте його Adapter:

MainAdapter mainAdapter = new MainAdapter(this, mItemClick);

В Adapter«з onCreateViewHolder:

 @Override
public MainAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int position) {
    View itemView = activity.getLayoutInflater().inflate(R.layout.main_adapter_item, viewGroup, false);
    ViewHolder holder = new ViewHolder(itemView);
    itemView.setOnClickListener(mItemClick);
    return holder;
}

Як ви передаєте holderзначення за допомогою намірів?
RoCk RoCk

8

Я розробив бібліотеку з легкою вагою для android, ви можете відвідати https://github.com/ChathuraHettiarachchi/RecycleClick

і слідкуйте за наступним зразком

RecycleClick.addTo(YOUR_RECYCLEVIEW).setOnItemClickListener(new RecycleClick.OnItemClickListener() {
            @Override
            public void onItemClicked(RecyclerView recyclerView, int position, View v) {
                // YOUR CODE
            }
        });

Можу підтвердити, ця бібліотека чудова! Дуже проста у використанні, хороша робота!
peterkodermac

7

Ви можете впровадити OnClickListener у свій клас ViewHolder

public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        public Item item
        @InjectView(R.id.tv_title)
        public TextView tvTitle;
        @InjectView(R.id.rl_row)
        public RelativeLayout rlRow;

        public ViewHolder(View v) {
            super(v);
            ButterKnife.inject(this, v);
            v.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            Log.e("item title",item.getTitle());
        }
    }

І onBindViewHolder встановить елемент власника перегляду

public void onBindViewHolder(ViewHolder holder, int position) {
        holder.tvTitle.setText(objects.get(position).getTitle());
        holder.item = objects.get(position);
        }

7

Шлях занадто простий і ефективний.

Замість того, щоб реалізовувати інтерфейс View.OnClickListenerвсередині власника перегляду або створювати та інтерфейс та реалізовувати інтерфейс у своїй діяльності - я використовував цей код для простоти в OnClickListenerреалізації.

public static class SimpleStringRecyclerViewAdapter
            extends RecyclerView.Adapter<SimpleStringRecyclerViewAdapter.ViewHolder> {

        // Your initializations goes here...
        private List<String> mValues;

        public static class ViewHolder extends RecyclerView.ViewHolder {

            //create a variable mView
            public final View mView;

            /*All your row widgets goes here
            public final ImageView mImageView;
            public final TextView mTextView;*/

            public ViewHolder(View view) {
                super(view);
                //Initialize it here
                mView = view;

                /* your row widgets initializations goes here
                mImageView = (ImageView) view.findViewById(R.id.avatar);
                mTextView = (TextView) view.findViewById(android.R.id.text1);*/
            }
        }

        public String getValueAt(int position) {
            return mValues.get(position);
        }

        public SimpleStringRecyclerViewAdapter(Context context, List<String> items) {

            mBackground = mTypedValue.resourceId;
            mValues = items;
        }

        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.list_item, parent, false);
            view.setBackgroundResource(mBackground);
            return new ViewHolder(view);
        }

        @Override
        public void onBindViewHolder(final ViewHolder holder, int position) {
            holder.mBoundString = mValues.get(position);
            holder.mTextView.setText(mValues.get(position));

            //Here it is simply write onItemClick listener here
            holder.mView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Context context = v.getContext();
                    Intent intent = new Intent(context, ExampleActivity.class);

                    context.startActivity(intent);
                }
            });
        }

        @Override
        public int getItemCount() {
            return mValues.size();
        }
    }

3
Це звичайна погана практика, оскільки це виглядає занадто просто. Ви створюєте нового внутрішнього слухача кожного разу, коли об'єкт прив'язується (і кожен елемент утилізатора може бути пов'язаний багато разів), що погано для а) продуктивності б) збирання сміття. Натомість вам слід створити ОДИН слухач десь (у переглядачі, в адаптері, у верхньому фрагменті чи діяльності) та просто додати його до елементів у конструкторі переглядачів перегляду в onCreateViewHolder. Це має додаткову складність у тому, щоб розібратися, який предмет був клікером, але його можна легко вирішити за допомогою тегів або додавання додаткової інформації для власника.
GuillermoMP

6

Усі відповіді, розміщені на сьогодні, є чудовими рішеннями, однак, якщо ви не хочете мати справу з надто великою кількістю деталей щодо впровадження, а просто хочете, щоб вона працювала аналогічно тому, як це робить ListView, я б рекомендував використовувати TwoWay-View, як показано тут:

https://github.com/lucasr/twoway-view

Зауважте, що ця реалізація також підтримує тривалий натиск на елементи, а також підтримку натиснутих станів (що є важливим, що відсутні інші рішення цього питання).

Якщо ви не хочете використовувати всю бібліотеку, перегляньте клас ClickItemTouchListener , який при необхідності може бути використаний як окремий. Єдине питання, з яким я натрапив на даний момент, - це довге натискання + прокручування, воно, схоже, має неправильну поведінку.


6

Якщо ви хочете зафіксувати подію клацання на окремих елементах, тоді просто застосуйте їх OnClickListenerдо ViewHolderкласу, а потім встановіть слухачів кліків на окремі види або цілі itemView.

Наступний приклад показує те саме

public  class ContactViewHolder extends RecyclerView.ViewHolder implements OnClickListener
    {
        TextView txt_title,txt_name,txt_email;

        public ContactViewHolder(View itemView) 
        {
            super(itemView);
            txt_title = (TextView)itemView.findViewById(R.id.txt_title);
            txt_name  = (TextView)itemView.findViewById(R.id.txt_name);
            txt_email = (TextView)itemView.findViewById(R.id.txt_email);

            txt_name.setOnClickListener(this);
            txt_email.setOnClickListener(this);
            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub

            if(v == itemView)
            {
                Toast.makeText(RecyclerDemoActivity.this, "Visiting Card Clicked is ==>"+txt_name.getText(), Toast.LENGTH_SHORT).show();
            }

            if(v == txt_name)
            {
                Toast.makeText(RecyclerDemoActivity.this, "Name ==>"+txt_name.getText(), Toast.LENGTH_SHORT).show();
            }

            if(v == txt_email)
            {
                Toast.makeText(RecyclerDemoActivity.this, "Email ==>"+txt_email.getText(), Toast.LENGTH_SHORT).show();
            }
        }

    }
} 

5

Для мене це найкращий спосіб:

class YourRecyclerAdapter extends RecyclerView.Adapter<ContactViewHolder> implements View.OnClickListener { 
  ...
  @Override
  public void onClick(View view) {
        int itemPosition = vRecycle.getChildPosition(view);
        //And use itemPosition to get the item from your collection. This way you dont restrain the ViewHolder with a OnClick callback
    }
  ...
}

3
getChildPosition () обезголовлений
Nasz Njoka. Ср.

5

У RecyclerViewцього немає OnClickListenerі доведеться це реалізовувати самостійно.

Мені подобається додати OnItemClickListenerінтерфейс Adapterіз onClickметодом, який викликається, коли ви клацаєте на перегляд елемента з пункту ViewHolder. Таким чином, відповідальність за керування клацанням предмета знаходиться поза ViewHolderтаAdapter . Чи буде діяльність чи фрагмент, який вирішить, що робити

Додайте інтерфейс до слухача та об'єкта слухача.

public class ItemsAdapter extends RecyclerView.Adapter<ItemsAdapter.ViewHolder> {

  ...

  private static OnItemClickListener onItemClickListener;

  ...

  public static interface OnItemClickListener {
      public void onItemClick(View view, int position);
  }

  ...
}

Ми фіксуємо клацання кореневого перегляду елемента і коли спрацьовує зворотний виклик onClickслухача, дзвінок на адаптер.

public class ItemsAdapter extends RecyclerView.Adapter<ItemsAdapter.ViewHolder> {

  ...

  private static OnItemClickListener onItemClickListener;

  ...

  public static interface OnItemClickListener {
      public void onItemClick(View view, int position);
  }

  ...

  public static class ViewHolder extends RecyclerView.ViewHolder {
      public ImageView imageView;

      public ViewHolder(View itemRootView) {
          super(itemRootView);
          imageView = (ImageView) itemRootView.findViewById(R.id.itemImage);

          itemRootView.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View view) {
                  int position  = ViewHolder.super.getAdapterPosition();
                  onItemClickListener.onItemClick(view,position);
              }
          });
      }
  }
}

Оскільки активність чи фрагмент, фрагмент у нашому випадку, ми призначаємо слухача адаптеру та onClick зворотного виклику, ми отримаємо вибраний елемент за позицією та відкрили детальну активність елемента.

public class ItemsFragment extends Fragment {
    ...
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
       ...    
        ((ItemsAdapter) adapter).setOnItemClickListener(new ItemsAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                //Do something when an item has been clicked
            }
        });
        ...
    }
...
}

5

На жаль, RecyclerViewне вистачає декількох функцій, які ListViewбули вбудовані. Наприклад, можливість додати знак, OnItemClickListenerякий запускається при натисканні на елемент. RecyclerViewдозволяє встановити OnClickListenerсвій адаптер, але передача цього слухача клацань з вашого коду виклику, адаптера та до ViewHolder, є складним для отримання простого клацання елемента.

public class ItemClickSupport {
private final RecyclerView mRecyclerView;
private OnItemClickListener mOnItemClickListener;
private OnItemLongClickListener mOnItemLongClickListener;
private View.OnClickListener mOnClickListener = new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (mOnItemClickListener != null) {
            RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
            mOnItemClickListener.onItemClicked(mRecyclerView, holder.getAdapterPosition(), v);
        }
    }
};
private View.OnLongClickListener mOnLongClickListener = new View.OnLongClickListener() {
    @Override
    public boolean onLongClick(View v) {
        if (mOnItemLongClickListener != null) {
            RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
            return mOnItemLongClickListener.onItemLongClicked(mRecyclerView, holder.getAdapterPosition(), v);
        }
        return false;
    }
};
private RecyclerView.OnChildAttachStateChangeListener mAttachListener
        = new RecyclerView.OnChildAttachStateChangeListener() {
    @Override
    public void onChildViewAttachedToWindow(View view) {
        if (mOnItemClickListener != null) {
            view.setOnClickListener(mOnClickListener);
        }
        if (mOnItemLongClickListener != null) {
            view.setOnLongClickListener(mOnLongClickListener);
        }
    }

    @Override
    public void onChildViewDetachedFromWindow(View view) {

    }
};

private ItemClickSupport(RecyclerView recyclerView) {
    mRecyclerView = recyclerView;
    mRecyclerView.setTag(R.id.item_click_support, this);
    mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener);
}

public static ItemClickSupport addTo(RecyclerView view) {
    ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
    if (support == null) {
        support = new ItemClickSupport(view);
    }
    return support;
}

public static ItemClickSupport removeFrom(RecyclerView view) {
    ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
    if (support != null) {
        support.detach(view);
    }
    return support;
}

public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) {
    mOnItemClickListener = listener;
    return this;
}

public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) {
    mOnItemLongClickListener = listener;
    return this;
}

private void detach(RecyclerView view) {
    view.removeOnChildAttachStateChangeListener(mAttachListener);
    view.setTag(R.id.item_click_support, null);
}

public interface OnItemClickListener {

    void onItemClicked(RecyclerView recyclerView, int position, View v);
}

public interface OnItemLongClickListener {

    boolean onItemLongClicked(RecyclerView recyclerView, int position, View v);
}
}

Вам також потрібно визначитись R.id.item_click_supportза допомогою ids.xml:

 <?xml version="1.0" encoding="utf-8"?>
 <resources>
  <item name="item_click_support" type="id" />
 </resources>

Тепер отриманий слухач клацання коду виглядає приблизно так:

ItemClickSupport.addTo(mRecyclerView).setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
@Override
public void onItemClicked(RecyclerView recyclerView, int position, View v) {
    // do it
}
});

Для короткого пояснення про кліки утилізації перегляньте цей маленький робочий каталог


5

ви можете легко визначити setOnClickListener у своєму класі ViewHolder наступним чином:

public class ViewHolder extends RecyclerView.ViewHolder {
    TextView product_name;

    ViewHolder(View itemView) {
        super(itemView);
        product_name = (TextView) itemView.findViewById(R.id.product_name);
        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int itemPosition = getLayoutPosition();
                Toast.makeText(getApplicationContext(), itemPosition + ":" + String.valueOf(product_name.getText()), Toast.LENGTH_SHORT).show();
            }
        });
    }
}

5

Ось що я зробив Детальніше та завантажуйте суть тут

Додаємо туди ж

CustomItemClickListener.java

public interface CustomItemClickListener {
 public void onItemClick(View v, int position);
}

ItemsListAdapter.java

public class ItemsListAdapter extends RecyclerView.Adapter<ItemsListAdapter.ViewHolder> {
ArrayList<ItemListSingleItem> data;

Context mContext;
CustomItemClickListener listener;

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View mView = LayoutInflater.from(parent.getContext()).inflate(R.layout.items_list_single_item, parent, false);
    final ViewHolder mViewHolder = new ViewHolder(mView);
    mView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            listener.onItemClick(v, mViewHolder.getAdapterPosition());
        }
    });
    return mViewHolder;
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    holder.itemTitle.setText(Html.fromHtml(data.get(position).getTitle()));
    if (!TextUtils.isEmpty(data.get(position).getThumbnailURL())) {
      // I Love picasso library :) http://square.github.io/picasso/
        Picasso.with(mContext).load(data.get(position).getThumbnailURL()).error(R.drawable.ic_no_image).
                placeholder(R.drawable.ic_no_image).
                transform(new RoundedCornersTransformation(5, 0)).
                into(holder.thumbnailImage);
    } else {
        holder.thumbnailImage.setImageResource(R.drawable.ic_no_image);
    }
}


@Override
public int getItemCount() {
    return data.size();
}

public ItemsListAdapter(Context mContext, ArrayList<ItemsListSingleItem> data, CustomItemClickListener listener) {
    this.data = data;
    this.mContext = mContext;
    this.listener = listener;
}

public static class ViewHolder extends RecyclerView.ViewHolder {
    public TextView itemTitle;
    public ImageView thumbnailImage;

    ViewHolder(View v) {
        super(v);
        itemTitle = (TextView) v
                .findViewById(R.id.post_title);
        thumbnailImage = (ImageView) v.findViewById(R.id.post_thumb_image);
    }
 }
}

4

З більшості відповідей, поданих вище, вони, схоже, налаштовують своїх учасників onclickliste на окремі пункти. Однак рішення, яке я пропоную запропонувати, дуже просте, але все ще не інтуїтивно зрозуміло для багатьох. Багато хто забуває, що інші компоненти завжди знаходяться у батьківському компоненті, який використовується для відображення елементів у поданнях Перелік або Переробник. Це рішення полягає лише у встановленні одного слухача onclick для цього батьківського подання, і відтворюється черга. Рішення також включає спосіб передавати позицію клацнутого предмета зі списку або перегляду рециркулятора. Ось наш головний rootview - це CardView з бібліотеки підтримки Android. Ось зразок коду

public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ViewHolder> {

public static final String LOG_TAG = ListAdapter.class.getSimpleName();
private Cursor mDataset;
private Context mContext;
private ViewHolder mViewHolder;

// Provide a suitable constructor (depends on the kind of dataset)
public ListAdapter(Context context, Cursor Dataset) {
    mDataset = Dataset;
    mContext = context;
}

// Create new views (invoked by the layout manager)
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    // create a new view
    View v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.list_business_view, parent, false);

    mViewHolder = new ViewHolder(v);
    return mViewHolder;
}

public void setData(Cursor newdata) {
    this.mDataset = newdata;
}

// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
//Bind data to other items here. To save time, i have ommited that.
           //here is where we attach a click listerner for an item in the recycler list rather than for each element of a given item.
            holder.card.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(mContext, " Just cliked item at position " + itemPosition, Toast.LENGTH_LONG).show();

            }
        });

    }
}

// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
    if (null != mDataset) {
        return mDataset.getCount();
    }
    return 0;

}


// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class ViewHolder extends RecyclerView.ViewHolder{
    // each data item is just a string in this case
    public final TextView mBusinesssName; // View for the business name
    public final TextView mBusinessCategory; //View for the category name
    public final ImageView businessImage; // View for the business category image Image
    public final TextView mBusinessDistance; // View for the distance
    public final CardView card;

    public ViewHolder(View view) {
        super(view);
        mBusinesssName = (TextView) view.findViewById(R.id.list_item_name_textview);
        mBusinessCategory = (TextView) view.findViewById(R.id.list_item_category_textview);
        mBusinessDistance = (TextView) view.findViewById(R.id.list_item_dist_textview);
        businessImage = (ImageView) view.findViewById(R.id.list_item_icon);
        card = (CardView) view.findViewById(R.id.card_view);

    }
}
}

4

Котлін реалізація nhaarman в відповідь :

mRecyclerView.addOnItemTouchListener(object  : RecyclerItemClickListener(this, mRecyclerView,object :RecyclerItemClickListener.OnItemClickListener{
            override fun onItemClick(view: View, position: Int) {

            }

            override fun onLongItemClick(view: View?, position: Int) {

            }
}){})

RecyclerItemClickListener.java:

import android.content.Context
import android.support.v7.widget.RecyclerView
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View


open class RecyclerItemClickListener(context: Context, recyclerView: RecyclerView, private val mListener: OnItemClickListener?) : RecyclerView.OnItemTouchListener {

    private var mGestureDetector: GestureDetector

    interface OnItemClickListener {
        fun onItemClick(view: View, position: Int)

        fun onLongItemClick(view: View?, position: Int)
    }

    init {
        mGestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
            override fun onSingleTapUp(e: MotionEvent): Boolean {
                return true
            }

            override fun onLongPress(e: MotionEvent) {
                val child = recyclerView.findChildViewUnder(e.x, e.y)
                if (child != null && mListener != null) {
                    mListener.onLongItemClick(child, recyclerView.getChildAdapterPosition(child))
                }
            }
        })
    }

    override fun onInterceptTouchEvent(view: RecyclerView, e: MotionEvent): Boolean {
        val childView = view.findChildViewUnder(e.x, e.y)
        if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
            mListener.onItemClick(childView, view.getChildAdapterPosition(childView))
            return true
        }
        return false
    }

    override fun onTouchEvent(view: RecyclerView, motionEvent: MotionEvent) {}

    override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}
}

3
public class MyViewHolder extends RecyclerView.ViewHolder {
        public TextView title, year, genre;

        public MyViewHolder(View view) {
            super(view);
            title = (TextView) view.findViewById(R.id.title);
            genre = (TextView) view.findViewById(R.id.genre);
            year = (TextView) view.findViewById(R.id.year);
            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(context, ""+getAdapterPosition(), Toast.LENGTH_SHORT).show();
                }
            });
        }
    }

3

ось повний код для мого користувальницького адаптера. Цей код надує рядки елементами списку, визначеними у файлі xml під назвою "list_item", він також виконуватиме події клацання на всіх рядках елементів списку з відповідними позиціями.

public class MyCustomAdapter extends RecyclerView.Adapter`<`AdapterMyCustomAdapter.ViewHolder> {

    public static class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener {
        public onItemClickListener mListener;
        public ViewHolder(View v, onItemClickListener listener) {
            super(v);
            mListener =listener;
            v.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            mListener.onRecyclerItemClick(v, getPosition());
        }

        public static interface onItemClickListener {
            public void onRecyclerItemClick(View view , int position);
        }
    }

    @Override
    public int getItemCount() {
        return 5;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int pos) {      

    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int position) {
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.list_item, parent, false);

    /* here list_item is an xml file we want to inflate ...it is same as we do in case of listview for customization.*/

        MyCustomAdapter.ViewHolder vh = new ViewHolder(v, new MyCustomAdapter.ViewHolder.onItemClickListener() {

            @Override
            public void onRecyclerItemClick(View view, int position) {
                System.out.println("clicked on list item at position " +position);
            } 
        });
        return vh;
    }
}

2

Це можна зробити за допомогою слабких посилань на Java. Семантично власник перегляду - це той, хто повинен відповісти на подію натискання або делегувати його правильному респонденту.

Наші цілі:

  1. Переглядач не повинен нічого знати про клас, який реагує на події, крім того, що він реалізує певний інтерфейс.
  2. Обробник кліків повинен отримати позицію в RecyclerView перегляду, на який натиснули.
  3. Ми повинні мати змогу розпізнати, на який вид натиснуто зображення власника.
  4. Підтримуйте нещільне з'єднання між усіма компонентами і не спричиняйте жодних циклів утримування.

Кроки:

  1. Створіть інтерфейс для обробки відповідей на натискання.

  2. Реалізуйте цей інтерфейс у розділі "Діяльність", який керуватиме клацанням.

  3. Додайте змінну члена в адаптер RecyclerView, щоб містити слабкий довідник і конструктор, який його встановлює.

  4. Зробіть те ж саме в RecyclerView ViewHolder і додайте змінну члена, щоб відстежувати позицію.

  5. Встановіть слухачів клацань на будь-якому перегляді, який ви хочете в ViewHolder, а потім зворотній виклик відповіді, щоб обробити їх.

  6. Змініть свій метод onBindViewHolder, щоб встановити положення під час прив’язки.

  7. Передайте відповідь вниз до ViewHolder.

  8. Тепер у відповіді ви можете використовувати getId () у поданні, щоб визначити, на який вид натиснули.

І ось Gist, щоб ви могли бачити, як все це поєднується: RecyclerView обробка кліків


2

Я знаю, що відповідей дуже багато, але я подумав, що, можливо, я б також також забезпечив свою реалізацію. (Повні деталі можна знайти в іншому запитанні, на яке я відповів ).

Отже, щоб додати слухача клацань, ваш внутрішній ViewHolderклас повинен реалізувати View.OnClickListener. Це тому , що ви подасте OnClickListenerдо itemViewпараметру ViewHolderконструктора «S. Дозвольте мені показати, що я маю на увазі:

public class ExampleClickViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    TextView text1, text2;

    ExampleClickViewHolder(View itemView) {
        super(itemView);

        // we do this because we want to check when an item has been clicked:
        itemView.setOnClickListener(this);

        // now, like before, we assign our View variables
        title = (TextView) itemView.findViewById(R.id.text1);
        subtitle = (TextView) itemView.findViewById(R.id.text2);
    }

    @Override
    public void onClick(View v) {
        // The user may not set a click listener for list items, in which case our listener
        // will be null, so we need to check for this
        if (mOnEntryClickListener != null) {
            mOnEntryClickListener.onEntryClick(v, getLayoutPosition());
        }
    }
}

Єдине, що вам потрібно додати, - це користувальницький інтерфейс для вашого Adapterметоду та налаштування :

private OnEntryClickListener mOnEntryClickListener;

public interface OnEntryClickListener {
    void onEntryClick(View view, int position);
}

public void setOnEntryClickListener(OnEntryClickListener onEntryClickListener) {
    mOnEntryClickListener = onEntryClickListener;
}

Отже, ваша нова, що підтримує клік Adapter завершена.

Тепер давайте скористаємося ...

    ExampleClickAdapter clickAdapter = new ExampleClickAdapter(yourObjects);
    clickAdapter.setOnEntryClickListener(new ExampleClickAdapter.OnEntryClickListener() {
        @Override
        public void onEntryClick(View view, int position) {
            // stuff that will happen when a list item is clicked
        }
    });

Це в основному, як ви налаштували нормальну Adapter , за винятком того, що ви використовуєте створений вами метод налаштування, щоб контролювати, що ви будете робити, коли користувач натисне певний елемент списку.

Ви також можете переглянути набір прикладів, які я зробив на цьому Gist на GitHub:

https://gist.github.com/FarbodSalamat-Zadeh/7646564f48ee708c1582c013e1de4f07


Ви повинні використовувати getAdapterPosition () замість getLayoutPosition ()
BladeCoder

2

Це те, що я роблю для повторного використання OnClickListener

  public class TestAdapter extends RecyclerView.Adapter<TestAdapter.MyviewHolder>
                                         implements View.OnClickListener

у ViewHoder Візьміть батьківський елемент елемента

  public class MyviewHolder extends RecyclerView.ViewHolder {

       LinearLayout linearLayout_item;

        public MyviewHolder(View itemView) {
            super(itemView);
            linearLayout_item=itemView.findViewById(R.id.linearLayout_item);
        }
    }

у тезі onBindViewHolder як позиція

   @Override
    public void onBindViewHolder(MyviewHolder holder, int position) {

       holder.linearLayout_item.setTag(position);
       holder.linearLayout_item.setOnClickListener(this);
    }

і в Onclick

 @Override
public void onClick(View v) {

    int position = (int) v.getTag();
    switch (v.getId()) {
        case R.id.linearLayout_item:

            // do some thing with position 

            break;
    }
}

2

Для мене чистий спосіб зробити це саме цей.

Конструктор адаптера

private class EnvironmentTypeRecyclerViewAdapter extends RecyclerView.Adapter<EnvironmentTypeRecyclerViewAdapter.ViewHolder>
{
     private final EnvironmentTypeRecyclerViewAdapterListener mEnvironmentTypeRecyclerViewAdapterListener;
     private List<Environment> mEnvironmentsData;

     public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
     {
         public ViewHolder(View v)
         {
             super(v);
             v.setOnClickListener(this);

         }

         @Override
         public void onClick(View v)
         {
              Environment environment = mEnvironmentsData.get(getAdapterPosition());
              if (mEnvironmentTypeRecyclerViewAdapterListener != null && environment != null) {
                      mEnvironmentTypeRecyclerViewAdapterListener.onListItemSelected(environment);      
              }
        }

        public EnvironmentTypeRecyclerViewAdapter(List<SmallCellEnvironment> environments, EnvironmentTypeRecyclerViewAdapterListener environmentTypeRecyclerViewAdapterListener)
        {
            mEnvironmentTypeRecyclerViewAdapterListener = environmentTypeRecyclerViewAdapterListener;
            mEnvironmentsData = environments;
        }
}

Пов'язаний інтерфейс

private interface EnvironmentTypeRecyclerViewAdapterListener
{
    void onListItemSelected(Environment environment);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.