前提:
如何为RecycleView设置点击事件,才会优雅,又不浪费内存呢?
在以前也许我会在Adapter.onBindViewHolder()为Item中相应View设置点击事件,这样是可以的,但是这样做会为“每个View(不管是当前显示在RecycleView列表中的,亦或是划出屏幕被缓存起来待下次使用的)都设置一个Listener回掉”,这样既浪费(因为没必要),又会增加内存开销(如果当前列表有1000个item,那岂不是会增加1000个Listener对象)。
究竟有没有,既优雅,又不浪费内存的做法呢?答案是有的,以下就罗列出2种比较常用的作坊,供大家参考。
1:在 Adapter.onCreateViewHolder() 中为itemView绑定点击事件
总结:onCreateViewHolder()是RecycleView初始化Item对应View的地方。之所以在这里为Item设置点击事件是因为“RdcycleView的缓存机制”,该控件的缓存机制,会做到View的复用。那些划出屏幕的View并不会被销毁掉,而是缓存起来,等待下一次加载一个新视图时,直接拿过来使用。
步骤:
1:在自定义Adapter中声明一个自定义的Interface,该接口就需要一个方法,且该方法需要把点前Itme对应的View返回。之所以要返回这个View是因为,需要通过此View从RecycleView中获取该View是列表/Adapter中的位置,然后好去从数据列表中取数据,做页面跳转等工作。
public void setClick(MyClick click){
this.click = click;
}
private interface MyClick{
void click(View v);
}
2:在Adapter.onCreateViewHolder()中为相应View设置点击事件。并在点击事件中通过自定义Interface返回相应的Item对应的View。
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = this.layoutInflater.inflate(R.layout.item_sild_layout, parent, false);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(click != null){
click.click(v);
}
}
});
return new Holder(view, this.itemWidth, this.mTopicBg);
}
3:需要在外部设置Adapter回调。
sildAdapter.setClick(new SildAdapter.MyClick() {
@Override
public void click(View v) {
if(v != null){
//返回的是“当前Item对应的View在当前列表可视范围内的index”。
int index1 = mRecycleView.indexOfChild(v);
//返回的是“当前Item对应的View在Adapter数据列表中的位置”。
int index2 = mRecycleView.getChildAdapterPosition(v);
//返回的是“当前Item对应的View在整个视图列表中的index”。
int index3 = mRecycleView.getChildLayoutPosition(v);
Log.e("===111", index1 + ", " + index2 + ", " + index3 );
}
}
});
2:利用RcyclerView的addOnItemTouchListener()
总结:
1:调用RecycleView.addOnItemTouchListener(),该方法会接收一个“RecyclerView.OnItemTouchListener”。
2:OnItemTouchListener内部并没有直接响应“点击”的回调方法,我们需要在其onTouchEvent()中自己来实现。
3:一般的我们可以借助“手势(GestureDetector)”来实现。在初始化手势的时候,需要接收一个“OnGestureListener”,我们只需要实现该接口就可以了。
4:如果是“点击”的话,需要重写“onSingleTapUp()”,“长按”的话需要实现“onLongPress()”。
5:点击的话,我们需要在“onSingleTapUp()”通过“RecyclerView.findChildViewUnder()”该方法需要传递一个“点击事件的x,y坐标”,RecycleView会根据点击的坐标来找到点击的那个Itme。
网友评论