我正在探索RecyclerView
,我很惊讶地发现RecyclerView
没有onItemClickListener()
。 因为RecyclerView
延伸
android.view.ViewGroup
和ListView
扩展
android.widget.AbsListView
。 不过,我通过在我的RecyclerView.Adapter
编写onClick
来解决了我的问题:
public static class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener { public TextView txtViewTitle; public ImageView imgViewIcon; public ViewHolder(View itemLayoutView) { super(itemLayoutView); txtViewTitle = (TextView) itemLayoutView.findViewById(R.id.item_title); imgViewIcon = (ImageView) itemLayoutView.findViewById(R.id.item_icon); } @Override public void onClick(View v) { } }
但我仍然想知道为什么谷歌删除onItemClickListener()
?
是否存在性能问题或其他问题?
tl; dr 2016使用RxJava和PublishSubject来展示点击的Observable。
public class ReactiveAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { String[] mDataset = { "Data", "In", "Adapter" }; private final PublishSubject<String> onClickSubject = PublishSubject.create(); @Override public void onBindViewHolder(final ViewHolder holder, int position) { final String element = mDataset[position]; holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onClickSubject.onNext(element); } }); } public Observable<String> getPositionClicks(){ return onClickSubject.asObservable(); } }
原帖:
自引入ListView
以来, onItemClickListener
一直存在问题。 当你有一个点击监听器的任何内部元素的callback将不会被触发,但没有通知或logging(如果有的话),所以有很多困惑和SO问题。
鉴于RecyclerView
更进一步,没有一个行/列的概念,而是一个任意摆放的孩子的数量,他们已经将onClick委派给他们每一个,或者程序员的实现。
将Recyclerview
视为不是ListView
1:1replace,而是作为复杂用例的更灵活的组件。 正如你所说,你的解决scheme是谷歌期望你的。 现在你有一个适配器,它可以委托onClick传递给构造函数的接口,这是ListView
和Recyclerview
的正确模式。
public static class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener { public TextView txtViewTitle; public ImageView imgViewIcon; public IMyViewHolderClicks mListener; public ViewHolder(View itemLayoutView, IMyViewHolderClicks listener) { super(itemLayoutView); mListener = listener; txtViewTitle = (TextView) itemLayoutView.findViewById(R.id.item_title); imgViewIcon = (ImageView) itemLayoutView.findViewById(R.id.item_icon); imgViewIcon.setOnClickListener(this); itemLayoutView.setOnClickListener(this); } @Override public void onClick(View v) { if (v instanceof ImageView){ mListener.onTomato((ImageView)v); } else { mListener.onPotato(v); } } public static interface IMyViewHolderClicks { public void onPotato(View caller); public void onTomato(ImageView callerImage); } }
然后在你的适配器上
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { String[] mDataset = { "Data" }; @Override public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_layout, parent, false); MyAdapter.ViewHolder vh = new ViewHolder(v, new MyAdapter.ViewHolder.IMyViewHolderClicks() { public void onPotato(View caller) { Log.d("VEGETABLES", "Poh-tah-tos"); }; public void onTomato(ImageView callerImage) { Log.d("VEGETABLES", "To-m8-tohs"); } }); return vh; } // Replace the contents of a view (invoked by the layout manager) @Override public void onBindViewHolder(ViewHolder holder, int position) { // Get element from your dataset at this position // Replace the contents of the view with that element // Clear the ones that won't be used holder.txtViewTitle.setText(mDataset[position]); } // Return the size of your dataset (invoked by the layout manager) @Override public int getItemCount() { return mDataset.length; } ...
现在看看最后一块代码: onCreateViewHolder(ViewGroup parent, int viewType)
签名已经提示不同的视图types。 对于他们中的每一个,你也需要一个不同的查看者,随后他们每个人都可以有不同的点击次数。 或者,您可以创build一个通用的视图,它可以接受任何视图,一个onClickListener
并相应地应用。 或者将一个级别委托给协调器,这样几个片段/活动具有相同的具有不同点击行为的列表。 再一次,所有的灵活性都在你身边。
这是一个真正需要的组件,并且非常接近我们的内部实现和对ListView
改进。 谷歌最终承认这一点很好。
我喜欢这种方式,我正在使用它
内
public Adapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
放
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_image_and_text, parent, false); v.setOnClickListener(new MyOnClickListener());
并在你想要的地方创build这个类
class MyOnClickListener implements View.OnClickListener { @Override public void onClick(View v) { int itemPosition = recyclerView.indexOfChild(v); Log.e("Clicked and Position is ",String.valueOf(itemPosition)); } }
我以前看过有更好的方法,但我喜欢这种方式很简单,而且不复杂。
另一种解决scheme是由Android GDE Hugo Visser 提出的解决scheme。 他为你准备了一个免许可证的课程,只需放下你的代码并使用它。
用法:
ItemClickSupport.addTo(mRecyclerView) .setOnItemClickListener(new ItemClickSupport.OnItemClickListener() { @Override public void onItemClicked(RecyclerView recyclerView, int position, View v) { // do it } });
(它也支持长时间点击)
实施(由我添加的意见):
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) { // ask the RecyclerView for the viewHolder of this view. // then use it to get the position for the adapter 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) { // every time a new child view is attached add click listeners to it if (mOnItemClickListener != null) { view.setOnClickListener(mOnClickListener); } if (mOnItemLongClickListener != null) { view.setOnLongClickListener(mOnLongClickListener); } } @Override public void onChildViewDetachedFromWindow(View view) { } }; private ItemClickSupport(RecyclerView recyclerView) { mRecyclerView = recyclerView; // the ID must be declared in XML, used to avoid // replacing the ItemClickSupport without removing // the old one from the RecyclerView mRecyclerView.setTag(R.id.item_click_support, this); mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener); } public static ItemClickSupport addTo(RecyclerView view) { // if there's already an ItemClickSupport attached // to this RecyclerView do not replace it, use it 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); } }
还要创build一个文件values/ids.xml
并把它放在里面:
<?xml version="1.0" encoding="utf-8"?> <resources> <item name="item_click_support" type="id" /> </resources>
该类通过将RecyclerView.OnChildAttachStateChangeListener
附加到RecyclerView.OnChildAttachStateChangeListener
来工作。 每次儿童从RecyclerView
附着或分离时都会通知此侦听器。 该代码使用这个附加一个龙头/长按听众的视图。 该监听器向RecyclerView
询问包含该位置的RecyclerView.ViewHolder
。
如果你需要更多的话,你也可以修改代码来让你回到持有者身上。
请记住,通过在列表的每个视图上设置一个点击监听器,就像在其他的答案中一样,在你的适配器中处理它是完全正确的。 这不是最有效率的做法(每次重新使用视图时都会创build一个新的监听器),但是它可以工作,而且在大多数情况下这不是问题。
关于为什么 RecyclerView
没有onItemClickListener
。
RecyclerView
是一个工具箱,与旧的ListView
相比,它具有更less的function和更多的灵活性。 onItemClickListener
不是从ListView中删除的唯一function。 但是它有很多听众和方法可以把它扩展到你喜欢的地方,它在右手上更加强大)。
在我看来, RecyclerView
最复杂的function是快速滚动 。 大多数其他function可以轻松地重新实施。
Android的Recyclerview与onItemClickListener
,为什么我们不能尝试这个像ListView
只工作。
来源: 链接
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); } GestureDetector mGestureDetector; public RecyclerItemClickListener(Context context, OnItemClickListener listener) { mListener = listener; mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onSingleTapUp(MotionEvent e) { return true; } }); } @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:
recyclerView = (RecyclerView)rootView. findViewById(R.id.recyclerView); RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity()); recyclerView.setLayoutManager(mLayoutManager); recyclerView.addOnItemTouchListener( new RecyclerItemClickListener(getActivity(), new RecyclerItemClickListener.OnItemClickListener() { @Override public void onItemClick(View view, int position) { // TODO Handle item click Log.e("@@@@@",""+position); } }) );
感谢@marmor,我更新了我的答案。
我认为这是一个很好的解决scheme,处理ViewHolder类构造函数中的onClick(),并通过OnItemClickListener接口将其传递给父类。
MyAdapter.java
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{ private LayoutInflater layoutInflater; private List<MyObject> items; private AdapterView.OnItemClickListener onItemClickListener; public MyAdapter(Context context, AdapterView.OnItemClickListener onItemClickListener, List<MyObject> items) { layoutInflater = LayoutInflater.from(context); this.items = items; this.onItemClickListener = onItemClickListener; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = layoutInflater.inflate(R.layout.my_row_layout, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder holder, int position) { MyObject item = items.get(position); } public MyObject getItem(int position) { return items.get(position); } class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { private TextView title; private ImageView avatar; public ViewHolder(View itemView) { super(itemView); title = itemView.findViewById(R.id.title); avatar = itemView.findViewById(R.id.avatar); title.setOnClickListener(this); avatar.setOnClickListener(this); itemView.setOnClickListener(this); } @Override public void onClick(View view) { //passing the clicked position to the parent class onItemClickListener.onItemClick(null, view, getAdapterPosition(), view.getId()); } } }
其他类中适配器的使用:
MyFragment.java
public class MyFragment extends Fragment implements AdapterView.OnItemClickListener { private RecyclerView recycleview; private MyAdapter adapter; . . . private void init(Context context) { //passing this fragment as OnItemClickListener to the adapter adapter = new MyAdapter(context, this, items); recycleview.setAdapter(adapter); } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //you can get the clicked item from the adapter using its position MyObject item = adapter.getItem(position); //you can also find out which view was clicked switch (view.getId()) { case R.id.title: //title view was clicked break; case R.id.avatar: //avatar view was clicked break; default: //the whole row was clicked } } }
你在你的主要活动中使用这个代码。 非常有效的方法
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.users_list); UsersAdapter adapter = new UsersAdapter(users, this); recyclerView.setAdapter(adapter); adapter.setOnCardClickListner(this);
这是你的适配器类。
public class UsersAdapter extends RecyclerView.Adapter<UsersAdapter.UserViewHolder> { private ArrayList<User> mDataSet; OnCardClickListner onCardClickListner; public UsersAdapter(ArrayList<User> mDataSet) { this.mDataSet = mDataSet; } @Override public UserViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.user_row_layout, parent, false); UserViewHolder userViewHolder = new UserViewHolder(v); return userViewHolder; } @Override public void onBindViewHolder(UserViewHolder holder, final int position) { holder.name_entry.setText(mDataSet.get(position).getUser_name()); holder.cardView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onCardClickListner.OnCardClicked(v, position); } }); } @Override public int getItemCount() { return mDataSet.size(); } @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); } public static class UserViewHolder extends RecyclerView.ViewHolder { CardView cardView; TextView name_entry; public UserViewHolder(View itemView) { super(itemView); cardView = (CardView) itemView.findViewById(R.id.user_layout); name_entry = (TextView) itemView.findViewById(R.id.name_entry); } } public interface OnCardClickListner { void OnCardClicked(View view, int position); } public void setOnCardClickListner(OnCardClickListner onCardClickListner) { this.onCardClickListner = onCardClickListner; } }
在此之后,您将在您的活动中获得此重写方法。
@Override public void OnCardClicked(View view, int position) { Log.d("OnClick", "Card Position" + position); }
> RecyclerView和Listview有什么不同?
一个区别是有与RecyclerView的LayoutManager
类,您可以通过它来pipe理您的RecyclerView
,
LinearLayoutManager
水平或垂直滚动GridLayoutManager的
GridLayoutManager
StaggeredGridLayoutManager交错GridLayout
就像RecyclerView的水平滚动一样,
LinearLayoutManager llm = new LinearLayoutManager(context); llm.setOrientation(LinearLayoutManager.HORIZONTAL); recyclerView.setLayoutManager(llm);
如何把它放在一起的例子…
阅读@ MLProgrammer-CiM的答案后,这是我的代码:
class NormalViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ @Bind(R.id.card_item_normal) CardView cardView; public NormalViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); cardView.setOnClickListener(this); } @Override public void onClick(View v) { if(v instanceof CardView) { // use getAdapterPosition() instead of getLayoutPosition() int itemPosition = getAdapterPosition(); removeItem(itemPosition); } } }
据我所知MLProgrammer-CiM的答案,只是可能做到这一点:
class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ private ImageView image; private TextView title; private TextView price; public MyViewHolder(View itemView) { super(itemView); image = (ImageView)itemView.findViewById(R.id.horizontal_list_image); title = (TextView)itemView.findViewById(R.id.horizontal_list_title); price = (TextView)itemView.findViewById(R.id.horizontal_list_price); image.setOnClickListener(this); title.setOnClickListener(this); price.setOnClickListener(this); } @Override public void onClick(View v) { Toast.makeText(context, "Item click nr: "+getLayoutPosition(), Toast.LENGTH_SHORT).show(); } }
我这样做,其实很简单:
只需添加1行为 点击RecyclerView位置 :
int position = getLayoutPosition()
ViewHolder类的完整代码:
private class ChildViewHolder extends RecyclerView.ViewHolder { public ImageView imageView; public TextView txtView; public ChildViewHolder(View itemView) { super(itemView); imageView= (ImageView)itemView.findViewById(R.id.imageView); txtView= (TextView) itemView.findViewById(R.id.txtView); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Log.i("RecyclerView Item Click Position", String.valueOf(getLayoutPosition())); } }); } }
希望这会帮助你。
我使用这个方法从RecyclerView启动一个Intent:
@Override public void onBindViewHolder(ViewHolder viewHolder, int i) { final MyClass myClass = mList.get(i); viewHolder.txtViewTitle.setText(myclass.name); ... viewHolder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v){ Intent detailIntent = new Intent(mContext, type.class); detailIntent.putExtra("MyClass", myclass); mContext.startActivity(detailIntent); } } );
继MLProgrammer-CiM的优秀RxJava解决scheme
消费/观察点击
ReactiveAdapter rxAdapter = new ReactiveAdapter(); rxAdapter.getPositionClicks().subscribe(mClickConsumer); Consumer<String> mClickConsumer = new Consumer<String>() { @Override public void accept(@NonNull String element) throws Exception { Toast.makeText(getApplicationContext(), element +" was clicked", Toast.LENGTH_LONG); } };
RxJava 2. +
将原来的tl; dr修改为:
public Observable<String> getPositionClicks(){ return onClickSubject; }
PublishSubject#asObservable()
已被删除。 只需返回一个Observable
的PublishSubject
。
如果您有一个POJO列表,并希望从适配器外部单击来检索一个POJO列表,则可以非常轻松地实现它。
在您的适配器中,为click事件创build一个侦听器并设置它的方法:
public class MyAdapter extends RecyclerView.Adapter<SitesListAdapter.ViewHolder> { ... private List<MyPojo> mMyPojos; private static OnItemClickListener mOnItemClickListener; ... public interface OnItemClickListener { public void onItemClick(MyPojo pojo); } ... public void setOnItemClickListener(OnItemClickListener onItemClickListener){ mOnItemClickListener = onItemClickListener; } ...
}
在您的ViewHolder中,实现onClickListener并创build一个类成员来临时存储视图呈现的POJO,这样(这是一个例子,创build一个setter会更好):
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { public MyPojo mCurrentPojo; ... public ViewHolder(View view) { super(v); ... view.setOnClickListener(this); //You could set this on part of the layout too } ... @Override public void onClick(View view) { if(mOnItemClickListener != null && mCurrentPojo != null){ mOnItemClickListener.onItemClick(mCurrentPojo); } }
回到你的适配器中,当ViewHolder绑定时设置当前的POJO(如果当前视图没有,则设置为null):
@Override public void onBindViewHolder(final ViewHolder holder, final int position) { final MyPojo currentPojo = mMyPojos.get(position); holder.mCurrentPojo = currentPojo; ...
就是这样,现在你可以像这样从片段/活动中使用它:
mMyAdapter.setOnItemClickListener(new mMyAdapter.OnItemClickListener() { @Override public void onItemClick(MyPojo pojo) { //Do whatever you want with your pojo here } });
看到我的这个方法:
首先声明一个这样的接口:
/** * Interface used for delegating item click events in a {@link android.support.v7.widget.RecyclerView} * Created by Alex on 11/28/2015. */ public interface OnRecyclerItemClickListener<T> { /** * Called when a click occurred inside a recyclerView item view * @param view that was clicked * @param position of the clicked view * @param item the concrete data that is displayed through the clicked view */ void onItemClick(View view, int position, T item); }
然后创build适配器:
public class CustomRecyclerAdapter extends RecyclerView.Adapter { private class InternalClickListener implements View.OnClickListener{ @Override public void onClick(View v) { if(mRecyclerView != null && mItemClickListener != null){ // find the position of the item that was clicked int position = mRecyclerView.getChildAdapterPosition(v); Data data = getItem(position); // notify the main listener mItemClickListener.onItemClick(v, position, data); } } } private final OnRecyclerItemClickListener mItemClickListener; private RecyclerView mRecyclerView; private InternalClickListener mInternalClickListener; /** * * @param itemClickListener used to trigger an item click event */ public PlayerListRecyclerAdapter(OnRecyclerItemClickListener itemClickListener){ mItemClickListener = itemClickListener; mInternalClickListener = new InternalClickListener(); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, parent, false); v.setOnClickListener(mInternalClickListener); ViewHolder viewHolder = new ViewHolder(v); return viewHolder; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { // do your binding here } @Override public int getItemCount() { return mDataSet.size(); } @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); mRecyclerView = recyclerView; } @Override public void onDetachedFromRecyclerView(RecyclerView recyclerView) { super.onDetachedFromRecyclerView(recyclerView); mRecyclerView = null; } public Data getItem(int position){ return mDataset.get(position); } }
现在让我们看看如何从片段中整合这个:
public class TestFragment extends Fragment implements OnRecyclerItemClickListener<Data>{ private RecyclerView mRecyclerView; @Override public void onItemClick(View view, int position, Data item) { // do something } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.test_fragment, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { mRecyclerView = view.findViewById(idOfTheRecycler); mRecyclerView .setAdapter(new CustomRecyclerAdapter(this)); }
If you want to add onClick() to the child view of items, for example, a button in item, I found that you can do it easily in onCreateViewHolder() of your own RecyclerView.Adapter just like this:
@Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater .from(parent.getContext()) .inflate(R.layout.cell, null); Button btn = (Button) v.findViewById(R.id.btn); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //do it } }); return new MyViewHolder(v); }
i don't know whether it's a good way, but it works well. If anyone has a better idea, very glad to tell me and correct my answer! ?
这对我工作:
@Override public void onBindViewHolder(PlacesListViewAdapter.ViewHolder holder, int position) { ---- ---- ---- // Set setOnClickListener(holder); } @Override public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { ---- ---- ---- @Override public void onClick(View view) { // Use to get the item clicked getAdapterPosition() } }
是的你可以
public ViewHolder onCreateViewHolder(ViewGroup parent,int viewType) { //inflate the view View view = LayoutInflator.from(parent.getContext()).inflate(R.layout.layoutID,null); ViewHolder holder = new ViewHolder(view); //here we can set onClicklistener view.setOnClickListener(new View.OnClickListeener(){ public void onClick(View v) { //action } }); return holder;
Here you can handle multiple onclick see below code and it is very efficient
public class RVNewsAdapter extends RecyclerView.Adapter<RVNewsAdapter.FeedHolder> { private Context context; List<News> newsList; // Allows to remember the last item shown on screen private int lastPosition = -1; public RVNewsAdapter(List<News> newsList, Context context) { this.newsList = newsList; this.context = context; } public static class FeedHolder extends RecyclerView.ViewHolder implements OnClickListener { ImageView img_main; TextView tv_title; Button bt_facebook, bt_twitter, bt_share, bt_comment; public FeedHolder(View itemView) { super(itemView); img_main = (ImageView) itemView.findViewById(R.id.img_main); tv_title = (TextView) itemView.findViewById(R.id.tv_title); bt_facebook = (Button) itemView.findViewById(R.id.bt_facebook); bt_twitter = (Button) itemView.findViewById(R.id.bt_twitter); bt_share = (Button) itemView.findViewById(R.id.bt_share); bt_comment = (Button) itemView.findViewById(R.id.bt_comment); img_main.setOnClickListener(this); bt_facebook.setOnClickListener(this); bt_twitter.setOnClickListener(this); bt_comment.setOnClickListener(this); bt_share.setOnClickListener(this); } @Override public void onClick(View v) { if (v.getId() == bt_comment.getId()) { Toast.makeText(v.getContext(), "Comment " , Toast.LENGTH_SHORT).show(); } else if (v.getId() == bt_facebook.getId()) { Toast.makeText(v.getContext(), "Facebook " , Toast.LENGTH_SHORT).show(); } else if (v.getId() == bt_twitter.getId()) { Toast.makeText(v.getContext(), "Twitter " , Toast.LENGTH_SHORT).show(); } else if (v.getId() == bt_share.getId()) { Toast.makeText(v.getContext(), "share " , Toast.LENGTH_SHORT).show(); } else { Toast.makeText(v.getContext(), "ROW PRESSED = " + String.valueOf(getAdapterPosition()), Toast.LENGTH_SHORT).show(); } } } @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); } @Override public FeedHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.feed_row, parent, false); FeedHolder feedHolder = new FeedHolder(view); return feedHolder; } @Override public void onBindViewHolder(FeedHolder holder, int position) { holder.tv_title.setText(newsList.get(position).getTitle()); // Here you apply the animation when the view is bound setAnimation(holder.img_main, position); } @Override public int getItemCount() { return newsList.size(); } /** * Here is the key method to apply the animation */ private void setAnimation(View viewToAnimate, int position) { // If the bound view wasn't previously displayed on screen, it's animated if (position > lastPosition) { Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left); viewToAnimate.startAnimation(animation); lastPosition = position; } } }
Modified my comment…
public class MyViewHolder extends RecyclerView.ViewHolder { private Context mContext; public MyViewHolder(View itemView) { super(itemView); mContext = itemView.getContext(); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int itemPosition = getLayoutPosition(); Toast.makeText(mContext, "" + itemPosition, Toast.LENGTH_SHORT).show(); } }); }
Check this one in which I have implemented all the things with a proper way
RecyclerViewHolder Class
public class RecyclerViewHolder extends RecyclerView.ViewHolder { //view holder is for girdview as we used in the listView public ImageView imageView,imageView2; public RecyclerViewHolder(View itemView) { super(itemView); this.imageView=(ImageView)itemView.findViewById(R.id.image); } }
Adapter
public class RecyclerView_Adapter extends RecyclerView.Adapter<RecyclerViewHolder> { //RecyclerView will extend to recayclerview Adapter private ArrayList<ModelClass> arrayList; private Context context; private static RecyclerViewClickListener itemListener; //constructor of the RecyclerView Adapter RecyclerView_Adapter(Context context,ArrayList<ModelClass> arrayList,RecyclerViewClickListener itemListener){ this.context=context; this.arrayList=arrayList; this.itemListener=itemListener; } @Override public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //this method will inflate the custom layout and return as viewHolder LayoutInflater layoutInflater=LayoutInflater.from(parent.getContext()); ViewGroup mainGroup=(ViewGroup) layoutInflater.inflate(R.layout.single_item,parent,false); RecyclerViewHolder listHolder=new RecyclerViewHolder(mainGroup); return listHolder; } @Override public void onBindViewHolder(RecyclerViewHolder holder, final int position) { final ModelClass modelClass=arrayList.get(position); //holder RecyclerViewHolder mainHolder=(RecyclerViewHolder)holder; //convert the drawable image into bitmap Bitmap image= BitmapFactory.decodeResource(context.getResources(),modelClass.getImage()); //set the image into imageView mainHolder.imageView.setImageBitmap(image); //to handle on click event when clicked on the recyclerview item and // get it through the RecyclerViewHolder class we have defined the views there mainHolder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //get the position of the image which is clicked itemListener.recyclerViewListClicked(v,position); } }); } @Override public int getItemCount() { return (null!=arrayList?arrayList.size():0); } }
The interface
public interface RecyclerViewClickListener { //this is method to handle the event when clicked on the image in Recyclerview public void recyclerViewListClicked(View v,int position); } //and to call this method in activity RecyclerView_Adapter adapter=new RecyclerView_Adapter(Wallpaper.this,arrayList,this); recyclerView.setAdapter(adapter); adapter.notifyDataSetChanged(); @Override public void recyclerViewListClicked(View v,int position){ imageView.setImageResource(wallpaperImages[position]); }
main_recyclerview.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() { @Override public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { int position=rv.getChildAdapterPosition(rv.findChildViewUnder(e.getX(),e.getY())); switch (position) { case 0: { wifi(position); adapter2.notifyDataSetChanged(); } break; case 1: { sound(position); adapter2.notifyDataSetChanged(); } break; case 2: { bluetooth(position); adapter2.notifyDataSetChanged(); } break; } return true; } @Override public void onTouchEvent(RecyclerView rv, MotionEvent e) { } @Override public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { } });
Instead of implementing interface View.OnClickListener inside view holder or creating and interface and implementing interface in your activity.. I used this code for simple on OnClickListener implementation.
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(); } }
use PlaceHolderView
@Layout(R.layout.item_view_1) public class View1{ @View(R.id.txt) public TextView txt; @Resolve public void onResolved() { txt.setText(String.valueOf(System.currentTimeMillis() / 1000)); } @Click(R.id.btn) public void onClick(){ txt.setText(String.valueOf(System.currentTimeMillis() / 1000)); } }
I wrote a library to handle android recycler view item click event. You can find whole tutorial in
RecycleClick.addTo(YOUR_RECYCLEVIEW).setOnItemClickListener(new RecycleClick.OnItemClickListener() { @Override public void onItemClicked(RecyclerView recyclerView, int position, View v) { // YOUR CODE } });
or to handle item long press you can use
RecycleClick.addTo(YOUR_RECYCLEVIEW).setOnItemLongClickListener(new RecycleClick.OnItemLongClickListener() { @Override public boolean onItemLongClicked(RecyclerView recyclerView, int position, View v) { // YOUR CODE return true; } });
Access the mainView
of rowLayout(cell)
for you RecyclerView
and in your OnBindViewHolder
write this code:
@Override public void onBindViewHolder(MyViewHolder holder, final int position) { Movie movie = moviesList.get(position); holder.mainView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { System.out.println("pos " + position); } }); }
it worked for me. 希望它会有所帮助。 Most simplest way.
Inside View Holder
class GeneralViewHolder extends RecyclerView.ViewHolder { View cachedView = null; public GeneralViewHolder(View itemView) { super(itemView); cachedView = itemView; }
Inside OnBindViewHolder()
@Override public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { final GeneralViewHolder generalViewHolder = (GeneralViewHolder) holder; generalViewHolder.cachedView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(context, "item Clicked at "+position, Toast.LENGTH_SHORT).show(); } });
And let me know, do you have any question about this solution ?
Easiest way to do this is as follows:
Declare global variable at start of Adapter class:
// Store out here so we can resuse private View yourItemView;
Then set the OnClickListener within the onBindViewHolder method:
@Override public void onBindViewHolder(BusinessAdapter.ViewHolder holder, int position) { // Set up the on click listener yourItemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(mContext,Integer.toString(position),Toast.LENGTH_SHORT).show(); } }); }
All other answers are lame.
以上就是android开发分享为什么RecyclerView没有onItemClickListener()?相关内容,想了解更多android开发(异常处理)及android游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/addevelopment/523958.html