android HorizontalScrollView嵌套RecyclerView横向不能滑动问题

本文主要是介绍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横向不能滑动问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/655049

相关文章

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

Android ClassLoader加载机制详解

《AndroidClassLoader加载机制详解》Android的ClassLoader负责加载.dex文件,基于双亲委派模型,支持热修复和插件化,需注意类冲突、内存泄漏和兼容性问题,本文给大家介... 目录一、ClassLoader概述1.1 类加载的基本概念1.2 android与Java Class

Python中将嵌套列表扁平化的多种实现方法

《Python中将嵌套列表扁平化的多种实现方法》在Python编程中,我们常常会遇到需要将嵌套列表(即列表中包含列表)转换为一个一维的扁平列表的需求,本文将给大家介绍了多种实现这一目标的方法,需要的朋... 目录python中将嵌套列表扁平化的方法技术背景实现步骤1. 使用嵌套列表推导式2. 使用itert

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

Redis出现中文乱码的问题及解决

《Redis出现中文乱码的问题及解决》:本文主要介绍Redis出现中文乱码的问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 问题的产生2China编程. 问题的解决redihttp://www.chinasem.cns数据进制问题的解决中文乱码问题解决总结

全面解析MySQL索引长度限制问题与解决方案

《全面解析MySQL索引长度限制问题与解决方案》MySQL对索引长度设限是为了保持高效的数据检索性能,这个限制不是MySQL的缺陷,而是数据库设计中的权衡结果,下面我们就来看看如何解决这一问题吧... 目录引言:为什么会有索引键长度问题?一、问题根源深度解析mysql索引长度限制原理实际场景示例二、五大解决

Springboot如何正确使用AOP问题

《Springboot如何正确使用AOP问题》:本文主要介绍Springboot如何正确使用AOP问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录​一、AOP概念二、切点表达式​execution表达式案例三、AOP通知四、springboot中使用AOP导出

Python中Tensorflow无法调用GPU问题的解决方法

《Python中Tensorflow无法调用GPU问题的解决方法》文章详解如何解决TensorFlow在Windows无法识别GPU的问题,需降级至2.10版本,安装匹配CUDA11.2和cuDNN... 当用以下代码查看GPU数量时,gpuspython返回的是一个空列表,说明tensorflow没有找到

解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘问题

《解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘问题》:本文主要介绍解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4... 目录未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘打开pom.XM