我正在试图弄清楚实现两个列表的最佳方法是什么,其中父列表可以垂直滑动,子节点可以水平滑动。 假定父列表是无限列表,而子列表最多可以有n个页面。 RecyclerView似乎是最好的工具,并且添加了PagerSnapHelper,重新创建页面滑动行为非常简单(想想ViewPager。) 我面临的当前问题是,当我们一直水平滑动到结束或开始时,有时垂直Recyclerview(父级)接管并更改页面。 即使使用单个垂直回收视图,也可以重新创建,如下所示:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
PagerSnapHelper snapHelper = new PagerSnapHelper();
SearchAdapter searchAdapter = new SearchAdapter();
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setAdapter(searchAdapter);
snapHelper.attachToRecyclerView(mRecyclerView);
}
从上到下或从下到上滑动/拖动将按预期更改页面。但是,如果您进行水平运动(从左到右或从右到左),有时垂直滑动会启动。 似乎PagerSnapHelper对快速运动非常敏感。当水平启动滑动而不是垂直滑动时,有没有办法避免此页面更改?这个问题在我的案例中更加引人注目,因为我也有一个水平的pagersnaphelper。
可能的解决方案:
如果需要,我很乐意提供更多上下文/代码。 拥有两个PagerSnapHelper可能不是Android中的当前模式,但即使我把这部分拿走了,我也想知道为什么PagerSnapHelper对某些手势如此敏感。
答案 0 :(得分:4)
我认为当父母是垂直的PagerSnapHelpers时,问题是垂直父母将一些水平滑动混淆为垂直。为了避免这种混淆,我拦截了被检测为水平的事件并且禁止父母使用这些事件。 这是我所做的简化版本:
public class VerticalRecyclerView extends RecyclerView {
private GestureDetector mGestureDetector;
public VerticalRecyclerView(Context context) {
super(context);
init();
}
public VerticalRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public VerticalRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
setLayoutManager(layoutManager);
mGestureDetector = new GestureDetector(getContext(), new HorizontalScrollDetector());
}
@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
if (mGestureDetector.onTouchEvent(e)) {
return false;
}
return super.onInterceptTouchEvent(e);
}
public class HorizontalScrollDetector extends
GestureDetector.SimpleOnGestureListener {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return Math.abs(distanceX) > Math.abs(distanceY);
}
}
}
它们的关键在于如何检测滚动是否应该被视为水平,如return Math.abs(distanceX) > Math.abs(distanceY);
答案 1 :(得分:0)
apSTRK 在 Kotlin 中的类:
class VerticalRecyclerView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : RecyclerView(context, attrs, defStyleAttr) {
private var mGestureDetector = GestureDetector(context, object : SimpleOnGestureListener() {
override fun onScroll(e1: MotionEvent, e2: MotionEvent, distanceX: Float, distanceY: Float)
= abs(distanceX) > abs(distanceY)
})
override fun onInterceptTouchEvent(e: MotionEvent?) = if (mGestureDetector.onTouchEvent(e)) false
else super.onInterceptTouchEvent(e)
}