最近有个需求,就是手指在RecyclerView随意滑动,如在ABCDEF 滑动到A就响应数据A显示。(当然该功能可以直接自定义view draw出来)效果如图
核心即题目,RecyclerView根据座标得到position?也就是说
ACTION_DOWN,ACTION_MOVE的时候去实时回调position
我们先直接给RecyclerView加上setOnTouchListener 得到x,y
我一开始想到的方案1是根据item的宽高区域,去算出对应x,y所在position 但是并不好用,我试着猜想RecyclerView是否有自带的这个方法,联想ListView的setOnItemClick实现中有类似获取position的方法,但RecyclerView并没有自带setOnItemClick。
我们position一般从哪儿拿呢,viewHolder.getAdapterPosition(),所以我们只要找到xy所在的item对应的viewHolder即可,x,y获取item的方法是自带的findChildViewUnder
@Nullable
public View findChildViewUnder(float x, float y) {
int count = this.mChildHelper.getChildCount();
for(int i = count - 1; i >= 0; --i) {
View child = this.mChildHelper.getChildAt(i);
float translationX = child.getTranslationX();
float translationY = child.getTranslationY();
if (x >= (float)child.getLeft() + translationX && x <= (float)child.getRight() + translationX && y >= (float)child.getTop() + translationY && y <= (float)child.getBottom() + translationY) {
return child;
}
}
return null;
}
viewholder又如何从itemView里面得到呢查看源码
public void bindViewToPosition(@NonNull View view, int position) {
RecyclerView.ViewHolder holder = RecyclerView.getChildViewHolderInt(view);
...
RecyclerView.LayoutParams rvLayoutParams;
...
rvLayoutParams.mViewHolder = holder;
}
}
}
我们可以看到RecyclerView.getChildViewHolderInt 可以获取到holder。同时是赋值给了RecyclerView.LayoutParams
RecyclerView.getChildViewHolderInt也是从RecyclerView.LayoutParams中取看有没有了
所以得到触碰位置的position就比较容易了
rv.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
View child = rv.findChildViewUnder(event.getX(), event.getY());
if (child != null) {
RecyclerView.ViewHolder vh = rv.getChildViewHolder(child);
mPosition = vh.getAdapterPosition();
}
return true;
}
});