【Android】使用SeekBar控制数据的滚动
项目需求
有一个文本数据比较长,需要在文本右侧加一个SeekBar,然后根据SeekBar的上下滚动来控制文本的滚动。
项目实现
我们使用TextView来显示文本,但是文本比较长的话,需要在TextView外面套一个ScrollView,但是我们现在这个文本是上下滚动的,很巧不巧的是我们的文本在一个上下滚动的Recyclerview的item里面,这下就很搞了,因为两个都是上下滚动的,我们需要做一个处理。
首先,自定义一个ScrollView
public class NonScrollableScrollView extends ScrollView {public NonScrollableScrollView(Context context) {super(context);}public NonScrollableScrollView(Context context, AttributeSet attrs) {super(context, attrs);}public NonScrollableScrollView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overridepublic boolean onTouchEvent(MotionEvent ev) {return false;}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {return false;}
}
重写其触摸事件方法使其不响应触摸事件。所有这样的话我们的TextView就不能通过自己滚动了,然后我们通过这个SeekBar来控制TextView的滚动
接下来是对SeekBar的修改,以下部分内容来自知乎
https://zhuanlan.zhihu.com/p/622534050
@SuppressLint("AppCompatCustomView")
public class VerticalSeekBar extends SeekBar {private boolean isTopToBottom = false;//显示进度方向是否从上到下,默认false(从下到上)public VerticalSeekBar(Context context) {super(context);}public VerticalSeekBar(Context context, AttributeSet attrs) {super(context, attrs);TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.VerticalSeekBar, 0, 0);try {isTopToBottom = ta.getBoolean(R.styleable.VerticalSeekBar_isTopToBottom, false);} finally {ta.recycle();}}public VerticalSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}public void setOnSeekBarChangeListener(OnSeekBarChangeListener l) {mOnSeekBarChangeListener = l;}void onStartTrackingTouch() {if (mOnSeekBarChangeListener != null) {mOnSeekBarChangeListener.onStartTrackingTouch(this);}}void onStopTrackingTouch() {if (mOnSeekBarChangeListener != null) {mOnSeekBarChangeListener.onStopTrackingTouch(this);}}protected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(h, w, oldh, oldw);}@Overridepublic synchronized void setProgress(int progress) {super.setProgress(progress);onSizeChanged(getWidth(), getHeight(), 0, 0);}@Overrideprotected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(heightMeasureSpec, widthMeasureSpec);setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());}protected void onDraw(Canvas c) {if (isTopToBottom) {//显示进度方向 从上到下c.rotate(90);c.translate(0, -getWidth());} else {//显示进度方向 从下到上c.rotate(-90);c.translate(-getHeight(), 0);}super.onDraw(c);}@Overridepublic boolean onTouchEvent(MotionEvent event) {if (!isEnabled()) {return false;}switch (event.getAction()) {case MotionEvent.ACTION_DOWN:onStartTrackingTouch();trackTouchEvent(event);break;case MotionEvent.ACTION_MOVE:trackTouchEvent(event);attemptClaimDrag();break;case MotionEvent.ACTION_UP:trackTouchEvent(event);onStopTrackingTouch();break;case MotionEvent.ACTION_CANCEL:onStopTrackingTouch();break;}return true;
// getParent().requestDisallowInterceptTouchEvent(true);
// return super.onTouchEvent(event);}private void trackTouchEvent(MotionEvent event) {//关键更改2int progress = getMax() - (int) (getMax() * event.getY() / getHeight());//触摸进度方向 从下到上if (isTopToBottom) {progress = (int) (getMax() * event.getY() / getHeight());//触摸进度方向 从上到下}setProgress(progress);if (mOnSeekBarChangeListener != null) {mOnSeekBarChangeListener.onProgressChanged(this, progress);}}private void attemptClaimDrag() {if (getParent() != null) {getParent().requestDisallowInterceptTouchEvent(true);}}public boolean dispatchKeyEvent(KeyEvent event) {if (event.getAction() == KeyEvent.ACTION_DOWN) {KeyEvent newEvent = null;switch (event.getKeyCode()) {case KeyEvent.KEYCODE_DPAD_UP:newEvent = new KeyEvent(KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_DPAD_RIGHT);break;case KeyEvent.KEYCODE_DPAD_DOWN:newEvent = new KeyEvent(KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_DPAD_LEFT);break;case KeyEvent.KEYCODE_DPAD_LEFT:newEvent = new KeyEvent(KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_DPAD_DOWN);break;case KeyEvent.KEYCODE_DPAD_RIGHT:newEvent = new KeyEvent(KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_DPAD_UP);break;default:newEvent = new KeyEvent(KeyEvent.ACTION_DOWN,event.getKeyCode());break;}KeyEvent.DispatcherState dispatcherState = new KeyEvent.DispatcherState();dispatcherState.isTracking(event);return newEvent.dispatch(this, dispatcherState, event);}return false;}/*** 设置显示进度方向** @param isTopToBottom true 方向从上到下*/public void setTopToBottom(boolean isTopToBottom) {this.isTopToBottom = isTopToBottom;}private OnSeekBarChangeListener mOnSeekBarChangeListener;public interface OnSeekBarChangeListener {void onProgressChanged(VerticalSeekBar VerticalSeekBar, int progress);void onStartTrackingTouch(VerticalSeekBar VerticalSeekBar);void onStopTrackingTouch(VerticalSeekBar VerticalSeekBar);}
}
需要在attrs文件里面添加 (需要注意,因为在知乎上面没有这个东西)
<declare-styleable name="VerticalSeekBar"><attr name="isTopToBottom" format="boolean" /></declare-styleable>
设置 progress_vertical_drawable2
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"><item android:id="@android:id/background"><shape><corners android:radius="5dp" /><solid android:color="#D9EFFF" /></shape></item><item android:id="@android:id/progress"><scale android:scaleWidth="100%"><shape><corners android:radius="5dp" /><solid android:color="#5EB2FF" /></shape></scale></item><item android:id="@android:id/secondaryProgress"><scale android:scaleWidth="100%"><shape><corners android:radius="5dp" /><solid android:color="#5EB2FF" /></shape></scale></item>
</layer-list>
设置ic_thumb
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"><itemandroid:width="@dimen/dp_20"android:height="@dimen/dp_20"><shape android:shape="oval"><gradientandroid:angle="180"android:endColor="#1C000000"android:startColor="#1Cffffff" /></shape></item><itemandroid:bottom="1dp"android:left="1dp"android:right="1dp"android:top="1dp"><shape android:shape="oval"><solid android:color="#5EB2FF" /><strokeandroid:width="6dp"android:color="#FFFFFF" /></shape></item>
</layer-list>
设置Style
<!--自定义SeekBar样式--><style name="SeekbarStyle"><item name="android:indeterminateDrawable"><!--未知资源时显示-->@android:drawable/progress_indeterminate_horizontal</item><item name="android:progressDrawable">@drawable/progress_vertical_drawable2</item><item name="android:max">100</item><item name="android:progress">0</item><item name="android:maxHeight">@dimen/dp_60</item>
<!-- <item name="android:minHeight">@dimen/dp_10</item>--><item name="android:thumb">@drawable/ic_thumb</item>
<!-- <item name="android:thumbOffset">@dimen/dp_20</item>--></style>
然后就可以在xml布局中使用了
<com.complex.app.view.VerticalSeekBarandroid:id="@+id/seekBar_Text"style="@style/SeekbarStyle"android:layout_width="wrap_content"android:layout_height="@dimen/dp_60"android:background="@android:color/transparent"android:splitTrack="false"app:isTopToBottom="true" />
android:splitTrack="false"是为了让这个滑块周围的背景变的透明,不然就只能是一个正方形的滑块图案了
然后我们在RecyclerView的Adapter里面进行设置
protected void convert(BaseViewHolder helper, ElectronicFencePoint item) {NonScrollableScrollView scrollView = helper.getView(R.id.ns_scroll);VerticalSeekBar seekBar = helper.getView(R.id.seekBar_Text);scrollView.post(() -> {int maxScroll = scrollView.getChildAt(0).getHeight() - scrollView.getHeight();if (maxScroll <= 0) {//这里我的逻辑是当TextView的文本显示内容不多不需要滑动的时候,设置滑块滑动到底部显示seekBar.setProgress(seekBar.getMax());} else {//当TextView的文本很多,需要滑动的时候,将滑块放在顶部seekBar.setProgress(0);seekBar.setMax(maxScroll);}});seekBar.setOnSeekBarChangeListener(new VerticalSeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(VerticalSeekBar VerticalSeekBar, int progress) {scrollView.scrollTo(0, progress);}@Overridepublic void onStartTrackingTouch(VerticalSeekBar VerticalSeekBar) {}@Overridepublic void onStopTrackingTouch(VerticalSeekBar VerticalSeekBar) {}});scrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() {@Overridepublic void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {seekBar.setProgress(scrollY);}});
}
补充:
开始滑动前:

开始滑动后

这个只需要修改一下样式就好了
ic_thumb
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"><itemandroid:width="@dimen/dp_15"android:height="@dimen/dp_15"><shape android:shape="oval"><gradientandroid:endColor="#1C000000"android:startColor="#1Cffffff" /></shape></item><itemandroid:bottom="1dp"android:left="1dp"android:right="1dp"android:top="1dp"><shape android:shape="oval"><solid android:color="#5EB2FF" /><strokeandroid:width="2dp"android:color="#FFFFFF" /></shape></item>
</layer-list>
progress_vertical_drawable2
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"><!--设置滑轨颜色:滑过部分和未滑过部分--><!--未滑过部分滑轨颜色--><itemandroid:id="@android:id/background"android:height="4dp"android:gravity="center"><shape><corners android:radius="67dp"/><solid android:color="#4d000000"/></shape></item><!--滑过部分滑轨颜色--><itemandroid:id="@android:id/progress"android:height="6dp"android:gravity="center"><clip><shape><corners android:radius="67dp"/><solid android:color="#2196F3"/></shape></clip></item>
</layer-list>
SeekbarStyle
<!--自定义SeekBar样式--><style name="SeekbarStyle" parent="Widget.AppCompat.SeekBar"><item name="android:progressDrawable">@drawable/progress_vertical_drawable2</item><item name="android:thumb">@drawable/ic_thumb</item></style>
xml应用
<com.southgnss.digitalconstruction.view.VerticalSeekBarandroid:id="@+id/seekBar_Text"style="@style/SeekbarStyle"android:layout_width="@dimen/dp_20"android:layout_height="@dimen/dp_60"android:background="@null"android:splitTrack="false"app:isTopToBottom="true" /></LinearLayout>
相关文章:
【Android】使用SeekBar控制数据的滚动
项目需求 有一个文本数据比较长,需要在文本右侧加一个SeekBar,然后根据SeekBar的上下滚动来控制文本的滚动。 项目实现 我们使用TextView来显示文本,但是文本比较长的话,需要在TextView外面套一个ScrollView,但是我…...
新能源汽车的能源动脉:中国星坤汽车电缆在新能源汽车电气化中的应用!
随着新能源汽车行业的蓬勃发展,汽车电缆组件作为汽车电气系统的核心组成部分,其重要性日益凸显。中国星坤汽车电缆组件以其卓越的性能和创新技术,为汽车的电能传输、信号传递和控制提供了坚实的保障。本文将深入解析星坤汽车电缆组件的特性、…...
AVL许可证查询系统
在数字化时代,软件已经成为企业运营的核心组成部分。然而,随着软件应用的不断增加,许可证管理也变得越来越复杂。AVL许可证查询系统作为企业软件资产管理的重要工具,能够帮助企业实现对软件许可证的全面掌控。本文将深入探讨AVL许…...
四个步骤,帮你成为价值导向型项目经理
在企业数字化转型的浪潮下,项目管理的方向逐渐从任务导向转变为以价值交付为导向。在快速变化的市场环境中,仅仅关注项目任务的完成已不足以确保项目的成功,需要更加注重项目的最终成果和价值,确保项目能够为组织带来实际的价值和…...
Python3 使用 clickhouse-connect 操作 clickhouse
版本: Python 3.7 x86 clickhouse 24.6.1.3573 clickhouse-connect 0.6.22 代码一: # pip install clickhouse-connectimport clickhouse_connect# 准备参数 host "192.168.1.112" port 8123 username "default" passw…...
Python脚手架系列-DrissionPage
记录DrissionPage模块使用中的一些常常复用的代码,持续更新… 接管谷歌浏览器 from DrissionPage import ChromiumPage, ChromiumOptionsco ChromiumOptions().set_local_port(4249) driver ChromiumPage(addr_or_optsco)创建driver,如果浏览器已开启优先接管&am…...
Java中如何调用mysql中函数
在Java中调用MySQL中的函数(无论是存储函数还是自定义函数),通常是通过JDBC(Java Database Connectivity)来完成的。以下是一个简单的步骤说明和示例代码,展示如何在Java中调用MySQL中的函数。 步骤 添加…...
Huggingface-cli 登录最新版(2024)
安装Huggingface-cli pip install -U "huggingface_hub[cli]"设置好git的邮箱和用户名和huggingface的github账号一致 git config --global user.mail xxx git config --global user.name xxx登录 复制token,划红线的地方,在命令行中点击右…...
Java学习 - Docker管理和容器命令 实例
docker管理 查看docker版本,检测是否可用 sudo docker version查看docker 系统信息 sudo docker infodocker容器命令 容器状态 容器标识 容器长uuid容器短uuid容器名字 查看容器状态 sudo docker status [容器标识1] [容器标识2] [容器标识n]深入查看容器信息 su…...
下载工程resources目录下的模板excel文件
一、添加依赖 <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.1.0</version> </dependency> 二、编写接口 GetMapping("/downloadTemplate")public void downlo…...
音频基础知识和音频指标
音频基础知识 声音 声音(sound)是由物体振动产生的声波。物体在一秒钟之内振动的次数叫做频率,单位是赫兹,字母Hz。人耳可以识别的声音频率在 20 Hz~20000 Hz之间; 声音三要素: 响度 响度,…...
使用Vue CLI在其他磁盘创建项目出现错误及解决
Vue CLI是Vue.js官方推出的脚手架工具,可以帮我们快速的创建Vue项目框架。 我们创建Vue项目时一般默认都是在C盘,但由于某些因素我们需要在其他磁盘上创建Vue项目。 通过“winr”打开终端时默认位置都是C盘,但是Vue CLI不接受绝对路径作为参…...
关于lamda表达式的使用
Lambda表达式是一种匿名函数,即没有函数名的函数,它可以以更简洁、更灵活的方式编写代码。以下是Lambda表达式的常用方式: 无参数,无返回值: 如果抽象方法不带参数且不返回值,可以使用空括号和主体编写Lam…...
Android替换默认的按键音
替换audio_assets.xml文件 此文件在AudioService.java被调用 <!--文件位置 /frameworks/base/core/res/res/xml/--> <audio_assets version"1.0"><group name"touch_sounds"><asset id"FX_KEY_CLICK" file"Effect…...
Windows 服务器Nginx 下载、部署、配置流程(图文教程)
不定期更新 目录 一、下载Nginx安装包 二、上传安装包 三、启动Nginx 四、Nginx常用命令 五、Nginx(最小)配置详解 六、Nginx(基础)配置详解 七、反向代理 八、负载均衡 九、动静分离 十、报错 一、下载Nginx安装包 四…...
基于Redis实现共享session登录
搭配食用:Redis(基础篇)-CSDN博客 项目实现前的 Mysql中的表: 表说明tb_user用户表tb_user_info用户详情表tb_shop商户信息表tb_shop_type商户类型表tb_blog用户日记表(达人探店日记)tb_follow用户关注表tb_voucher优…...
shell函数的定义
shell函数的定义 定义:将命令序列按照格式写在一起.格式指的是函数的固定格式 作用:方便重复使用,还可以做成函数库,集中在一起,随时可以传参调用,大的工程分割成小的模块,提高代码的可读性. 函数的格式 vim hanshu1.shfunction shopping {命令序列}shopping () {命令…...
vue部署宝塔nginx配置(获取用户ip地址、反代理访问api接口、websocket转发)
以下配置为我自己的需求,因人而异,如果只是单纯的前端非交互页面,可以不用修改配置。 代码及注释,如下: #解决vue-router设置mode为history,去掉路由地址上的/#/后nginx显示404的问题location / {proxy_htt…...
Jenkins教程-3-github自动化测试任务构建
上一小节我们学习了Jenkins在windows和mac系统上安装搭建环境的方法,本小节我们讲解一下Jenkins构建github自动化测试任务的方法。 接下来我们以windows系统为例,讲解一下构建实际自动化测试任务的具体步骤。 安装git和github插件 点击进入Jenkins插件…...
0元体验苹果macOS系统,最简单的虚拟机部署macOS教程
前言 最近发现小伙伴热衷于在VMware上安装体验macOS系统,所以就有了今天的帖子。 正文开始 首先,鉴于小伙伴们热衷macOS,所以小白搜罗了一圈macOS系统,并开启了分享通道。 本次更新的系统版本是: macOS 10.13.6 ma…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
