我正在探索RecyclerView,我很惊讶地看到,RecyclerView没有onItemClickListener()。
我有两个问题。
主要问题
我想知道为什么谷歌删除onItemClickListener()?
是否存在性能问题或其他问题?
次要的问题
我解决了我的问题写onClick在我的RecyclerView。适配器:
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) {
}
}
这样可以吗/有更好的办法吗?
Android Recyclerview与onItemClickListener,
为什么我们不能尝试这是工作像ListView。
来源:Link
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);
}
})
);
RecyclerView没有一个onItemClickListener,因为RecyclerView负责回收视图(惊讶!),所以回收视图的责任是处理它接收到的点击事件。
这实际上使它更容易使用,特别是如果你有可以在多个地方点击的项目。
无论如何,检测点击一个RecyclerView项目是非常容易的。你所需要做的就是定义一个接口(如果你不使用Kotlin,在这种情况下你只需要传入一个lambda):
public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
private final Clicks clicks;
public MyAdapter(Clicks clicks) {
this.clicks = clicks;
}
private List<MyObject> items = Collections.emptyList();
public void updateData(List<MyObject> items) {
this.items = items;
notifyDataSetChanged(); // TODO: use ListAdapter for diffing instead if you need animations
}
public interface Clicks {
void onItemSelected(MyObject myObject, int position);
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private MyObject myObject;
public MyViewHolder(View view) {
super(view);
// bind views
view.setOnClickListener((v) -> {
int adapterPosition = getBindingAdapterPosition();
if(adapterPosition >= 0) {
clicks.onItemSelected(myObject, adapterPosition);
}
});
}
public void bind(MyObject myObject) {
this.myObject = myObject;
// bind data to views
}
}
}
Kotlin中的代码相同:
class MyAdapter(val itemClicks: (MyObject, Int) -> Unit): RecyclerView.Adapter<MyViewHolder>() {
private var items: List<MyObject> = Collections.emptyList()
fun updateData(items: List<MyObject>) {
this.items = items
notifyDataSetChanged() // TODO: use ListAdapter for diffing instead if you need animations
}
inner class MyViewHolder(val myView: View): RecyclerView.ViewHolder(myView) {
private lateinit var myObject: MyObject
init {
// binds views
myView.onClick {
val adapterPosition = getBindingAdapterPosition()
if(adapterPosition >= 0) {
itemClicks.invoke(myObject, adapterPosition)
}
}
}
fun bind(myObject: MyObject) {
this.myObject = myObject
// bind data to views
}
}
}
你不需要做的事情:
1)你不需要手动拦截触摸事件
2.)您不需要在子附加状态更改侦听器上添乱
3)你不需要RxJava中的PublishSubject/PublishRelay
只需使用点击侦听器。
伙计们,在你们的主要活动中使用这个代码。非常有效的方法
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);
}
Android Recyclerview与onItemClickListener,
为什么我们不能尝试这是工作像ListView。
来源:Link
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,我更新了我的答案。
我认为在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
}
}
}