RecyclerView onClick


583

มีใครใช้วิธีRecyclerViewพบการตั้งค่าonClickListenerรายการในRecyclerView? ฉันคิดว่าการตั้งค่าผู้ฟังให้กับแต่ละเลย์เอาท์ของแต่ละรายการ แต่ดูเหมือนจะยุ่งยากมากเกินไปฉันแน่ใจว่ามีวิธีที่RecyclerViewจะฟังonClickเหตุการณ์ แต่ฉันคิดไม่ออกเลย



4
RecyclerViewDemoฉันพบว่าโครงการนี้ยอดเยี่ยมโดยใช้อินเทอร์เฟซเพื่อให้การดำเนินการฟรีมากขึ้น
MewX

2
ตรวจสอบบทช่วย
Bikesh M

ง่ายและใช้งานง่าย - github.com/rahulkapoor1/ClickableAdapter
Rahul

stackoverflow.com/a/31199564/5788247
Shomu

คำตอบ:


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
จะทำอย่างไรถ้าฉันต้องการลบแถวในการคลิก
Piyush Kukadiya

20
ฉันชอบคำตอบนี้ดีกว่าคำที่คุณเชื่อมโยง ใครต้องการที่จะเขียนฟังท่าทางและการตรวจสอบกล่องกดเพื่อจัดการกับสิ่งนี้ Google--
Lo-Tan

17
getChildPosition (มุมมอง) เลิกใช้วิธี
Jigar

45
คุณรังเกียจที่จะบอกว่าคลาสของคุณคืออะไร onClick()เป็นของOnClickListenerสามารถแนบไปกับมุมมองใดก็ได้ คำถามทั้งหมดที่นี่คือที่! โปรดใช้ความพยายามไม่เพียง แต่จะระบุชื่อด้วยวิธีการเท่านั้น แต่อย่างน้อยต้องมีชั้นเรียนด้วย หากคุณไม่ได้บอกว่ารหัสของคุณจะถูกเพิ่มลงในอะแดปเตอร์คำตอบของคุณไม่ได้ช่วยจริงๆ
Vince

16
เมธอด onClick ควรอยู่ในแฟรกเมนต์ที่มี RecyclerView หรือไม่ เนื่องจากคุณอ้างอิง mRecyclerView ในคลาส MyOnClickListener ของคุณ คุณได้รับการอ้างอิงไปยังวัตถุนั้นอยู่ที่ไหน
Ced

606

นี่คืองานที่ดีและน้อยทางคู่แน่นที่จะใช้สำหรับ OnClickListenerRecyclerView

ตัวอย่างการใช้งาน:

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
สิ่งนี้จะไม่ให้เบาะแสเกี่ยวกับการคลิกปุ่มหรือมุมมอง (ภายในรายการ) ใด ๆ แต่สำหรับการคลิกไอเท็มโดยรวมก็ถือว่าใช้ได้
Niranjan

27
ความคิดเห็นของ ngen นั้นถูกต้อง - หากคุณต้องการแนบผู้ฟัง onClick กับรายการเฉพาะภายในมุมมองรายการคุณอาจทำเช่นนั้นในอะแดปเตอร์ของคุณใน onBindViewHolder หรือในมุมมองของคุณเอง
Jacob Tabak

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 ฉันคิดว่า Marurban หมายถึง PasswordAdapter.clickListener และแทนที่จะเป็น TrainingAdapter.ClickListener () ควรเป็น PasswordAdapter.ClickListener () นอกเหนือจากนั้นทางออกที่ดี Marurban! ทำงานให้ฉัน
เสนอชื่อ

ผู้ฟัง onItemClick กำลังเปิดใช้งานเมื่อคลิกแบบยาว
Rashad.Z

10
ViewHolder ต้องเป็นแบบคงที่เพื่อประสิทธิภาพที่ดีที่สุด นี่ไม่ใช่คำตอบที่ดี
Gilberto Ibarra

10
clickListener แบบคงที่สร้างหน่วยความจำรั่ว ประกาศให้ฟังเป็นแบบไม่คงที่และผูกไว้กับ ViewHolder แทน
BladeCoder

1
@AJW วิธีที่ง่ายที่สุดคือการเริ่มต้นฟังก่อนและส่งผ่านมันเป็นอาร์กิวเมนต์ไปยังตัวสร้างอะแดปเตอร์แล้วตัวสร้าง ViewHolder
BladeCoder

97

ตรวจสอบที่คล้ายกันคำถาม @ CommonsWare ของความคิดเห็นลิงก์ไปนี้ซึ่งจะใช้งานอินเตอร์เฟซในOnClickListenerviewHolder

นี่คือตัวอย่างง่ายๆของ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
สิ่งนี้ดูเหมือนจะไปในทิศทางที่ผิด หากคุณต้องการใช้ recyclerview อีกครั้งในแฟรกเมนต์ / กิจกรรมอื่นอะแด็ปเตอร์ / ผู้ดูจะกำหนดตรรกะของการคลิกแทนที่จะเป็นสิ่งที่มีอยู่ การคลิกควรได้รับการจัดการโดยตรงหรือโดยอ้อมด้วยอินสแตนซ์ที่มีอยู่ ดูเหมือนว่าผู้ฟังแบบสัมผัสเป็นวิธีเดียวที่มีประสิทธิภาพในการดำเนินเรื่องนี้
ian.shaun.thomas

18
@tencent ฉันไม่เห็นว่าเป็นปัญหา หาก ViewHolder นั้นมีข้อมูลทั้งหมดเกี่ยวกับข้อมูลที่ถูกเลือกเมื่อองค์ประกอบนั้นถูกคลิกดังนั้นความรับผิดชอบเพียงอย่างเดียวของคอนเทนเนอร์คือการแสดงองค์ประกอบ N ไม่ใช่การจัดการเลือกองค์ประกอบ i-th ที่เฉพาะเจาะจงออกไป ขององค์ประกอบ N ListViewอยู่แล้วมีปัญหาถ้าคุณมีการสร้างรายการของวัตถุที่มีความซับซ้อนมากขึ้นกว่าเพียงแถวที่เรียบง่าย ถ้าคุณต้องการจัดการเหตุการณ์ต่าง ๆ ขึ้นอยู่กับว่าคุณคลิกที่รายการใดใน ListView คุณเมาแล้ว ที่นี่คุณมีผู้ฟังแต่ละคน
EpicPandaForce

2
ฉันเห็นด้วยกับ @EpicPandaForce ในอันนี้ ฉันมาเพื่อกำจัดคำตอบนี้หลังจากอ่านส่วนของหนังสือ Commonsware เกี่ยวกับการจัดการคลิกใน RecyclerViews มันใช้งานได้ดีมากสำหรับฉันจนถึงตอนนี้
AdamMc331

1
findViewById ถูกนำมาใช้เฉพาะในการสร้างตัวยึดมุมมองที่นี่ (ดังนั้น onCreateViewHolder) ตัวยึดมุมมองมีวัตถุประสงค์เพื่อป้องกันการค้นหามุมมองทุกครั้งที่รายการถูกผูกไว้กับตัวยึดไม่ใช่การสร้างครั้งแรก
stuckj

2
getPosition()เลิกใช้getAdapterPosition()หรือgetLayoutPosition()แทนที่
K Neeraj Lal

94

จากคำตอบของ Jacob Tabak (+1 สำหรับเขา) ฉันสามารถเพิ่มผู้ฟัง LongClick:

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

คุณจะเพิ่มภาพเคลื่อนไหวสำหรับการคลิกที่ยาวนานได้อย่างไร
Jon

1
@ ผลคลิก Eng.Fouad ไม่ทำงานโดยใช้นี้แม้ว่าถ้าเราฟังคลิกตั้งอยู่ในผลอะแดปเตอร์คลิกทำงานแก้ปัญหาใด ๆ นี้
ingsaurabh

4
คุณควรจะแทนที่ public void onRequestDisallowInterceptTouchEvent (boolean disallowIntercept){}
Paolo Rotolo

ด้วยเหตุผลบางอย่างมันไม่ส่งคืนมุมมองที่ถูกคลิก ในกรณีของฉันฉันคลิกที่ช่องทำเครื่องหมาย แต่มุมมองที่กำหนดเป็นสิ่งที่แตกต่างกัน วิธีที่ฉันตรวจสอบ: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
ในกรณีของฉัน holder.itemView.setOnClickListener (.. )
D4rWiNS

18
มันมีชื่อว่า 'itemView' แทนที่จะเป็น 'view' ในกรณีของฉันเพียงแค่พูดสำหรับผู้เริ่มต้นบางคนไม่เข้าใจสิ่งที่พวกเขากำลังคัดลอกและไม่สามารถคิดได้ว่าทำไมไม่ทำงาน
D4rWiNS

3
มันเป็นตำแหน่งเลย์เอาต์
Bubunyo Nyavor

1
สำหรับฉันดูเหมือนว่าจะใช้กับรายการที่มองเห็นได้ครั้งสุดท้ายเท่านั้นไม่ใช่รายการที่คลิก
Nasz Njoka Sr.

2
วิธีนี้ดูเหมือนจะดีที่สุดสำหรับฉัน แต่สิ่งนี้แตกต่างจากคำตอบของ @bolot ในการทำงานที่มีประสิทธิภาพอย่างไร เขาได้ใช้ ViewOnClickListener โดยตรงในคลาส ViewHolder ซึ่งแยกวิธีการ onClick ออกจากกัน ซึ่งจะเป็นทางออกที่ดีที่สุด?
Edmond Tamas

46

นี่เป็นเรื่องยากสำหรับฉันที่จะมีผู้ฟังรายการคลิกในกิจกรรมและยังมีผู้ฟังคลิกสำหรับมุมมองเดียวของรายการที่จะไม่เรียกผู้ฟังรายการคลิก หลังจากเล่นกับคำตอบของ Jacob Tabak ฉันเคารพคำตอบของเขาในการคลิกไอเท็มหากไม่มีการดำเนินการสัมผัสอื่น ๆ ภายในไอเท็ม

ฉันมีประเพณี OnClickListenerอินเทอร์เฟซที่มีในรายการคลิกเหตุการณ์ซึ่งเก็บมุมมองของรายการที่ถูกคลิกและตำแหน่งรายการจากอะแดปเตอร์ ฉันนำเสนออินสแตนซ์ของมันในตัวสร้าง (หรืออาจเป็นกับ setter) และแนบไปที่ฟังดูคลิกฟังคอนเทนเนอร์

ฉันยังมีฟังคลิกอื่น ๆ ในอะแดปเตอร์ (สามารถอยู่ในมุมมองผู้ถือ) ซึ่งจะจัดการคลิกดูปัจจุบันจากภาชนะ

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

วิธีนี้ใช้ได้ผลดีสำหรับฉัน - หมายความว่าคุณสามารถจัดการการคลิกในกิจกรรมได้มากกว่าภายในมุมมองกริด
leafcutter

3
ฉันจะให้เงินคุณได้ที่ไหน 4 ชั่วโมงในการค้นหาจากนั้นฉันอ่านโพสต์ของคุณ ขอบคุณสำหรับเวลาที่คุณโพสต์ข้อความนี้
Brandon

3
ฟังดูงี่เง่า แต่มีหน่วยความจำหรือประสิทธิภาพเช่นปัญหาหรือไม่ เพราะเรากำลังกำหนดฟังการคลิกทุกครั้งที่มีการดึงมุมมองใช่ไหม
rgv

1
@Raghav ใช่ทุกครั้งที่มีการดูการผูก listener การคลิกใหม่จะถูกกำหนด แต่นี่เป็นโฟลว์มาตรฐาน แต่ mOnItemClickListener ถูกสร้างเพียงครั้งเดียวสำหรับอแด็ปเตอร์เพียงแค่มุมมองและตำแหน่งของมันจะแตกต่างกันในการคลิกแต่ละรายการ;)
Sir NIkolay Cesar The First

3
ตัวอย่างที่ดีในการฆ่าประสิทธิภาพแอพและสร้างความจำที่มากเกินไป! ด้วยตัวอย่างนี้คุณเพียงแค่ต้องใช้สโครลเพื่อสร้างวัตถุที่ไร้ประโยชน์หลายร้อยรายการซึ่งในไม่ช้าก็จะไร้ประโยชน์และจะต้องเข้าถึงได้ในรูปแบบ garbige @NoobDogg ถูกต้อง ClickListeners ไม่ได้ถูกสร้างขึ้นที่ onBindView ต้องสร้าง listener การคลิกหนึ่งครั้งใน onCreateView (หรือ constructor holder) และมีอยู่ในขณะที่เราต้องการหน้าจอที่มีอะแดปเตอร์นี้
Mykola Tychyna

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


ทุกรุ่นที่ฉันลองนี่เป็นรุ่นที่ฉันใช้งานได้ แต่มันก็โอเคที่จะทำอย่างนั้น? หรือมีวิธีที่ดีกว่าเช่นการปฏิบัติที่ดีที่สุด?
Matthias Loibl

1
เท่าที่ฉันจะบอกได้นี่เป็นวิธีเดียวเท่านั้น ลองดูรายละเอียดเพิ่มเติม! stackoverflow.com/a/24933117/1508887
Fifer Sheep

ฉันจะเปิดแฟรกเมนต์ใหม่จากวิธี onclick ภายในได้อย่างไร
แฮ

5
getAdapterPosition () แทนที่ getPosition ()
Kennedy Nyaga

27

ผมมีทางออกที่ดีสำหรับRecyclerView's onItemClickListenerสำหรับรายการและไอเทมย่อย

ขั้นตอนที่ 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 -ใช้อินเทอร์เฟซในกิจกรรมหรือส่วนที่คุณใช้ 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
นี่เป็นทางออกที่ดีที่สุดเพราะปกติเราต้องการคุณสมบัติมากมายจากกิจกรรม / แฟรกเมนต์ใน onItemClickListener ของเราและไม่มีเหตุผลที่จะเรียกมันโดยตรงจากผู้ชม (ฉันจะต้องสร้างคอนสตรัคเตอร์ที่กำหนดเองสำหรับแต่ละอะแดปเตอร์) โดยวิธีการที่รหัสของคุณเป็น extense เล็กน้อยฉันขอแนะนำให้คุณตัดเป็นส่วนที่สำคัญที่สุด (setOnItemClickListener)
sagits

นี่เป็นวิธีการง่ายๆที่ดีสำหรับการแยกแยะแถว / ไอเท็มจากรายการย่อย
Nigel Savage

17

นี่คือสิ่งที่ฉันทำ โซลูชันนี้รองรับทั้ง onClick และ onLongClick ทั้งใน RecyclerView Items และ Views ภายใน RecyclerView Items (มุมมองภายใน)

ฉันติดแท็กมุมมองผู้จัดวางบนมุมมองที่ฉันเลือก:

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

และฉันใช้ holder.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 () ในขณะที่เมื่อฉันรวมโซลูชันของ Jacob สำหรับมุมมองรายการ RecyclerView และโซลูชันของฉันสำหรับมุมมองภายในมุมมอง RecyclerView Item 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

คุณสามารถผ่านไปclickListenerAdapter

ใน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'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;
}

คุณจะส่งผ่าน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
นี่เป็นวิธีปฏิบัติที่ไม่ดีทั่วไปเพราะดูง่ายเกินไป คุณกำลังสร้างฟังภายในใหม่ทุกครั้งที่มีการผูกวัตถุ (และแต่ละรายการใน recycler สามารถผูกหลายครั้ง) ซึ่งไม่ดีสำหรับ a) ประสิทธิภาพ b) การรวบรวมขยะ แต่คุณควรสร้างผู้ฟังหนึ่งคนที่ใดที่หนึ่ง (ใน viewholder, ในอะแด็ปเตอร์, ในแฟรกเมนต์หรือกิจกรรม) และเพิ่มไปยังไอเท็มในตัวสร้างวิวเวอร์ใน onCreateViewHolder นี่คือความซับซ้อนที่เพิ่มขึ้นของการคิดว่ารายการใดเป็น clicker แต่สามารถแก้ไขได้อย่างง่ายดายผ่านแท็กหรือเพิ่มข้อมูลเพิ่มเติมให้กับผู้ถือ
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 Sr.

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

สำหรับคำอธิบายโดยย่อเกี่ยวกับการคลิกที่ recyclerview โปรดดูที่littlerobots_blog


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

จากคำตอบส่วนใหญ่ข้างต้นดูเหมือนว่าพวกเขากำลังตั้งค่าตัวเลือกผู้ประกาศในรายการแต่ละรายการ อย่างไรก็ตามการแก้ปัญหาที่ฉันกำลังจะนำเสนอนั้นง่ายมาก แต่ก็ไม่ง่ายนักสำหรับหลาย ๆ คน หลายคนลืมว่าส่วนประกอบอื่น ๆ มักจะอยู่ในองค์ประกอบหลักที่ใช้ในการแสดงรายการในมุมมองรายการหรือรีไซเคิล วิธีการแก้ปัญหานี้เป็นเพียงเกี่ยวกับการตั้งค่าฟังเดียวคลิกเพื่อดูผู้ปกครองนี้และเปิดเล่น การแก้ปัญหายังรวมถึงวิธีการส่งผ่านตำแหน่งของรายการที่ถูกคลิกจากรายการหรือมุมมองรีไซเคิล ที่นี่รูทวิวหลักของเราคือ 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

การใช้ Kotlin ใน คำตอบของ 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 Adaptor เพื่อเก็บ Weak Reference และ Constructor ที่ตั้งค่าไว้

  4. ทำเช่นเดียวกันใน RecyclerView ViewHolder และเพิ่มตัวแปรสมาชิกเพื่อติดตามตำแหน่ง

  5. ตั้งค่าให้ผู้ฟังคลิกของคุณในมุมมองใด ๆ ที่คุณต้องการใน ViewHolder จากนั้นโทรกลับไปที่ผู้ตอบคำถามเพื่อจัดการกับพวกเขา

  6. เปลี่ยนเมธอด onBindViewHolder ของคุณเพื่อตั้งค่าตำแหน่งเมื่อเชื่อมโยง

  7. ส่งผู้ตอบกลับไปที่ ViewHolder

  8. ในการตอบกลับตอนนี้คุณสามารถใช้ getId () บนมุมมองเพื่อกำหนดว่ามุมมองใดถูกคลิก

และนี่คือส่วนสำคัญเพื่อให้คุณเห็นว่าทุกอย่างลงตัวเข้าด้วยกันได้อย่างไร: RecyclerViewView handling handling


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);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.