【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…...

IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...

对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...