我正在试图找出实现两个列表的最佳方法,其中父列表可以垂直滑动,子列表可以水平滑动。父列表被假定为无限列表,而子列表最多可以有n个页面。回收站视图似乎是这项工作的最佳工具,并且考虑到PagerSnapHelper的添加,重新创建页面滑动行为真的很容易(想想ViewPage)。我目前面临的问题是,当我们水平滑动到结束或开始时,有时垂直回收站视图(父)会接管并更改页面。即使使用单个垂直回收站视图也可以重新创建,如下所示:
@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。
可能的解决方案:
如果需要,我很乐意提供更多的上下文/代码。拥有两个pagersnapper可能不是Android目前的模式,但即使我把那部分拿走,我也想知道为什么pagersnapper对某些手势如此敏感。
我认为,当必须在父级是垂直的情况下调用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);
}
}
}
关键在于如何检测滚动是否应该被认为是水平,如在< code>return Math.abs(distanceX)中
apSTRK的静态编程语言类:
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)
}