我正在探索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) {
}
}
这样可以吗/有更好的办法吗?
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
只需使用点击侦听器。
我喜欢这样,我正在用它
内部
public Adapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
Put
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_image_and_text, parent, false);
v.setOnClickListener(new MyOnClickListener());
在任何你想要的地方创建这个类
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));
}
}
我以前读过有一个更好的方法,但我喜欢这个方法,简单,不复杂。
我写了一个库来处理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
}
});
或处理项目长按即可使用
RecycleClick.addTo(YOUR_RECYCLEVIEW).setOnItemLongClickListener(new RecycleClick.OnItemLongClickListener() {
@Override
public boolean onItemLongClicked(RecyclerView recyclerView, int position, View v) {
// YOUR CODE
return true;
}
});
RecyclerView是如何不同于Listview?
一个区别是有一个LayoutManager类和RecyclerView,通过它你可以像-一样管理你的RecyclerView
水平或垂直滚动线性layoutmanager
GridLayout by GridLayoutManager
交错网格布局由StaggeredGridLayoutManager
就像水平滚动的RecyclerView-
LinearLayoutManager llm = new LinearLayoutManager(context);
llm.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(llm);
最简单的方法如下:
在Adapter类开始时声明全局变量:
// Store out here so we can resuse
private View yourItemView;
然后在onBindViewHolder方法中设置OnClickListener:
@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();
}
});
}
其他答案都不正确。
如果你想添加onClick()到项目的子视图,例如,项目中的按钮,我发现你可以很容易地在你自己的RecyclerView的onCreateViewHolder()中做到这一点。适配器就像这样:
@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);
}
我不知道这是不是一个好方法,但它很有效。如果有人有更好的想法,很高兴告诉我并纠正我的答案!:)