Android 类似淘宝的吸顶特效 NestedScrollView+RecycleView

运行图

布局的设计

要实现上面的效果需要搞定NestedScrollView和RecycleView的滑动冲突。有人要问RecycleView为何要滑动自动撑大不就好了么?这个问题其实对于有限的资源加载来说是很好的解决方案,但是如果涉及到的是图文结合的并且有大批量的数据的时候就需要用到RecycleView的复用机制,这样就要求RecycleView固定高度。

这里面涉及到的几个参数:

1:整屏高度 screenHeight  (用此方法可以省掉Context的传入)

    /**
     * 获取屏幕高度 px
     * @return
     */
    public static int getScreenHeightPixels() {
        return Resources.getSystem().getDisplayMetrics().heightPixels;
    }

2:头部悬浮框高度 floatActionBarHeight

这里直接用View去getHeight()就行,这个方法在使用的时候调用就好,如果一开始就调用有可能拿不到数据,因为页面还没加载完成

3:底部导航高度 bottomBarHeight

这个可以是固定值,看自己的设计是多大的,我的设定是48dp,所以转化后的结果是。

  //将设置的db转为屏幕像素
    public static int dp2px(int dpVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, Resources.getSystem().getDisplayMetrics());
    }

4:悬浮tab的高度 floatTabBarHeight

跟导航的高度一样处理。

在这里RecycleView的高度值我们有了方案。

scrollRecycleHeight=screenHeight-floatActionBarHeight-bottomBarHeight-floatTabBarHeight

设置高度在数据返回回来的时候或者一开始的时候设置都行。

接下来要处理的就是滑动冲突的问题

NestedScrollingChildHelper 提供了一个禁止view滑动的方法,这个类封装在了RecycleView内部,所以RecycleView也可以调用。
 public void setNestedScrollingEnabled(boolean enabled) {
        if (this.mIsNestedScrollingEnabled) {
            ViewCompat.stopNestedScroll(this.mView);
        }

        this.mIsNestedScrollingEnabled = enabled;
    }

说到这里小伙伴可能会说那就简单了,只要NestedScrollView没有滑动到浮层tab的位置的时候都禁止RecyceView的滑动就好了,超出的时候允许其滑动是不是就可以解决了?

事实的情况并不是这样。当我们测试的时候,当我们慢慢滑动NestedScrollView,当屏幕出现RecycleView的时候,这时候NestedScroolView的滑动惯性还在继续,我们此时触摸滑动RecycleView 是可以滑动的。具体原因大家可以查看源码去分析下,这里不做分析。

解决方案

重写NestedScrollView 实现拦截。

public class NestedInsScrollView extends NestedScrollView {
    private int limitHeight = 0;
    private float startX, startY;

    public void setLimitHeight(int limitHeight) {
        this.limitHeight = limitHeight;
    }
    public NestedInsScrollView(@NonNull Context context) {
        super(context);
    }

    public NestedInsScrollView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public NestedInsScrollView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        int scrollY = 0;
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                startX = ev.getX();
                startY = ev.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                scrollY = getScrollY();
                // 判断是否需要拦截子View的滑动事件
                float offsetX = Math.abs(ev.getX() - startX);
                float offsetY = Math.abs(ev.getY() - startY);
                if (offsetY > offsetX && ev.getY() - startY < 0) {//向上的垂直滑动
                    if (scrollY < limitHeight) {
                        return true;
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                break;
        }
        return super.onInterceptTouchEvent(ev);
    }
}

这里面通过重写onInterceptTouchEvent 在ACTION_MOVE事件中判断是否可以滚动,如果不允许RecycleView滚动则事件不往下分发。

这里面需要注意的点:

1:要判断事件是垂直滚动 (因为内部的View还要处理左右滚动的事件)

2:要判断是向上滚动 (因为头部的RecycleView还要处理下拉刷新)

3:最后只有满足垂直向上并且滚动距离达到tab的浮动距离的时候才拦截

     homeScrollView.setOnScrollChangeListener(new 
            NestedScrollView.OnScrollChangeListener() {
            @Override
            public void onScrollChange(NestedScrollView v, int scrollX, int     
                                  scrollY, int oldScrollX, int oldScrollY) {
                int limitHeight = ((ViewGroup) 
                homeScrollView.getChildAt(0)).getChildAt(0).getHeight();
                int topHeight = homeHeadTopLayout.getHeight();
                homeScrollView.setLimitHeight(limitHeight - topHeight -             
                DisplayUtils.dp2px(5));
                // 例如:
                if (scrollY >= limitHeight - topHeight - DisplayUtils.dp2px(5)) {
                    main_home_services_tab_recycle.setNestedScrollingEnabled(true);
                } else {
                   main_home_services_tab_recycle.setNestedScrollingEnabled(false);
                }
            }
        });

这时候再设置  setNestedScrollingEnabled(true/false);

就可以解决问题了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/106771.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Mac用NTFS文件夹读写NTFS硬盘 NTFS能复制多大的文件

Mac作为一款备受欢迎的计算机操作系统&#xff0c;具备了许多令人惊叹的功能和特性。然而&#xff0c;对于一些Mac用户来说&#xff0c;使用NTFS格式的硬盘可能存在一些疑问。他们可能想知道Mac是否能够读写NTFS格式的硬盘&#xff0c;以及NTFS格式的硬盘是否有文件大小的限制。…

.\missyou-0.0.1-SNAPSHOT.jar中没有主清单属性

引用&#xff1a;https://blog.csdn.net/marypiglwy/article/details/132016171 配置的时候 <skip>true</skip> skip设置为true&#xff0c;跳过了执行插件&#xff0c;&#xff0c; <plugin><groupId>org.springframework.boot</groupId><a…

如何使用手机蓝牙设备作为电脑的解锁工具像动态锁那样,蓝牙接近了电脑,电脑自动解锁无需输入开机密码

环境&#xff1a; Win10 专业版 远程解锁 蓝牙解锁小程序 问题描述&#xff1a; 如何使用手机蓝牙设备作为电脑的解锁工具像动态锁那样&#xff0c;蓝牙接近了电脑&#xff0c;电脑自动解锁无需输入开机密码 手机不需要拿出来&#xff0c;在口袋里就可以自动解锁&#xff…

vscode json文件添加注释报错

在vscode中创建json文件&#xff0c;想要注释一波时&#xff0c;发现报了个错&#xff1a;Comments are not permitted in JSON. (521)&#xff0c;意思是JSON中不允许注释 以下为解决方法&#xff1a; 在vscode的右下角中找到这个&#xff0c;点击 在出现的弹窗中输入json wit…

【Mybatis源码】XMLConfigBuilder构建器 - 读取XML配置初始化Configuration对象

XMLConfigBuilder是Mybatis中定义的进行构建Configuration对象的类,此类用于读取XML配置文件创建并初始化Configuration对象; 上一篇中我们介绍了XMLConfigBuilder构建器加载XML配置文件以及创建Configuration对象https://blog.csdn.net/m1729339749/article/details/133983…

Linux shell编程学习笔记16:bash中的关联数组

上一节我们探讨了普通的数组&#xff0c;即使用数字下标来索引数组中不同的元素的数组&#xff0c;也可以称之为索引数组。 相比纯粹的数字&#xff0c;字符串不仅能表明含义&#xff0c;也更便于记忆使用&#xff0c;于是就有了关联数组。 一、关联数组概述 bash 从4.0开始支…

【Linux】部署单机OA项目及搭建spa前后端分离项目

目录 部署OA项目 ​编辑 搭建spa前后端分离项目 后端 前端 配置坏境变量 部署OA项目 在虚拟机中&#xff0c;将项目打包成war文件放置到tomcat根目录下的webapps文件目录下 再在主机数据库中连接数据库&#xff0c;并定义数据库名导入相关的表 继续进入tomcat目录下双击点…

香港服务器运行不正常原因简析

​  网站在线业务的部署需要服务器的存在。于我们而言&#xff0c;租用正规服务商(正规机房)的服务器&#xff0c;一般情况下是会很少出现问题。但&#xff0c;要知道&#xff0c;再稳定的服务器也有出现问题的时候&#xff0c;香港服务器也不例外&#xff0c;而且恰恰这个原…

Windows-Oracle19c 安装详解-含Navicate远程连接配置 - 同时连接Oracle11g和Oracle19c

文章目录 0 说明1 下载链接2 安装&#xff1a;一定要以管理员身份运行&#xff0c;不然后面有可能会报错。3 启动监听4. 登录Oracle4 Navicate远程连接-配置监听4.1 修改监听文件4.2 网络配置助手-配置本地监听端口4.3 Navicate连接成功 5 Navicate同时连接两个Oracle数据库 0 …

SpringBoot 自动配置@EnableAutoConfiguration

自动配置vs自动装配 Spring有两个名字听起来相似的概念&#xff1a;一个是自动装配&#xff0c;一个是自动配置。他们两个只是听起来相似&#xff0c;实际根本不同。自动装配是autowire&#xff0c;自动配置是autoconfiguration&#xff0c;他们之间没有任何关系&#xff0c;概…

科聪协作(复合)移动机器人整体解决方案

协作&#xff08;复合&#xff09;移动机器人&#xff08;AGV/AMR&#xff09;相较传统工业机器人具有更加安全和简单的工作优势&#xff0c;具备较强的发展潜力。协作&#xff08;复合&#xff09;移动机器人安全性和操作的简洁性、灵活性不断提高,优势得到了充分发挥,在越来越…

如何为3D模型设置自发光材质?

1、自发光贴图的原理 自发光贴图是一种纹理贴图&#xff0c;用于模拟物体自发光的效果。其原理基于光的发射和反射过程。 在真实世界中&#xff0c;物体自发光通常是由于其本身具有能够产生光的属性&#xff0c;如荧光物质、发光材料或光源本身。为了在计算机图形中模拟这种效…

electron27+react18集成搭建跨平台应用|electron窗口多开

基于Electron27集成React18创建一个桌面端exe程序。 electron27-vite4-react18基于electron27结合vite4构建工具快速创建react18跨端应用实践。 版本列表 "vite": "^4.4.5" "react": "^18.2.0" "electron": "^27.0.1&…

【MyBatis Plus】深入探索 MyBatis Plus 的条件构造器,自定义 SQL语句,Service 接口的实现

文章目录 前言一、条件构造器1.1 什么是条件构造器1.2 QueryWrapper1.3 UpdateWrapper1.4 LambdaWrapper 二、自定义 SQL 语句2.1 自定义 SQL 的基本用法2.2 自定义 SQL 实现多表查询 三、Service 接口3.1 对 Service 接口的认识3.2 实现 Service 接口3.3 实现增删改查功能3.4 …

HarmonyOS开发:探索组件化模式开发

前言 组件化一直是移动端比较流行的开发方式&#xff0c;有着编译运行快&#xff0c;业务逻辑分明&#xff0c;任务划分清晰等优点&#xff0c;针对Android端的组件化&#xff0c;之前有比较系统的总结过相关文章&#xff0c;感兴趣的朋友&#xff0c;可以查看&#xff0c;点击…

java集成海康预览抓图出现内存一直上涨问题

求助&#xff1a;在java 中集成海康sdk后批量抓图出现内存上涨问题&#xff0c;不论是预览后不关闭继续预览&#xff0c;还是预览后关闭预览&#xff0c;然后重新预览都没有解决这个问题&#xff08;抓图正常&#xff09;&#xff0c;尝试使用第三方解码器ffmpeg来进行解码&…

(PyTorch)PyTorch中的常见运算(*、@、Mul、Matmul)

1. 矩阵与标量 矩阵&#xff08;张量&#xff09;每一个元素与标量进行操作。 import torch a torch.tensor([1,2]) print(a1) >>> tensor([2, 3]) 2. 哈达玛积&#xff08;Mul&#xff09; 两个相同尺寸的张量相乘&#xff0c;然后对应元素的相乘就是这个哈达玛…

Qwt QwtLegend和QwtPlotLegendItem图例类详解

1.概述 QwtLegend类是Qwt绘图库中用于显示图例的类。图例用于标识不同曲线、绘图元素或数据的意义&#xff0c;以便用户能够更好地理解图表中的数据。通过QwtLegend类&#xff0c;可以方便地在图表中添加、删除和设置图例的位置、方向和样式等属性。 QwtPlotLegendItem类是Qwt…

浏览器事件循环 (event loop)

进程与线程 进程 进程的概念 进程是操作系统中的一个程序或者一个程序的一次执行过程&#xff0c;是一个动态的概念&#xff0c;是程序在执行过程中分配和管理资源的基本单位&#xff0c;是操作系统结构的基础。 简单的来说&#xff0c;就是一个程序运行开辟的一块内存空间&a…

听GPT 讲Rust源代码--library/std(3)

rust标准库std中的src目录主要包含以下内容和模块: alloc:内存分配相关函数,比如alloc::boxed::Box、alloc::string::String等。 ascii:ASCII相关工具函数。 char:字符相关类型和函数,如Char、char等。 cmp:比较相关trait和函数,如Ord、Eq、PartialOrd等。 env:环境变量相关功能…