当前位置: 首页 > news >正文

【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控制数据的滚动

项目需求 有一个文本数据比较长&#xff0c;需要在文本右侧加一个SeekBar&#xff0c;然后根据SeekBar的上下滚动来控制文本的滚动。 项目实现 我们使用TextView来显示文本&#xff0c;但是文本比较长的话&#xff0c;需要在TextView外面套一个ScrollView&#xff0c;但是我…...

新能源汽车的能源动脉:中国星坤汽车电缆在新能源汽车电气化中的应用!

随着新能源汽车行业的蓬勃发展&#xff0c;汽车电缆组件作为汽车电气系统的核心组成部分&#xff0c;其重要性日益凸显。中国星坤汽车电缆组件以其卓越的性能和创新技术&#xff0c;为汽车的电能传输、信号传递和控制提供了坚实的保障。本文将深入解析星坤汽车电缆组件的特性、…...

AVL许可证查询系统

在数字化时代&#xff0c;软件已经成为企业运营的核心组成部分。然而&#xff0c;随着软件应用的不断增加&#xff0c;许可证管理也变得越来越复杂。AVL许可证查询系统作为企业软件资产管理的重要工具&#xff0c;能够帮助企业实现对软件许可证的全面掌控。本文将深入探讨AVL许…...

四个步骤,帮你成为价值导向型项目经理

在企业数字化转型的浪潮下&#xff0c;项目管理的方向逐渐从任务导向转变为以价值交付为导向。在快速变化的市场环境中&#xff0c;仅仅关注项目任务的完成已不足以确保项目的成功&#xff0c;需要更加注重项目的最终成果和价值&#xff0c;确保项目能够为组织带来实际的价值和…...

Python3 使用 clickhouse-connect 操作 clickhouse

版本&#xff1a; Python 3.7 x86 clickhouse 24.6.1.3573 clickhouse-connect 0.6.22 代码一&#xff1a; # 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&#xff0c;如果浏览器已开启优先接管&am…...

Java中如何调用mysql中函数

在Java中调用MySQL中的函数&#xff08;无论是存储函数还是自定义函数&#xff09;&#xff0c;通常是通过JDBC&#xff08;Java Database Connectivity&#xff09;来完成的。以下是一个简单的步骤说明和示例代码&#xff0c;展示如何在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&#xff0c;划红线的地方&#xff0c;在命令行中点击右…...

Java学习 - Docker管理和容器命令 实例

docker管理 查看docker版本&#xff0c;检测是否可用 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…...

音频基础知识和音频指标

音频基础知识 声音 声音&#xff08;sound)是由物体振动产生的声波。物体在一秒钟之内振动的次数叫做频率&#xff0c;单位是赫兹&#xff0c;字母Hz。人耳可以识别的声音频率在 20 Hz~20000 Hz之间&#xff1b; 声音三要素&#xff1a; 响度 响度&#xff0c;…...

使用Vue CLI在其他磁盘创建项目出现错误及解决

Vue CLI是Vue.js官方推出的脚手架工具&#xff0c;可以帮我们快速的创建Vue项目框架。 我们创建Vue项目时一般默认都是在C盘&#xff0c;但由于某些因素我们需要在其他磁盘上创建Vue项目。 通过“winr”打开终端时默认位置都是C盘&#xff0c;但是Vue CLI不接受绝对路径作为参…...

关于lamda表达式的使用

Lambda表达式是一种匿名函数&#xff0c;即没有函数名的函数&#xff0c;它可以以更简洁、更灵活的方式编写代码。以下是Lambda表达式的常用方式&#xff1a; 无参数&#xff0c;无返回值&#xff1a; 如果抽象方法不带参数且不返回值&#xff0c;可以使用空括号和主体编写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&#xff08;最小&#xff09;配置详解 六、Nginx&#xff08;基础&#xff09;配置详解 七、反向代理 八、负载均衡 九、动静分离 十、报错 一、下载Nginx安装包 四…...

基于Redis实现共享session登录

搭配食用&#xff1a;Redis&#xff08;基础篇&#xff09;-CSDN博客 项目实现前的 Mysql中的表&#xff1a; 表说明tb_user用户表tb_user_info用户详情表tb_shop商户信息表tb_shop_type商户类型表tb_blog用户日记表&#xff08;达人探店日记)tb_follow用户关注表tb_voucher优…...

shell函数的定义

shell函数的定义 ​ 定义:将命令序列按照格式写在一起.格式指的是函数的固定格式 ​ 作用:方便重复使用,还可以做成函数库,集中在一起,随时可以传参调用,大的工程分割成小的模块,提高代码的可读性. 函数的格式 vim hanshu1.shfunction shopping {命令序列}shopping () {命令…...

vue部署宝塔nginx配置(获取用户ip地址、反代理访问api接口、websocket转发)

以下配置为我自己的需求&#xff0c;因人而异&#xff0c;如果只是单纯的前端非交互页面&#xff0c;可以不用修改配置。 代码及注释&#xff0c;如下&#xff1a; #解决vue-router设置mode为history&#xff0c;去掉路由地址上的/#/后nginx显示404的问题location / {proxy_htt…...

Jenkins教程-3-github自动化测试任务构建

上一小节我们学习了Jenkins在windows和mac系统上安装搭建环境的方法&#xff0c;本小节我们讲解一下Jenkins构建github自动化测试任务的方法。 接下来我们以windows系统为例&#xff0c;讲解一下构建实际自动化测试任务的具体步骤。 安装git和github插件 点击进入Jenkins插件…...

0元体验苹果macOS系统,最简单的虚拟机部署macOS教程

前言 最近发现小伙伴热衷于在VMware上安装体验macOS系统&#xff0c;所以就有了今天的帖子。 正文开始 首先&#xff0c;鉴于小伙伴们热衷macOS&#xff0c;所以小白搜罗了一圈macOS系统&#xff0c;并开启了分享通道。 本次更新的系统版本是&#xff1a; macOS 10.13.6 ma…...

3步解决Atlas OS中Xbox登录错误0x89235107的实用方案

3步解决Atlas OS中Xbox登录错误0x89235107的实用方案 【免费下载链接】Atlas &#x1f680; An open and lightweight modification to Windows, designed to optimize performance, privacy and security. 项目地址: https://gitcode.com/GitHub_Trending/atlas1/Atlas …...

保姆级教程:用Brainstorm搞定运动想象EEG分析,从时频图到分类器实战

保姆级教程&#xff1a;用Brainstorm搞定运动想象EEG分析&#xff0c;从时频图到分类器实战 运动想象脑电&#xff08;EEG&#xff09;分析是脑机接口&#xff08;BCI&#xff09;研究中的经典课题&#xff0c;也是许多研究生和初学者的第一个实战项目。但面对复杂的信号处理和…...

手把手教你排查Windows系统错误1114:从DLL加载原理到MySQL驱动修复

深入解析Windows系统错误1114&#xff1a;从DLL加载机制到MySQL驱动故障修复实战 当你在配置MySQL ODBC数据源时突然遭遇"系统错误1114&#xff1a;动态链接库(DLL)初始化例程失败"的红色警告框&#xff0c;那种挫败感我深有体会。这个看似简单的错误背后&#xff0…...

uniapp复制文本的两种实现方式对比:从基础到进阶

Uniapp复制文本功能深度解析&#xff1a;从基础实现到跨平台适配 在移动应用和H5页面开发中&#xff0c;复制文本到剪贴板是一个看似简单却直接影响用户体验的基础功能。作为一款跨平台开发框架&#xff0c;Uniapp提供了多种实现方式&#xff0c;但每种方法都有其特定的适用场…...

CoPaw模型多轮对话效果深度评测:连贯性、逻辑性与知识准确性

CoPaw模型多轮对话效果深度评测&#xff1a;连贯性、逻辑性与知识准确性 1. 开场白&#xff1a;为什么关注多轮对话能力 最近测试了不下20个大语言模型&#xff0c;发现一个有趣现象&#xff1a;单轮问答表现都不错&#xff0c;但一到多轮对话就原形毕露。有的模型聊着聊着就…...

JBoltAI视频SOP平台:山东工业“智”变新助力

在国家“十五五”发展规划强调“人工智能”工业融合的背景下&#xff0c;山东省及威海市的工业制造业企业正迎来智能化转型的关键期。山东向量空间人工智能科技有限公司推出的JBoltAI工业数智化SOP管理平台&#xff0c;凭借其独特优势&#xff0c;正成为推动这一转型的重要力量…...

Qwen3-4B-Thinking环境部署:vLLM推理加速+Web前端调用完整步骤

Qwen3-4B-Thinking环境部署&#xff1a;vLLM推理加速Web前端调用完整步骤 1. 开篇&#xff1a;为什么你需要这个组合方案&#xff1f; 如果你正在寻找一个既能快速推理大模型&#xff0c;又能通过网页轻松对话的解决方案&#xff0c;那么你来对地方了。今天要介绍的&#xff…...

AudioLDM-S实战教程:为有声书项目批量生成章节过渡音效(含脚本)

AudioLDM-S实战教程&#xff1a;为有声书项目批量生成章节过渡音效&#xff08;含脚本&#xff09; 1. 项目简介 AudioLDM-S是一个专门生成现实环境音效的AI工具&#xff0c;基于audioldm-s-full-v2模型的轻量级Gradio实现。无论你需要电影配音、游戏音效还是助眠白噪音&…...

手把手教你用s2-pro:上传参考音频,轻松生成同款语音播报

手把手教你用s2-pro&#xff1a;上传参考音频&#xff0c;轻松生成同款语音播报 1. s2-pro语音合成镜像简介 s2-pro是Fish Audio开源的专业级语音合成模型镜像&#xff0c;它让普通用户也能轻松实现高质量的文本转语音功能。与常见的语音合成工具不同&#xff0c;s2-pro有一个…...

Qwen2.5-0.5B Instruct在软件测试中的自动化应用

Qwen2.5-0.5B Instruct在软件测试中的自动化应用 1. 引言 软件测试是确保产品质量的关键环节&#xff0c;但传统测试方法往往耗时费力。开发人员需要编写大量测试用例&#xff0c;执行重复的测试流程&#xff0c;还要分析复杂的测试结果。这个过程不仅枯燥&#xff0c;还容易…...