首页 > 编程语言 >直播软件源码,自定义RecyclerView支持快速滚动

直播软件源码,自定义RecyclerView支持快速滚动

时间:2023-04-20 14:11:07浏览次数:42  
标签:自定义 int RecyclerView float 源码 layoutManager null recyclerView

直播软件源码,自定义RecyclerView支持快速滚动

问题描述:

 

RecyclerView自带快速滚动无法控制滚动条的长度唯一,也就是说随着item的增多,滚动条的长度会越变越小。

 

解决问题:

 

通过自定义RecyclerView来实现滚动条的长度不会因为item的增多而发生长度变化。

 

package com.emsm.app.widget;
 
import android.view.MotionEvent;
 
import androidx.annotation.NonNull;
import androidx.core.view.ViewCompat;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
 
import com.emsm.app.util.LogHelps;
 
/**
 * @Author chentao 0000668668
 * @Time 2023/2/10
 * @Description
 *  * 专注美妆(香水口红护肤)批发代发-供淘宝/天猫/京东/微商/代购/闲鱼等
 *  * 主做欧美大牌:迪奥/阿玛尼/祖马龙/香奈儿/古驰/TF/MAC/圣罗兰等等
 *  * 只做高品质产品!(送朋友亲人客户公司活动以及自用或泡妞等等)
 *  * +V:em-smart-99999
 */
public class ScrollerEvent {
    private RecyclerView mRecyclerView;
 
    private float mInitialBarHeight;
    private float mLastPressedYAdjustedToInitial;
    private int mLastAppBarLayoutOffset;
 
    public void attachRecyclerView(RecyclerView recyclerView, CallBack call) {
        this.mRecyclerView = recyclerView;
        this.mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                LogHelps.i("");
            }
 
            @Override
            public void onScrolled(@NonNull RecyclerView parent, int dx, int dy) {
                super.onScrolled(parent, dx, dy);
                if (call == null) {
                    return;
                }
 
                // 滚动条拇指的垂直范围
                float extent = parent.computeVerticalScrollExtent();
                //  可滚动的区域大小
                float range = parent.computeVerticalScrollRange();
                // 当前偏移量(当前滚动的距离)
                float offset = parent.computeVerticalScrollOffset();
                // 最大偏移量(最大可滚动的距离)
                float maxOffset = range - extent;
                // 可以滑动时,在绘制
                if (maxOffset > 0) {
                    // float offsetY = ratio * mMeasureHeight;
                    float ratio = offset / maxOffset;
                    LogHelps.i("dx:" + dx +
                            " dy:" + dy +
                            " extent:" + extent +
                            " range:" + range +
                            " offset:" + offset +
                            " maxOffset:" + maxOffset +
                            " ratio:" + ratio);
 
                    call.onScrolled(ratio);
                }
            }
        });
    }
 
    public boolean onTouchEvent(MotionEvent event, int viewHeight) {
        if (mRecyclerView == null || event == null) {
            return true;
        }
 
        if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
            mRecyclerView.stopScroll();
 
            int nestedScrollAxis = ViewCompat.SCROLL_AXIS_NONE;
            nestedScrollAxis |= ViewCompat.SCROLL_AXIS_VERTICAL;
 
            mRecyclerView.startNestedScroll(nestedScrollAxis);
 
            mInitialBarHeight = viewHeight;
            mLastPressedYAdjustedToInitial = event.getY() + 0;
        } else if (event.getActionMasked() == MotionEvent.ACTION_MOVE) {
            float newHandlePressedY = event.getY() + 0;
            int barHeight = viewHeight;
            float newHandlePressedYAdjustedToInitial = newHandlePressedY + (mInitialBarHeight - barHeight);
            float deltaPressedYFromLastAdjustedToInitial = newHandlePressedYAdjustedToInitial - mLastPressedYAdjustedToInitial;
 
            int dY = (int) ((deltaPressedYFromLastAdjustedToInitial / mInitialBarHeight) * (mRecyclerView.computeVerticalScrollRange() + 0));
            updateRvScroll(dY + mLastAppBarLayoutOffset);
 
            mLastPressedYAdjustedToInitial = newHandlePressedYAdjustedToInitial;
        } else if (event.getActionMasked() == MotionEvent.ACTION_UP) {
            mLastPressedYAdjustedToInitial = -1;
            mRecyclerView.stopNestedScroll();
        }
        return true;
    }
 
    public void updateRvScroll(int dY) {
        if (mRecyclerView == null) {
            return;
        }
        try {
            mRecyclerView.scrollBy(0, dY);
        } catch (Exception t) {
            t.printStackTrace();
        }
    }
 
    interface CallBack {
        // 滚动的比例值 0-1
        void onScrolled(float ratio);
    }
 
    /**
     * 判断是否可以滚动
     * @param recyclerView
     * @return
     */
    public static boolean isRecyclerScrollable(RecyclerView recyclerView) {
        if (recyclerView == null) {
            return false;
        }
 
        float range = recyclerView.computeVerticalScrollRange();
        float height = recyclerView.getHeight();
        // LogHelps.i("recyclerView的滚动范围 " + range + " | RecyclerView的高度 " + height);
        // 滚动范围大于RecyclerView的高度 说明是可以滚动的
        if (true) {
            return range > height;
        }
 
        boolean h = false;
        if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
            LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
            RecyclerView.Adapter adapter = recyclerView.getAdapter();
            if (layoutManager == null || adapter == null) {
                h = false;
            } else {
                h = layoutManager.findLastCompletelyVisibleItemPosition() < adapter.getItemCount() - 1;
            }
        } else if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {
            GridLayoutManager layoutManager = (GridLayoutManager) recyclerView.getLayoutManager();
            RecyclerView.Adapter adapter = recyclerView.getAdapter();
            if (layoutManager == null || adapter == null) {
                h = false;
            } else {
                h = layoutManager.findLastCompletelyVisibleItemPosition() < adapter.getItemCount() - 1;
            }
        } else if (recyclerView.getLayoutManager() instanceof StaggeredGridLayoutManager) {
            StaggeredGridLayoutManager layoutManager = (StaggeredGridLayoutManager) recyclerView.getLayoutManager();
            RecyclerView.Adapter adapter = recyclerView.getAdapter();
            if (layoutManager == null || adapter == null) {
                h = false;
            } else {
                h = layoutManager.findLastCompletelyVisibleItemPositions(null)[(layoutManager.getSpanCount() - 1)] < adapter.getItemCount() - 1;
            }
        }
 
        return h;
    }
 
}

以上就是 直播软件源码,自定义RecyclerView支持快速滚动,更多内容欢迎关注之后的文章

 

标签:自定义,int,RecyclerView,float,源码,layoutManager,null,recyclerView
From: https://www.cnblogs.com/yunbaomengnan/p/17336619.html

相关文章

  • Fedora 8下的MySQL源码安装手记
    评:系统开发计划改变!弃PostgreSQL!拥抱MySQL!当然前提是依然支持BerkeleyDB作为存储引擎的MySQL版本,5.1.12版本的MySQL已经正式将BDB从数据库引擎列表中扫地出门,虽然MySQL宣称这和Oracle收购Sleepycat没有任何关系,但是Oracle发面称是公司内部BDB开发团队要求取消支持的,所以也不太清......
  • JSP自定义标签开发入门
    评:简单深入赞一般情况下开发jsp自定义标签需要引用以下两个包 importjavax.servlet.jsp.*;importjavax.servlet.jsp.tagext.*; 首先我们需要大致了解开发自定义标签所涉及到的接口与类的层次结构(其中SimpleTag接口与SimpleTagSupport类是JSP2.0中新引入的)。 目标1:自......
  • 收藏 JSP自定义标签EL表达式取值问题
    给你个标签的例子自己看看吧!标签:<framework:VoucherCodeToNamecode=""/>tld.xml<tag><name>VoucherCodeToName</name><tagclass>com.itown.crm.fee.vouchermanager.util.VoucherCodeToNameTag</tagclass>&......
  • 记录一次使用 表达式引擎 自定义注解 还有 sql union all 实现对数据库数据提取、重组
    这样编写减少了前后端很多没必要的遍历,以及if判断并最大限度提高了代码的可变通性额外需要学习的是ORM框架下,如何接收多表(各表结构不同)操作后,sql返回的新结构的临时表问题表达式引擎用到的依赖<dependency><groupId>org.apache.commons</groupId>......
  • 源码安装 openresty
    #!/bin/bashrc#参考文档:https://openresty.org/en/installation.html#定义版本号OPENRESTY_VERSION=1.21.4.1#安装编译依赖yuminstallpcre-developenssl-develgcccurl-y#下载openresty源码curl-OLhttps://openresty.org/download/openresty-${OPENRESTY......
  • Vue3 自定义hook
    视频9.自定义hook函数什么是hook?——本质是一个函数,把setup函数中使用的CompositionAPI进行了封装。类似于vue2.x中的mixin。自定义hook的优势:复用代码,让setup中的逻辑更清楚易懂。componentsDemo.vue<template> <h2>当前求和为:{{sum}}</h2> <button@clic......
  • java学习日记20230415-LinkedHashSet源码
    LinkedHashSet全面说明:LinkedHashSet是HashSet子类;底层是一个LinkedHashMap,底层维护了一个数组和双向链表根据元素的hashCode值来决定元素的位置,同时使用链表维护元素的次序,使得元素看起来是以插入的顺序保存的不允许添加重复元素维护了一个hash表和双向链表,每个节点有pre和......
  • melange 基于源码构建apk 包的工具
    实际上melange是apko的相关项目,结合起来可以更好的创建基于apk的oci镜像,melange主要是定义了一套pipeline可以方便的进行apk包开发安装可以基于docker运行 goinstallchainguard.dev/melange@latest使用配置package:name:helloversion:2.12epoch:0description:"the......
  • vue2源码-九、异步更新
    异步更新异步更新原因以下情况下:vm.name='123'vm.name='234'vm.name='123'...如果我们频繁的修改一个数据,就会多次触发视图渲染dep.notify->watcher.update这样就会降低性能,因此就需要采用异步更新策略,仅仅在最后执行一次视图更新操作。思路当数据变化时,先......
  • 源码共读|vue2 工具函数
    前言本期源码共读的课程是学习vue2中的工具函数,学习优秀开源项目的代码的写作思路,看看他们在书写代码中都会考虑到那些问题。资源:源码位置:vue/util.tsatmain·vuejs/vue(github.com)学习目标分析源码学习源码中优秀代码和思想分析源码代码使用Typescript编写,......