自定义 View 循环滚动刻度控件
LoopScaleView
先看效果图:
LoopScaleView 是一个自定义的刻度尺风格的选值控件,从上面的动图大家可以看到 LoopScaleView 的运行效果.可以设置屏幕内显示的刻度数,也可以设置每一个刻度代表的值得大小。
LoopScaleView.class
Nested class
OnValueChangeListener | 刻度取值监听接口 |
Public methods
方法名 | 返回值类型 | 说明 |
---|---|---|
getItemsCount() | int | 获取总的刻度数 |
setCursorColor(int color) | void | 设置游标颜色(游标不采用图片时) |
setCursorWidth(int width) | void | 设置游标宽度(同上) |
setCursorMap(Bitmap map) | void | 设置图片作为游标 |
setScaleWidth(int scaleWidth) | void | 设置刻度宽度 |
setShowItemSize(int showItemSize) | void | 设置屏幕内可见的大刻度数 |
setScaleHeight(float scaleHeight) | void | 设置刻度的高度 |
setLineColor(int lineColor) | void | 设置底部直线的颜色 |
setScaleTextColor(int scaleTextColor) | void | 设置刻度标值的颜色 |
setScaleTextSize(int scaleTextSize) | void | 设置刻度标值的文字大小 |
setMaxValue(int maxValue) | void | 设置最大值 |
setOneItemValue(int oneItemValue) | void | 设置一个刻度表示的值的大小 |
setCurrentValue(int currValue) | void | 设置当前的值 |
分解剖析
- onMeasure 方法中初始化一个刻度的像素宽度,整个视图的宽度
@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);viewHeight = MeasureSpec.getSize(heightMeasureSpec);//一个小刻度的宽度(十进制,每5个小刻度为一个大刻度)scaleDistance = getMeasuredWidth() / (showItemSize * 5);//尺子长度总的个数*一个的宽度viewWidth = maxValue / oneItemValue * scaleDistance;maxX = getItemsCount() * scaleDistance;minX = -maxX;}复制代码
- onDraw() 方法重写绘制 ScaleView 的视图
@Overrideprotected void onDraw(Canvas canvas) {canvas.clipRect(getPaddingStart(), getPaddingTop(), getWidth() - getPaddingRight(), viewHeight - getPaddingBottom());// 绘制底部线条drawLine(canvas);// 绘制游标drawCursor(canvas);paint = new Paint(Paint.ANTI_ALIAS_FLAG);paint.setStrokeWidth(scaleWidth);// 绘制反向的一个刻度尺for (int i = 0; i < maxValue / oneItemValue; i++) {//drawScale 为绘制刻度线的方法drawScale(canvas, i, -1);}//绘制正向的一个刻度尺for (int i = 0; i < maxValue / oneItemValue; i++) {//drawScale 为绘制刻度线的方法drawScale(canvas, i, 1);}}复制代码
可以看出上面的绘制过程,实际上是绘制出了两个刻度尺。经过上面的步骤,静止状态下的 ScaleView 已经绘制完成,接下来就是要让他动起来了
手势识别来处理滑动
在 onTouchEvent() 方法中将触摸事件交给手势识别 GestureDetector.SimpleOnGestureListener 来处理:/*** 滑动手势处理*/private GestureDetector.SimpleOnGestureListener gestureListener = new GestureDetector.SimpleOnGestureListener() {@Overridepublic boolean onDown(MotionEvent e) {return true;}//滚动事件public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {scrollView(distanceX);return true;}//快速滑动时间public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {if (!mScroller.computeScrollOffset()) {mScroller.fling((int) currLocation, 0, (int) (-velocityX / 1.5), 0, minX, maxX, 0, 0);setNextMessage(0);}return true;}@Overridepublic boolean onSingleTapUp(MotionEvent e) {return super.onSingleTapUp(e);}};复制代码
上述代码主要注意两个地方:onScroll() 和 onFling()。当正常左右滑动时,触发 onScroll 方法调用 srcollView(float distance) 对整个视图进行重绘。当快速惯性滑动时通过 Scroller 让惯性滑动变得流畅,惯性滑动的状态更新是通过 Handler 进行不断的查询 Scroller 的执行状态得到的,当 Scroller 执行完惯性滑动的动画到达目的地时,停止 Handler 的查询任务,当 onFling 多次触发时只会执行第一次的状态。
- 循环滚动的实现
开始说到的绘制了正向反向两个方向的刻度尺即是为了实现循环滚动而设定的,在 drawScale() 方法中有如下代码:if (currLocation + showItemSize / 2 * 5 * scaleDistance >= viewWidth) {currLocation = -showItemSize / 2 * 5 * scaleDistance;float speed = mScroller.getCurrVelocity();mScroller.fling((int) currLocation, 0, (int) speed, 0, minX, maxX, 0, 0);setNextMessage(0);} else if (currLocation - showItemSize / 2 * 5 * scaleDistance <= -viewWidth) {currLocation = showItemSize / 2 * 5 * scaleDistance;float speed = mScroller.getCurrVelocity();mScroller.fling((int) currLocation, 0, (int) speed, 0, minX, maxX, 0, 0);setNextMessage(0);}复制代码
当 currLocation 加上可视视图一半的距离大于刻度尺的宽度 viewWidth 或者 currLocation 减去可视视图一半的距离小于 -viewWidth 时(即正向或者反向滑到最大/最小值时)通过为 currLocation 重新赋值将刻度值重置,来达到循环滚动的目的.如果到达临界点时是在 Scroller 执行快速滑动的过程则重置之后需要再为 Scroller 重新设置初速度来达到流畅的滑动.
基本思路就是上面所说的这样了,详细操作大家自己查看 LoopScaleView 的源码。接入使用
project's build.gradle (工程的 build.gradle)
allprojects {repositories {jcenter()maven{url "http://dl.bintray.com/huxinyu/maven"}} }复制代码
module's build.gradle (模块的build.gradle)
dependencies {compile 'com.pandaq:loopscale:1.0.1' }复制代码
- xml 文件中进行属性配置,这些属性也可以通过 Java 代码进行修改
<com.pandaq.loopscaleview.LoopScaleViewandroid:id="@+id/lsv_4"android:layout_width="match_parent"android:layout_height="50dp"android:layout_margin="8dp"android:background="@drawable/loopscaleview_bg"android:padding="8dp"app:cursorColor="@color/colorAccent"app:maxShowItem="4"app:maxValue="1000"app:oneItemValue="5"app:scaleTextColor="@color/colorPrimary"/>复制代码
最后
觉得本文对你有帮助
简书PandaQ404
掘金PandaQ
GithubPandaQAQ
持续分享中,欢迎关注和 star。。。
自定义 View 循环滚动刻度控件相关推荐
- Kotlin 自定义View之实现标尺控件(选择身高、体重等)
本篇文章讲的是Kotlin 自定义view之实现标尺控件Ruler,以选择身高.体重等.开发中,当我们需要获取用户的身高和体重等信息时,如果直接让他们输入,显然体验不够好.像类似于唯品会.好轻等APP ...
- android lrc 歌词view,自定义View强势来袭,用自定义View实现歌词显示控件下篇之自定义LyricView的实现...
在上篇中,我与大家分享了关于如何进行*.lrc歌词文件的解析,以及将解析完成后的歌词展示在镶嵌在ScrollView中的TextView上,就这样而言,一个简单的歌词显示功能也就实现了. 但是,如何才 ...
- android歌词效果,自定义View:Android歌词控件
TicktockMusic 音乐播放器项目相关文章汇总: 简介 之前做 TicktockMusic 音乐播放器,一个必要的需求肯定是歌词,在 github 上找了几个,发现或多或少都有点不满足需求,所 ...
- Android Paint应用之自定义View实现进度条控件
在上一篇文章<Android神笔之Paint>学习了Paint的基本用法,但是具体的应用我们还没有实践过.从标题中可知,本文是带领读者使用Paint,自定义一个进度条控件. 上图就是本文要 ...
- Android自定义View 多边形能力分析控件,雷达图(蛛网)动态实现
自定义View实现雷达图还是挺简单的,它能让使用让使用者能一目了然的了解各项指标的变动情形以及好坏趋势.使用得最多的便是Path路径,很适合初学者用来练习. 效果图如下: 下面是实体类的属性: pub ...
- iOS 自定义无限循环滚动广告动画控件
iOS 自定义无限循环广告动画控件 自定义循环滚动的广告控件,支持水平和竖直两个动画方向,页码标记是自定义的,可以随意控制大小位置和颜色等 效果图: 下载地址: https://github.com ...
- mysql抽屉图标_React Native自定义组件实现抽屉菜单控件效果
一.需求分析 原生开发中,自定义View可谓是屡见不鲜的事情,往往系统的控件总不能满足现实的需求.五花八门的产品设计需要我们做出不同的View.关于自定义View的内容网上已经有很多的博文,本篇博客要 ...
- WPF中自定义的DataTemplate中的控件,在Window_Loaded事件中加载机制初探
原文:WPF中自定义的DataTemplate中的控件,在Window_Loaded事件中加载机制初探 最近因为项目需要,开始学习如何使用WPF开发桌面程序.使用WPF一段时间之后,感觉WPF的开发思 ...
- 【Android】App首页上下滚动快报控件 通知控件 类似京东快报控件(一)
前言 快过年了,对于大伙来说手头上的事情做完没有呢,马上也该让自己轻松一阵子了,哈哈哈.好,说正事,由于公司App这个版本首页的改版,新增了很多新的控件,类似于京东快报这种控件的话我在写之前也去找了一 ...
最新文章
- 0730------Linux网络编程----------服务器端模型(迭代,多进程,多线程,select,poll,epoll 等)...
- wangEditor 菜单栏随页面滚动位置改变(吸顶)问题解决
- git使用-设置项目忽略文件
- textarea 高度调整
- 计算机技术在工程的应用浅论,《计算机技术在计算机应用技术中的应用浅论》...
- Python实现字符串反转的6种方法
- 我感觉ae比较难用,就是做这种画中画的视频,final cut pro真香
- IOS 输入框 placeholder字体的颜色
- android蓝牙设计与实现,一个Android客户端的蓝牙支付系统设计与实现
- 【本人秃顶程序员】深入理解Java——ConcurrentHashMap源码的分析(JDK1.8)
- 利用mycat实现mysql数据库读写分离
- php 伸展菜单代码,上下伸展的JS菜单
- .Net中应用XML动态生成窗体
- Python杂记-set()
- SEP客户端部署方式及故障处理手册____借鉴文档的思路方法
- opencv 运动检测 二帧差法
- 美丽的花蝴蝶 动人的海豚音 天后[Mariah Carey玛丽亚·凯莉]全集
- 视频教程-微信公众号编辑器开发-微信公众号开发11-微信开发php-微信开发
- 代码仓库已移步http://202.119.84.104:8088/Socialbiao/bookdinner
- 邢台计算机编程培训学校,邢台有几家计算机培训中心
热门文章
- linux内核设计与实现---从内核出发
- php的range函数
- vivo C/C++工程师视频面试总结 20180802
- windows C++ 通过WMI获取底层信息
- BZOJ-2005能量采集-数论函数
- 【Linux】编译C语言文件(-o -lpthread)
- 01-复杂度2 Maximum Subsequence Sum (25 分)
- 1073 多选题常见计分法 (20 分)
- 最高效的进(线)程间通信机制--eventfd
- android md 控件,Android基本UI控件.md