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

相关文章

hdu1254(嵌套bfs,两次bfs)

/*第一次做这种题感觉很有压力,思路还是有点混乱,总是wa,改了好多次才ac的思路:把箱子的移动当做第一层bfs,队列节点要用到当前箱子坐标(x,y),走的次数step,当前人的weizhi(man_x,man_y),要判断人能否将箱子推到某点时要嵌套第二层bfs(人的移动);代码如下:

好题——hdu2522(小数问题:求1/n的第一个循环节)

好喜欢这题,第一次做小数问题,一开始真心没思路,然后参考了网上的一些资料。 知识点***********************************无限不循环小数即无理数,不能写作两整数之比*****************************(一开始没想到,小学没学好) 此题1/n肯定是一个有限循环小数,了解这些后就能做此题了。 按照除法的机制,用一个函数表示出来就可以了,代码如下

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

购买磨轮平衡机时应该注意什么问题和技巧

在购买磨轮平衡机时,您应该注意以下几个关键点: 平衡精度 平衡精度是衡量平衡机性能的核心指标,直接影响到不平衡量的检测与校准的准确性,从而决定磨轮的振动和噪声水平。高精度的平衡机能显著减少振动和噪声,提高磨削加工的精度。 转速范围 宽广的转速范围意味着平衡机能够处理更多种类的磨轮,适应不同的工作条件和规格要求。 振动监测能力 振动监测能力是评估平衡机性能的重要因素。通过传感器实时监

缓存雪崩问题

缓存雪崩是缓存中大量key失效后当高并发到来时导致大量请求到数据库,瞬间耗尽数据库资源,导致数据库无法使用。 解决方案: 1、使用锁进行控制 2、对同一类型信息的key设置不同的过期时间 3、缓存预热 1. 什么是缓存雪崩 缓存雪崩是指在短时间内,大量缓存数据同时失效,导致所有请求直接涌向数据库,瞬间增加数据库的负载压力,可能导致数据库性能下降甚至崩溃。这种情况往往发生在缓存中大量 k

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

【VUE】跨域问题的概念,以及解决方法。

目录 1.跨域概念 2.解决方法 2.1 配置网络请求代理 2.2 使用@CrossOrigin 注解 2.3 通过配置文件实现跨域 2.4 添加 CorsWebFilter 来解决跨域问题 1.跨域概念 跨域问题是由于浏览器实施了同源策略,该策略要求请求的域名、协议和端口必须与提供资源的服务相同。如果不相同,则需要服务器显式地允许这种跨域请求。一般在springbo