vgu*_*zzi 19 android smooth-scrolling touch-event android-recyclerview
问题
我试图模拟Google Play应用程序的确切行为.
目前,当您滚动浏览类似"热门游戏"的类别并触摸列表,该单元格以及RecyclerView处理触摸事件时,您可以告诉他们正在处理它,因为当您按下手指时出现波纹以及滚动停止.或者,如果您在列表仍在移动时单击一个单元格,则会立即打开该内容.
默认行为是滚动在您移动时将手指放下时立即停止,然后消耗该触摸事件,这意味着细胞永远不会被告知该触摸.当您的应用程序主要内容位于a中时,这非常令人恼火RecyclerView,如果用户不断滚动然后单击一个单元格,则需要它们单击两次,因为通过停止滚动消耗了第一次单击,即使列表很少移动.
我到目前为止所做的一切
起初我以为必须有一些标志,RecyclerView它告诉它不要消耗触摸事件.我查看了Android源代码并通过Android文档路由无济于事.
然后我尝试捕捉触摸事件onInterceptTouchEvent并手动告诉我的视图它被触摸;
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
View myCell = recyclerView.findChildViewUnder(event.getX(), event.getY());
myCell.dispatchTouchEvent(event);
return super.onInterceptTouchEvent(event);
}
Run Code Online (Sandbox Code Playgroud)
在这里, dispatchTouchEvent似乎没有做任何事情,即使我得到的视图有我在适配器中设置的相应标签.
我试过用我的编码机枪在各个角度拍摄这个问题; 玩requestDisallowInterceptTouchEvent,手动调用onTouch和覆盖所有方式的听众RecyclerView.
似乎没有什么工作.我确信必须有一个优雅的解决方案,我已经在精神错乱的道路上的某个地方浏览了一个重要的细节?特别是因为谷歌自己的应用程序以这种方式运行.
请帮忙!:) 谢谢.
解决方案
感谢Jagoan Neon已找到解决方案.我最终将他的答案包含在一个习惯中,RecyclerView以方便使用.
public class MultiClickRecyclerView extends RecyclerView {
public MultiClickRecyclerView(Context context) {
super(context);
}
public MultiClickRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MultiClickRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN && this.getScrollState() == RecyclerView.SCROLL_STATE_SETTLING) {
this.stopScroll();
}
return super.onInterceptTouchEvent(event);
}
}
Run Code Online (Sandbox Code Playgroud)
Jag*_*eon 26
首先你应该定义一个OnItemTouchListener,也许作为一个像这样的全局变量:
RecyclerView.OnItemTouchListener mOnItemTouchListener = new RecyclerView.OnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
if (e.getAction() == MotionEvent.ACTION_DOWN && rv.getScrollState() == RecyclerView.SCROLL_STATE_SETTLING) {
Log.d(TAG, "onInterceptTouchEvent: click performed");
rv.findChildViewUnder(e.getX(), e.getY()).performClick();
return true;
}
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
};
Run Code Online (Sandbox Code Playgroud)
为什么选择ACTION_DOWN和SCROLL_STATE_SETTLING?
当您在RecyclerView上执行触摸时,将触发ACTION_DOWN运动事件,并且在确切的时间点,RecyclerView在尝试停止滚动时将其滚动状态更改为SCROLL_STATE_SETTLING.而这正是您想要执行点击的时间.
并记住返回true,以便告诉您的RecyclerView您已经使用了MotionEvent.否则,您的performClick()可能会被多次调用.
将它添加到onResume的RecyclerView并在onPause中将其删除,然后你就完成了设置;)
UPDATE
当您执行findChildViewUnder时添加一个空检查器 - 当您没有触摸特定单元格时它返回null.
View childView = rv.findChildViewUnder(e.getX(), e.getY());
if (childView != null) childView.performClick();
Run Code Online (Sandbox Code Playgroud)
更新2
事实证明,停止RecyclerView滚动就足够了.改为:
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
if (e.getAction() == MotionEvent.ACTION_DOWN && rv.getScrollState() == RecyclerView.SCROLL_STATE_SETTLING)
rv.stopScroll();
return false;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11766 次 |
| 最近记录: |