本文主要是介绍android HorizontalScrollView嵌套RecyclerView横向不能滑动问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
开发场景:在 HorizontalScrollView内嵌套RecyclerView和其他内容,要求其他控件和RecyclerView一起横向滑动,而RecyclerView自身滑动事件不响应。
问题分析:1.HorizontalScrollView内嵌套RecyclerView,发现HorizontalScrollView不能横向滑动;
2.RecyclerView于HorizontalScrollView的滑动冲突。
这个需求所面临的问题里面,第二个问题的解决方案很多,例如重写HorizontalScrollView,阻止滑动事件的传递。
首先来看第一个问题的解决方案:
第一,当我把HorizontalScrollView内嵌RecyclerView工程跑起来后,发现不能够滑动,重写RecyclerView的LinearLayoutManager,主要重写onMeasure方法,来计算出width和height。示例代码如下:
public class MyLinearLayoutManager extends LinearLayoutManager {public MyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {super(context, orientation, reverseLayout); }private int[] mMeasuredDimension = new int[2]; @Override public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {final int widthMode = View.MeasureSpec.getMode(widthSpec); final int heightMode = View.MeasureSpec.getMode(heightSpec); final int widthSize = View.MeasureSpec.getSize(widthSpec); final int heightSize = View.MeasureSpec.getSize(heightSpec); int width = 0; int height = 0; for (int i = 0; i <getItemCount(); i++) {if (getOrientation() == HORIZONTAL) {measureScrapChild(recycler, i, View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), heightSpec, mMeasuredDimension); width = width + mMeasuredDimension[0]; if (i == 0) {height = mMeasuredDimension[1]; }} else {measureScrapChild(recycler, i, widthSpec, View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), mMeasuredDimension); height = height + mMeasuredDimension[1]; if (i == 0) {width = mMeasuredDimension[0]; }}}switch (widthMode) {case View.MeasureSpec.EXACTLY:width = widthSize; case View.MeasureSpec.AT_MOST:case View.MeasureSpec.UNSPECIFIED:}switch (heightMode) {case View.MeasureSpec.EXACTLY:height = heightSize; case View.MeasureSpec.AT_MOST:case View.MeasureSpec.UNSPECIFIED:}width += 30 * getItemCount(); setMeasuredDimension(width, height); }private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec, int heightSpec, int[] measuredDimension) {View view = recycler.getViewForPosition(position); recycler.bindViewToPosition(view, position); if (view != null) {RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams(); int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, getPaddingLeft() + getPaddingRight(), p.width); int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, getPaddingTop() + getPaddingBottom(), p.height); view.measure(childWidthSpec, childHeightSpec); measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin; measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin; recycler.recycleView(view); }} }
解释下为什么会有下面这一句,因为设置了RecyclerView的间距,重写了RecyclerView.ItemDecoration方法,每一个item的间距设置了30px,所以,为了让ui显示完整,得加上下面这句代码,如果不需要设置间距,删除下面代码。
感慨下,代码还是比较简陋的,毕竟是demo
width += 30 * getItemCount();
另外,使用控件的时候,还需要给控件设置下面的属性
recyclerView.setNestedScrollingEnabled(false)
第二,重写RecyclerView,来阻止事件的分发,从而达到recyclerView不能滑动的问题,示例代码如下:
public class MyScollView extends HorizontalScrollView {public MyScollView(Context context) {super(context); }public MyScollView(Context context, @Nullable AttributeSet attrs) {super(context, attrs); }public MyScollView(Context context, @Nullable AttributeSet attrs, int defStyle) {super(context, attrs, defStyle); }private float lastX, lastY; @Override public boolean onInterceptTouchEvent(MotionEvent e) {boolean intercept = super.onInterceptTouchEvent(e); switch (e.getAction()) {case MotionEvent.ACTION_DOWN:lastX = e.getX(); lastY = e.getY(); break; case MotionEvent.ACTION_MOVE:// 只要横向大于竖向,就拦截掉事件。 // 部分机型点击事件(slopx==slopy==0),会触发MOVE事件。 // 所以要加判断(slopX > 0 || sloy > 0) float slopX = Math.abs(e.getX() - lastX); float slopY = Math.abs(e.getY() - lastY); // Log.log("slopX=" + slopX + ", slopY=" + slopY); if((slopX > 0 || slopY > 0) && slopX >= slopY){requestDisallowInterceptTouchEvent(true); intercept = true; }break; case MotionEvent.ACTION_UP:intercept = false; break; }// Log.log("intercept"+e.getAction()+"=" + intercept); return intercept; } }
在布局的时候记得使用自定义的ScollView,另外再说一下在开发的时候还遇到一个问题:
recyclerview嵌在ScollView里面,发现recyclerView不显示,查了查资料,通过设置了ScollView的width,height为match_parent,另外,还有一个重要属性需要设置
android:fillViewport="true"
这篇关于android HorizontalScrollView嵌套RecyclerView横向不能滑动问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!