Xem lại trên Click


583

Có ai đang sử dụng RecyclerViewtìm thấy một cách để thiết lập một onClickListenermục trong RecyclerView? Tôi đã nghĩ đến việc đặt một người nghe cho từng bố cục cho từng mục nhưng điều đó có vẻ hơi rắc rối. Tôi chắc chắn có một cách RecyclerViewđể lắng nghe onClicksự kiện nhưng tôi không thể hiểu được.



4
RecyclerViewDemo Tôi thấy dự án này rất tuyệt, sử dụng các giao diện để cung cấp nhiều hành động miễn phí hơn.
MewX

2
kiểm tra hướng dẫn này wiki.workrame.com/android-recyclerview-example
Bikesh M

Đơn giản và dễ sử dụng - github.com/rahulkapoor1/ClickableAdOG
Rahul

stackoverflow.com/a/31199564/5788247
Shomu

Câu trả lời:


477

Vì API đã thay đổi hoàn toàn, tôi sẽ không ngạc nhiên nếu bạn tạo một OnClickListenermục cho mỗi mục. Nó không phải là quá nhiều rắc rối mặc dù. Trong quá trình thực hiện RecyclerView.Adapter<MyViewHolder>, bạn nên có:

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);
}

Các onClickphương pháp:

@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
Điều gì nếu tôi muốn xóa một hàng trên nhấp chuột của nó?
Piyush Kukadiya

20
Tôi thích câu trả lời này tốt hơn câu trả lời của bạn. Ai muốn viết một người nghe cử chỉ và nhấn hộp phát hiện để xử lý việc này. Google--
Lo-Tan

17
getChildP vị trí (xem) là phương pháp không dùng nữa
Jigar

45
Bạn có phiền khi nói những lớp nào là đoạn trích của bạn không? onClick(), thuộc về OnClickListenercó thể được đính kèm với BẤT K View Chế độ xem nào. Toàn bộ câu hỏi ở đây là cái nào! Hãy nỗ lực, một phương thức không chỉ được xác định bằng tên, mà còn ít nhất là bởi một lớp. Nếu bạn không nói rằng mã của bạn sẽ được thêm vào bộ điều hợp, câu trả lời của bạn không thực sự hữu ích.
Vince

16
Phương thức onClick có nên nằm trong đoạn chứa RecyclerView không? Bởi vì bạn tham chiếu mRecyclerView trong lớp MyOnClickListener của bạn. Nơi mà bạn có được tài liệu tham khảo cho đối tượng đó?
Ced

606

Đây là một cách tốt hơn và ít kết hợp chặt chẽ hơn để thực hiện OnClickListenercho a RecyclerView.

Đoạn trích sử dụng:

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 thực hiện:

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
Điều này sẽ không cung cấp bất kỳ manh mối nào về nút hoặc chế độ xem (trong mục) đã được nhấp. Nhưng đối với mục nhấp chuột tổng thể, điều này là tốt.
Niranjan

27
Nhận xét của ngen là chính xác - nếu bạn muốn đính kèm trình nghe onClick vào một mục cụ thể trong chế độ xem mục, có lẽ bạn nên thực hiện điều đó trong bộ điều hợp, trong onBindViewHolder hoặc trong chính trình xem của bạn.
Jacob Tabak

16
Một vấn đề với phương pháp này là khi bạn đang làm một việc gì đó mất vài trăm mili giây như bắt đầu một hoạt động. Khi mục được nhấp và nó có hoạt ảnh được nhấp, có một độ trễ đáng chú ý giữa việc nhấp và xem hoạt hình.
Gak2

20
Giải pháp này cảm thấy cực kỳ cồng kềnh, có một số chậm trễ khi xử lý 'nhấp chuột' và cảm giác không ổn
wasyl

6
Ai đó có thể giải thích cho tôi tại sao giải pháp này với GestureDetector được cho là một giải pháp tốt hơn so với việc chỉ sử dụng "setOnClickListener" bên trong onBindViewHolder () trong bộ điều hợp cho phần tử theo không? Cách này ít nhất tôi cần ít mã hơn so với giải pháp GestureDetector. Cảm ơn đã giải thích.
thiên nhiên điện tử

115

Tôi làm theo cách này, không có lớp quá mức, máy dò, vv Mã đơn giản bên trong bộ chuyển đổi của chúng tôi. Đặc biệt là giải pháp tốt hơn cho longClick so với trình bày trước đây.

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);
    }
}

Sau đó, bên trong đoạn hoặc hoạt động, chỉ cần nhấn:

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);
    }
});

thay vì OurAd Module.clickListener tôi nghĩ Marurban có nghĩa là PasswordAd Module.clickListener và thay vì TrainingAd Module.ClickListener (), nên là PasswordAd Module.ClickListener (). Ngoài ra, giải pháp tuyệt vời Marurban! làm việc cho tôi
nommer

Trình nghe onItemClick cũng đang được kích hoạt khi nhấp dài.
Rashad.Z

10
ViewHolder phải tĩnh để có hiệu suất tốt nhất. đây không phải là một câu trả lời hay
Gilberto Ibarra

10
ClickListener tĩnh tạo ra rò rỉ bộ nhớ. Khai báo người nghe là không tĩnh và liên kết nó với ViewHolder.
BladeCoder

1
@AJW Cách đơn giản nhất là khởi tạo sớm trình nghe và chuyển nó làm đối số cho hàm tạo Bộ điều hợp và sau đó là hàm tạo ViewHolder.
BladeCoder

97

Kiểm tra một câu hỏi tương tự @ Nhận xét của CommonsWare liên kết đến câu hỏi này , trong đó thực hiện OnClickListenergiao diện trong viewHolder.

Đây là một ví dụ đơn giản về 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++){

        }


      }
  }

Sau Adapterđó trông như thế này:

    @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
Điều này dường như đi sai hướng mặc dù. Nếu bạn cần sử dụng lại recyclerview trong một đoạn / hoạt động khác, bộ điều hợp / trình xem hiện đang xác định logic của các nhấp chuột thay vì bất cứ thứ gì có chứa chúng. Các nhấp chuột phải thực sự được xử lý trực tiếp hoặc gián tiếp bởi thể hiện chứa. Có vẻ như một người nghe cảm ứng là cách hiệu quả duy nhất để đi về điều này.
ian.shaun.thomas

18
@tencent Mình không thấy vấn đề đó thế nào. Nếu chính ViewHolder chứa tất cả thông tin liên quan đến dữ liệu nào được chọn khi nhấp vào phần tử, thì trách nhiệm duy nhất của vùng chứa là hiển thị các phần tử N, thay vì xử lý lựa chọn phần tử thứ i cụ thể của các nguyên tố N. Điều ListViewnày đã có vấn đề nếu bạn phải tạo một danh sách các đối tượng phức tạp hơn chỉ là các hàng đơn giản. Điều gì xảy ra nếu bạn cần xử lý các sự kiện khác nhau tùy thuộc vào nơi bạn nhấp vào mục trong ListView? Bạn đang say sưa. Ở đây, bạn có từng người nghe.
EpicPandaForce

2
Tôi đồng ý với @EpicPandaForce về điều này. Tôi cũng đã đưa ra câu trả lời này sau khi đọc phần sách của Commonsware về xử lý các nhấp chuột trong RecyclerViews Nó đã hoạt động rất tốt cho tôi cho đến nay.
AdamMc331

1
findViewById chỉ được sử dụng để tạo chủ sở hữu chế độ xem tại đây (do đó onCreateViewHolder). Chủ sở hữu chế độ xem nhằm ngăn chặn việc tìm kiếm mỗi khi một mục bị ràng buộc với chủ sở hữu, không phải trên sáng tạo ban đầu.
mắc kẹt vào

2
getPosition()bị phản đối, sử dụng getAdapterPosition()hoặc getLayoutPosition()thay vào đó.
K Neeraj Lal

94

Dựa trên câu trả lời của Jacob Tabak (+1 cho anh ấy), tôi đã có thể thêm người nghe 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) {
    }
}

Sau đó, bạn có thể sử dụng nó như thế này:

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
Mất một thời gian để thích ứng với ứng dụng của tôi và căn chỉnh và định dạng mã theo các tiêu chuẩn Java / Android, nhưng cuối cùng nó vẫn hoạt động tốt.
milosmns

Làm thế nào để bạn thêm một hình ảnh động cho nhấp chuột dài?
Jon

1
Hiệu ứng nhấp @ Eng.Fouad không hoạt động bằng cách sử dụng hiệu ứng này, mặc dù nếu chúng ta đặt trình nghe nhấp trong hiệu ứng nhấp vào bộ điều hợp thì sẽ có giải pháp cho việc này
ingsaurabh

4
Bạn cũng nên ghi đèpublic void onRequestDisallowInterceptTouchEvent (boolean disallowIntercept){}
Paolo Rotolo

Vì một số lý do, nó không trả về chế độ xem được nhấp. Trong trường hợp của tôi, tôi nhấp vào một hộp kiểm nhưng xem được đưa ra là một cái gì đó khác nhau. Cách tôi kiểm tra:view.getId() == R.id.selection
dVaffection

63

Đây là những gì làm việc cho tôi. Đính kèm OnClickListenervào onBindView. Tôi thực sự không biết nếu điều này sẽ ảnh hưởng đến hiệu suất, nhưng nó dường như hoạt động tốt với ít mã.

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
trong trường hợp của tôi là chủ sở hữu.itemView.setOnClickListener (..)
D4rWiNS

18
nó được đặt tên là 'itemView' thay vì 'view' trong trường hợp của tôi, chỉ nói cho người mới bắt đầu, một số người trong số họ không hiểu họ đang sao chép gì và không thể hiểu tại sao nó không hoạt động
D4rWiNS

3
Đó là vị trí bố trí
Bubunyo Nyavor

1
đối với tôi điều này dường như chỉ áp dụng cho mục hiển thị cuối cùng chứ không phải mục được nhấp
Nasz Njoka Sr. 4/12/2015

2
Giải pháp này có vẻ tốt nhất đối với tôi, nhưng nó khác với câu trả lời của @bolot về hiệu suất như thế nào? Anh ta đã triển khai View.OnClickListener trực tiếp trên lớp ViewHolder, hơn là tách riêng phương thức onClick. Đó sẽ là giải pháp tốt nhất?
Edmond Tamas

46

Điều này thật khó đối với tôi khi có người nghe nhấp vào mục trong hoạt động và cũng có người nghe nhấp chuột để xem một lần duy nhất của mục sẽ không kích hoạt người nghe nhấp vào mục. Sau khi chơi xung quanh với câu trả lời của Jacob Tabak, tôi tôn trọng câu trả lời của anh ấy cho lần nhấp vào vật phẩm nếu không có hành động chạm nào khác bên trong vật phẩm được trình bày.

Tôi có một OnClickListenergiao diện tùy chỉnh có sự kiện nhấp vào mục giữ chế độ xem mục được nhấp và vị trí mục từ bộ điều hợp. Tôi trình bày một thể hiện của nó trong hàm tạo (hoặc nó có thể với setter) và đính kèm nó vào trình lắng nghe của ngăn chứa chủ chứa khung nhìn.

Tôi cũng có trình nghe nhấp chuột khác trong Bộ điều hợp (Có thể trong ngăn chứa chế độ xem) sẽ xử lý lần nhấp Xem hiện tại từ vùng chứa.

 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();
}}

Trong hoạt động bạn cần khởi tạo bộ điều hợp bằng cách chuyển thể hiện của 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);
}

Và ViewHolder của tôi

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);
}}

Cách tiếp cận này hiệu quả với tôi - nó có nghĩa là bạn có thể xử lý các nhấp chuột trong hoạt động thay vì bên trong chế độ xem lưới
cắt lá

3
Tôi có thể cho bạn tiền ở đâu. 4 giờ tìm kiếm và sau đó tôi đọc bài viết của bạn. Cảm ơn bạn đã dành thời gian để đăng bài này.
Brandon

3
Điều này nghe có vẻ ngu ngốc, nhưng điều này có bất kỳ bộ nhớ hoặc hiệu quả như vấn đề? Bởi vì chúng tôi đang chỉ định người nghe nhấp chuột mỗi khi một khung nhìn được vẽ phải không?
rgv

1
@Raghav có mỗi khi chế độ xem được liên kết một trình lắng nghe nhấp chuột mới được chỉ định, nhưng đây là luồng chuẩn. Nhưng mOnItemClickListener chỉ được tạo một lần cho bộ điều hợp, chỉ có chế độ xem và vị trí của nó là khác nhau trên mỗi lần nhấp vào vật phẩm;)
Sir NIkolay Cesar

3
Ví dụ tuyệt vời để giết hiệu suất ứng dụng và tạo lạm dụng bộ nhớ! Với ví dụ này, bạn chỉ cần cuộn để tạo ra hàng trăm đối tượng vô dụng, rằng trong một khoảnh khắc sẽ vô dụng và phải được truy cập dưới dạng garbige. @NoobDogg nói đúng. Không có ClickListener chưa được tạo tại onBindView. Một trình nghe nhấp chuột phải được tạo một lần trong onCreateView (hoặc hàm tạo) và tồn tại trong khi chúng ta cần màn hình với bộ điều hợp này.
Mykola Tychyna

36

Đây là những gì tôi đã cần, trong trường hợp ai đó thấy nó hữu ích:

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());
            }
        });

    }
}

Nguồn: http://blog.csdn.net/jwzhangjie/article/details/36868515


Trong tất cả các phiên bản tôi đã thử, đây là phiên bản tôi đã làm việc. Nhưng nó có ổn không, để làm theo cách đó? Hoặc có một cách tốt hơn, như thực hành tốt nhất?
Matthias Loibl

1
Theo như tôi có thể nói, đây là cách duy nhất. Kiểm tra này để biết thêm chi tiết! stackoverflow.com/a/24933117/1508887
Cừu Fifer

Làm thế nào tôi có thể mở đoạn mới từ bên trong phương thức onclick?
băm

5
getAd CHƯƠNGP vị trí () thay thế getP vị trí ()
Kennedy Nyaga

27

Tôi có giải pháp tốt đẹp cho RecyclerView's onItemClickListenercho các mục và subitems

Bước 1- Tạo giao diện

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);
}

Bước 2- Sau đó sử dụng nó trong onBindViewHolderphương thức của bộ chuyển đổi theo cách sau

/**
     * 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);
        }

    }

Bước 3- tìm và thiết lập chế độ xem tái chế trong hoạt động hoặc đoạn mà bạn đang sử dụng

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());

Bước 4- Cuối cùng thực hiện giao diện trong hoạt động hoặc đoạn mà bạn đang sử dụng recyclerview

@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
Đây là giải pháp tốt nhất vì chúng ta thường cần rất nhiều thuộc tính từ hoạt động / đoạn trên onItemClickListener của chúng tôi và không có ý nghĩa gì để gọi nó trực tiếp từ trình xem (tôi sẽ phải tạo một hàm tạo tùy chỉnh cho mỗi bộ điều hợp). Nhân tiện, mã của bạn hơi rộng, tôi khuyên bạn nên cắt nó thành phần quan trọng nhất (setOnItemClickListener).
sagits

đây là một cách tiếp cận đơn giản tốt để phân biệt hàng / vật phẩm với các vật phẩm phụ
Nigel Savage

17

Đây là những gì tôi đã làm. Giải pháp này hỗ trợ cả onClick và onLongClick trên cả Mục RecyclerView và Lượt xem bên trong Mục RecyclerView (chế độ xem nội bộ).

Tôi gắn thẻ viewHolder theo quan điểm của sự lựa chọn của tôi:

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;
}

Và tôi sử dụng chủ sở hữu.getP vị trí () để truy xuất vị trí trong phương thức onClick () (onLongClick là tương tự):

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();
    }
}

Một biến thể với getChildPocation cũng hoạt động. Xin lưu ý rằng đối với các chế độ xem nội bộ, trong onClick () sử dụng:

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

Theo suy nghĩ của tôi, điểm nổi bật của giải pháp này là khi một lần nhấp vào hình ảnh, chỉ có trình nghe hình ảnh onclick () được gọi trong khi tôi kết hợp giải pháp của Jacob cho chế độ xem Mục RecyclerView và giải pháp của tôi để xem nội bộ Chế độ xem Mục RecyclerView ) cũng được gọi (khi nhấp vào hình ảnh).


11

Có nhiều cách dễ dàng hơn để làm điều này. Chỉ cần áp dụng khi nhấp vàoonBindViewHolder vào xem trên root.

Xem xét đây là quan điểm của bạn cho bộ chuyển đổi,

<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>

Sau đó làm theo trong bộ chuyển đổi của bạn

//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

Bạn có thể vượt qua một clickListenerđến Adapter.

Trong của bạn 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);
        }
    }
};

sau đó chuyển nó tới Adapter:

MainAdapter mainAdapter = new MainAdapter(this, mItemClick);

Trong Adapter's 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;
}

Làm thế nào để bạn vượt qua các holdergiá trị thông qua ý định?
RoCk RoCk

8

Tôi đã phát triển một thư viện có trọng lượng nhẹ cho Android, bạn có thể truy cập https://github.com/ChathuraHettiarachchi/RecycleClick

và làm theo mẫu sau

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

Có thể xác nhận, thư viện này là tuyệt vời! Rất dễ sử dụng, công việc tốt!
peterkodermac

7

Bạn có thể triển khai OnClickListener cho lớp ViewHolder của mình

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());
        }
    }

Và onBindViewHolder đặt mục của chủ sở hữu chế độ xem của bạn

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

7

Cách quá đơn giản và hiệu quả.

Thay vì triển khai giao diện View.OnClickListenerbên trong khung nhìn hoặc tạo và giao diện và giao diện triển khai trong hoạt động của bạn - Tôi đã sử dụng mã này để OnClickListenerthực hiện đơn giản .

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
Đây là một thực tế xấu phổ biến vì nó có vẻ quá dễ dàng. Bạn đang tạo một trình lắng nghe bên trong mới mỗi khi một đối tượng được liên kết (và mỗi mục trong trình tái chế có thể bị ràng buộc rất nhiều lần), điều này không tốt cho a) hiệu suất b) thu gom rác. Thay vào đó, bạn nên tạo MỘT trình nghe ở đâu đó (trong khung nhìn, trong bộ điều hợp, ở đoạn trên hoặc hoạt động) và chỉ cần thêm nó vào các mục trong hàm tạo của khung nhìn trên trong onCreateViewHolder. Điều này có thêm sự phức tạp của việc phải tìm ra mục nào là clicker, nhưng có thể được giải quyết dễ dàng thông qua các thẻ hoặc thêm thông tin cho chủ sở hữu.
GuillermoMP

6

Tất cả các câu trả lời được đăng cho đến nay đều là những giải pháp tuyệt vời, tuy nhiên nếu bạn không muốn xử lý quá nhiều chi tiết triển khai và chỉ muốn nó hoạt động tương tự như cách ListView thực hiện, tôi khuyên bạn nên sử dụng TwoWay-View, như đã thấy ở đây:

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

Lưu ý rằng việc triển khai này cũng hỗ trợ nhấn lâu vào các mục, cũng như hỗ trợ cho các trạng thái được nhấn (đây là điều quan trọng mà các giải pháp khác cho câu hỏi này thiếu).

Nếu bạn không muốn sử dụng toàn bộ thư viện, hãy xem lớp ClickItemTouchListener , có thể được sử dụng như một độc lập nếu cần. Vấn đề duy nhất tôi tìm thấy với nó tại thời điểm này là với việc nhấn + cuộn lâu, nó dường như có hành vi không chính xác.


6

Nếu bạn muốn bắt sự kiện nhấp vào Trên các mục riêng lẻ, chỉ cần thực hiện OnClickListenertrong ViewHolderlớp và sau đó đặt người nghe nhấp vào trên từng chế độ xem hoặc toàn bộ itemView.

Ví dụ sau đây cho thấy tương tự

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

Đối với tôi, đây là cách tốt nhất:

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
getChildP vị trí () bị
đánh cắp

5

Việc RecyclerViewkhông có OnClickListenervà sẽ phải tự thực hiện.

Tôi muốn thêm một OnItemClickListenergiao diện Adaptervới một onClickphương thức được gọi khi bạn nhấp vào chế độ xem mục từ ViewHolder. Do đó, trách nhiệm quản lý nhấp chuột vào một mục nằm ngoài ViewHolderAdapter . Hoạt động hay đoạn sẽ quyết định phải làm gì

Thêm một giao diện cho người nghe và đối tượng người nghe.

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

  ...

  private static OnItemClickListener onItemClickListener;

  ...

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

  ...
}

Chúng tôi nắm bắt nhấp chuột của chế độ xem gốc của mục và khi gọi lại được kích hoạt onClickcuộc gọi người nghe trên bộ điều hợp.

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);
              }
          });
      }
  }
}

Vì hoạt động hoặc phân đoạn, phân đoạn trong trường hợp của chúng tôi, chúng tôi chỉ định người nghe cho bộ điều hợp và cuộc gọi lại onClick, chúng tôi sẽ nhận được mục đã chọn theo vị trí và mở một hoạt động chi tiết của mục.

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

Thật không may RecyclerViewlà thiếu một vài tính năng ListViewđã tích hợp sẵn. Ví dụ: khả năng thêm một OnItemClickListenerkích hoạt khi một mục được nhấp. RecyclerViewcho phép bạn đặt một OnClickListenerbộ chuyển đổi, nhưng chuyển qua trình nghe nhấp chuột đó từ mã cuộc gọi của bạn, đến bộ chuyển đổi và tới ViewHolder, rất phức tạp để bắt một nhấp chuột mục đơn giản.

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);
}
}

Bạn cũng cần xác định R.id.item_click_supportbằng cách sử dụng ids.xml:

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

Trình nghe mã nhấp chuột kết quả bây giờ trông như thế này:

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

Để được giải thích ngắn gọn về các lần nhấp của recyclerview, vui lòng xem qua littlerobots_blog


5

bạn có thể dễ dàng xác định setOnClickListener trong lớp ViewHolder của mình như sau:

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

Đây là những gì tôi đã làm Đọc thêm & tải về ý chính ở đây

Thêm tương tự ở đây

CustomItemClickListener.java

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

MụcListAdOG.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

Từ hầu hết các câu trả lời ở trên, dường như họ đang thiết lập danh sách phát hành của mình cho các mục riêng lẻ. Tuy nhiên, giải pháp sắp đưa ra rất đơn giản nhưng chưa trực quan với nhiều người. Nhiều người quên rằng các thành phần khác luôn nằm trong thành phần chính được sử dụng để hiển thị các mục trong chế độ xem Danh sách hoặc Trình tái chế. Giải pháp này chỉ là về việc thiết lập một trình nghe onclick duy nhất cho chế độ xem chính này và lượt chơi được phát. Giải pháp cũng bao gồm một cách để vượt qua vị trí của mục được nhấp vào từ danh sách hoặc chế độ xem tái chế. Ở đây, rootview chính của chúng tôi là một CardView từ thư viện hỗ trợ Android. Đây là mã mẫu

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

Kotlin thực hiện câu trả lời của 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

Đây là mã hoàn chỉnh cho bộ điều hợp tùy chỉnh của tôi, mã này sẽ làm tăng các hàng với các mục danh sách được xác định trong tệp xml có tên "list_item", nó cũng sẽ thực hiện sự kiện nhấp chuột trên tất cả các hàng của danh sách với các vị trí tương ứng.

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

Chúng ta có thể làm điều này bằng cách sử dụng các tham chiếu yếu của Java. Về mặt ngữ nghĩa, người giữ chế độ xem là người nên phản hồi với sự kiện nhấp hoặc ủy thác cho sự phản hồi chính xác.

Mục tiêu của chúng tôi:

  1. Người xem không nên biết gì về lớp phản ứng với các sự kiện ngoại trừ việc nó thực hiện một giao diện nhất định.
  2. Trình xử lý nhấp chuột sẽ nhận được vị trí trong RecyclerView của chế độ xem được nhấp.
  3. Chúng tôi sẽ có thể phân biệt nhìn được nhấp trong người giữ quan điểm.
  4. Duy trì khớp nối lỏng lẻo giữa tất cả các thành phần và không gây ra bất kỳ chu kỳ giữ lại.

Các bước:

  1. Tạo một giao diện để xử lý các phản hồi nhấp chuột.

  2. Thực hiện giao diện này trong Hoạt động sẽ xử lý nhấp chuột.

  3. Thêm một biến thành viên trong Bộ điều hợp RecyclerView để giữ Tham chiếu yếu và một hàm tạo đặt nó.

  4. Thực hiện tương tự trong RecyclerView ViewHolder và thêm một biến thành viên để theo dõi vị trí.

  5. Đặt trình nghe nhấp chuột của bạn trên bất kỳ chế độ xem nào bạn muốn trong ViewHolder, sau đó gọi lại cho người trả lời để xử lý chúng.

  6. Thay đổi phương thức onBindViewHolder của bạn để đặt vị trí khi liên kết.

  7. Chuyển phản hồi xuống cho ViewHolder.

  8. Trong phần trả lời, bây giờ bạn có thể sử dụng getId () trên chế độ xem để tìm ra chế độ xem nào được nhấp.

Và đây là một Gist để bạn có thể thấy tất cả khớp với nhau như thế nào: Xử lý nhấp chuột RecyclerView


2

Tôi biết có rất nhiều câu trả lời, nhưng tôi nghĩ tôi cũng có thể cung cấp cho mình việc thực hiện nó. (Chi tiết đầy đủ có thể được tìm thấy trên một câu hỏi khác tôi đã trả lời ).

Vì vậy, để thêm một trình nghe nhấp chuột, ViewHolderlớp bên trong của bạn cần phải thực hiện View.OnClickListener. Đây là bởi vì bạn sẽ thiết lập một OnClickListenerđến itemViewtham số của ViewHolderconstructor 's. Hãy để tôi chỉ cho bạn những gì tôi có nghĩa là:

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());
        }
    }
}

Những thứ khác bạn cần thêm là một giao diện tùy chỉnh cho Adapterphương thức setter của bạn và:

private OnEntryClickListener mOnEntryClickListener;

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

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

Vì vậy, hỗ trợ nhấp chuột mới của bạn Adapterđã hoàn tất.

Bây giờ, hãy sử dụng nó ...

    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
        }
    });

Về cơ bản, đó là cách bạn sẽ thiết lập một bình thường Adapter, ngoại trừ việc bạn sử dụng phương thức setter mà bạn đã tạo để kiểm soát những gì bạn sẽ làm khi người dùng của bạn nhấp vào một mục danh sách cụ thể.

Bạn cũng có thể xem qua một tập hợp các ví dụ tôi đã thực hiện trên GistHub này trên GitHub:

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


Bạn nên sử dụng getAd CHƯƠNGP vị trí () thay vì getLayoutP vị trí ()
BladeCoder

2

Đây là những gì tôi làm để tái sử dụng OnClickListener

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

trong ViewHoder Lấy cha mẹ của itemlayout

  public class MyviewHolder extends RecyclerView.ViewHolder {

       LinearLayout linearLayout_item;

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

trong thẻ onBindViewHolder đặt vị trí

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

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

và trong 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

Đối với tôi cách sạch sẽ để làm điều đó là cái này.

Xây dựng bộ chuyển đổi

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;
        }
}

Giao diện được liên kết

private interface EnvironmentTypeRecyclerViewAdapterListener
{
    void onListItemSelected(Environment environment);
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.