问题
我试图模拟Google Play应用程序的确切行为。
目前,当你在浏览“热门游戏”等类别时,如果你点击列表中的某个单元格,该单元格以及 RecyclerView
都会处理触摸事件,你可以通过按住手指时出现的波纹以及滚动停止来判断它们都在处理事件。或者如果你在列表仍在移动时点击单元格,内容会立即打开。
默认行为是,如果你放下手指而列表正在滚动,则滚动会立即停止,并且消耗该触摸事件,这意味着单元格永远不会收到该触摸事件。如果你的应用程序主要内容在 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);
}
这里,即使我从适配器中获取的视图具有我设置的相应标记,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);
}
}