Android UI-薄荷健康尺子

Posted 小陈乱敲代码

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android UI-薄荷健康尺子相关的知识,希望对你有一定的参考价值。

效果

源码:HenCoder-CustomView: HenCoder-三篇自定义View仿写 (gitee.com)

原的

仿的

功能点分析

  1. 根据尺子的量程 和 分度值 绘制尺子的静态效果
  2. 内容滑动,计算滑动边界
  3. 惯性滑动,智能定位
  4. 计算当前刻度值
  5. 基准线居中

实现分析

绘制尺子刻度

  1. 分度值:即最小刻度值,就是在测量仪器所能读出的最小值,指测量工具上相邻的两个刻度之间的最小格的数值
  2. 绘制尺子刻度,肯定要用到循环,最简单的办法,知道尺子的刻度总数,即可把尺子绘制出来。
  3. 尺子的刻度数根据 量程和分度值确定。上图尺子同样的量程 有两个分度值,尺子的刻度数完全不同
  4. 刻度数的计算:量程/分度值。 比如:
    1. 度量范围20~100,量程是80,分度值是1。 一共80个刻度
    2. 但凡事总有例外,度量范围0~100,量程100,分度值1,并不是100个刻度,而是一百零一个刻度。
    3. 0也算一个刻度,0 ~ 100 是101个数。1~100才是100个数。 程序员应该很好理解吧,毕竟从入行开始,数的起始就不是1了🐶
  5. 尺子的刻度一般都是10进制,则取余数 i % 10 == 0 表明是大刻度,其余的都是小刻度。
  6. 定义变量,刻度的长款,间隔。已经知道总刻度数,通过循环遍历即可绘制出尺子的静态样式
  7. 绘制文字比较简单 每次取余数 i % 10 == 0 表示大刻度,需要绘制文字,坐标微调即可。

尺子的滑动

  1. 滑动分两种,内容滑动和拖拽滑动。
    1. 内容滑动场景是:ScrollView ,ListView,RecyclerView,在有限的位置固定的空间内可以展示无限内容。
    2. 拖拽滑动指View内容不变,位置变化。应用场景是微信语音,视频电话的小窗口。
  2. 尺子的滑动是内容滑动
    1. 重写onTouchEvent() 。记录每次手指滑动产生的坐标,上一次坐标与当前坐标相减,计算滑动距离。
    2. 在move事件中,调用scrollBy() 传入滑动距离,内容滑动完成
  3. 惯性滑动组件介绍
    1. 仅仅使用scrollBy() 滑动无惯性,效果比较生硬,与系统滑动组件的体验相差比较多
    2. 结合 VelocityTrackerScroller 使滑动产生惯性
    3. VelocityTracker 收集手指滑动路径的坐标用作路程,传入时间,计算出速度。
    4. Scroller 滑动辅助类,并不实现View滚动。它的作用好像属性动画,计算一段时间内数字变化, 比如:一秒内从0增长到100。 开发者监听数字变化从而实现动画
  4. 惯性滑动实现
    1. 重写onTouchEvent() 调用VelocityTracker.addMovement(event) 收集手势滑动信息
    2. 在up事件,VelocityTracker.computeCurrentVelocity(1000) 计算一秒内滑动距离产生的速度
    3. 速度计算结果 ,手指左滑 速度正数 ,手指右滑 速度负数。
    4. 速度正数使坐标增加 ,负数使坐标减少。这里会引发一个问题
    5. 调用Scroller.fling()
      1. fling 参数解析
      2. startX:开始位置
      3. minX-maxX:区间 ,根据速度计算x值 的范围在 minX maxX之间
      4. velocityX 速度的影响
        1. 比如:手指右滑
        2. 期望效果 x轴正方向移动 值增加
        3. 实际效果 速度负数 Scroller.fling动画结果 x轴负方向移动 值减少
        4. 期望效果与实际效果正好相反 所以速度取相反数 效果正好
      5. fling总结
        1. startX开始位置 如 :100
        2. 受速度影响 计算结果 会从100开始增加或减少。
        3. 但不是无限增加或减少,计算结果的边界在 minX最小值,maxX最大值 之间
    6. 调用 invalidate() 触发view重绘,
    7. 重写computeScroll() ,获取Scroller动画结果 ,调用scrollTo() 实现内容滚动

滑动边界

滑动边界与view的大小是两个概念

view的内容绘制在canvas上,canvas是一块无限大的画布,View有坐标系,左上角是原点(0,0),惨van无限大,坐标系也是无限大的。

View的宽高则是在无限大的canvas从原点开始圈出一块位置展示内容。

如下图,用户的可视范围只是100*100,但无限大的canvas仍然存在。假设在(200,200)的位置画了一个点,虽然用户看不见,但是它仍然存在。

上一节使用scrollBy()scrollTo() 实现内容的滑动

其内部原理是修改View的两个属性mScrollX,mScrollYmScrollX,mScrollY 表示内容在X轴Y轴的滚动距离,也可以说是确定View的展示的原点。

举例说明:

  1. 自定义View,宽高都是100
  2. 两点坐标确定一个矩形,默认原点(0,0) 由于宽高100,另一点坐标(100,100)。View展示canvas (0,0),(100,100)两点坐标圈出的部分
  3. 沿X轴移动距离100后,原点坐标(100,0),另一点坐标(200,100)。View展示canvas (100,0),(200,100)两点坐标圈出的部分

所以想要实现View内容滑动的边界,就要限制X轴坐标的取值范围,也就是mScrollX 属性的范围,从0到X。

那么如何计算滑动范围呢?

滑动范围 = 大刻度数_大刻度宽 + 小刻度数_小刻度宽 + 间隔数*间隔宽

基准线居中

其实这个东西吧 属于会了不难,难了不会,经验问题,不知道的可能想半天也没想出来。

先说结论:基准线x轴坐标 = view宽度/2 + mScrollX 就能达到滚动时居中效果。

分析

  1. 假设View的宽高都为100
  2. 画一条长度为10的X轴居中的线段,坐标点(50,10)
  3. 这条线段只是看起来居中,在view的可视范围(0,0),(100,100)内居中,
  4. 它并不是画在View上,而是画在canvas,view只是圈出一个范围
  5. 当内容水平滑动,x值不断改变,线段的坐标也要随着滑动不断变化,才能维持居中的效果
  6. 代表水平滑动距离的变量是mScrollX 线段坐标点为 (mScrollX +50,10)

智能定位

业务描述

当滑动到两个刻度之间,四舍五入自动定位到最近的那个刻度,比如:滑动到11.6,分度值是1,左右两个刻度分别是11,12。四舍五入滑动到12。

应用场景

  1. 惯性滑动后需要智能定位
  2. up手势之后,如果速度过小,无法出发惯性滑动,则需要智能定位

实现过程

这块挺复杂的,没办法详细说 很容易乱,我的思路不一定是最好的,当作参考

  1. 核心思路是利用等比例换算。
  2. 预先知道总滑动距离,知道当前滑动值,能够计算出滑动比例。
  3. 滑动比例 == 数值比例,通过比例计算出当前的测量值
  4. 根据分度值单位四舍五入,求出定位值,计算出定位值的X轴坐标
  5. mScrollX -定位值的X轴坐标 = 滑动距离。求出滑动距离后利用 Scroller.startScroll() 进行滑动

只绘制可视区域内容

之前几点完成之后就算是可以正常使用的组件了,原本是不打算做可视区域绘制的(懒)

但是在调试的时候发现绘制内容过多会很卡,不流畅z

比如:度量范围1~100,分度值是1,需要绘制100个刻度。分度值0.1,需要绘制1k个刻度,分度值0.01,需要绘制1w个刻度,卡顿非常明显了,简直不能用。

计算可视区域非常简单。view的可见区域 = x轴坐标范围 = 滚动距离 + view的宽度

x坐标在范围内视为可见,不在范围内视为不可见

private fun isVisibleArea(x: Int): Boolean 
    //view的可见区域 = x轴坐标范围 = 滚动距离 + view的宽度
    val offset = 20 //偏移量
    val start =scrollX-offset
    val end =scrollX+measuredWidth+ offset
    return x in start..end


override fun onDraw(canvas: Canvas) 
        super.onDraw(canvas)
			//简化代码
     if (isVisibleArea(x))
          drawLine(i, canvas)
          drawText(i, canvas)
       
 

文末

要想成为架构师,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。

相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

一、架构师筑基必备技能

1、深入理解Java泛型
2、注解深入浅出
3、并发编程
4、数据传输与序列化
5、Java虚拟机原理
6、高效IO
……

二、Android百大框架源码解析

1.Retrofit 2.0源码解析
2.Okhttp3源码解析
3.ButterKnife源码解析
4.MPAndroidChart 源码解析
5.Glide源码解析
6.Leakcanary 源码解析
7.Universal-lmage-Loader源码解析
8.EventBus 3.0源码解析
9.zxing源码分析
10.Picasso源码解析
11.LottieAndroid使用详解及源码解析
12.Fresco 源码分析——图片加载流程

三、Android性能优化实战解析

  • 腾讯Bugly:对字符串匹配算法的一点理解
  • 爱奇艺:安卓APP崩溃捕获方案——xCrash
  • 字节跳动:深入理解Gradle框架之一:Plugin, Extension, buildSrc
  • 百度APP技术:Android H5首屏优化实践
  • 支付宝客户端架构解析:Android 客户端启动速度优化之「垃圾回收」
  • 携程:从智行 Android 项目看组件化架构实践
  • 网易新闻构建优化:如何让你的构建速度“势如闪电”?

四、高级kotlin强化实战

1、Kotlin入门教程
2、Kotlin 实战避坑指南
3、项目实战《Kotlin Jetpack 实战》

  • 从一个膜拜大神的 Demo 开始

  • Kotlin 写 Gradle 脚本是一种什么体验?

  • Kotlin 编程的三重境界

  • Kotlin 高阶函数

  • Kotlin 泛型

  • Kotlin 扩展

  • Kotlin 委托

  • 协程“不为人知”的调试技巧

  • 图解协程:suspend

五、Android高级UI开源框架进阶解密

1.SmartRefreshLayout的使用
2.Android之PullToRefresh控件源码解析
3.Android-PullToRefresh下拉刷新库基本用法
4.LoadSir-高效易用的加载反馈页管理框架
5.Android通用LoadingView加载框架详解
6.MPAndroidChart实现LineChart(折线图)
7.hellocharts-android使用指南
8.SmartTable使用指南
9.开源项目android-uitableview介绍
10.ExcelPanel 使用指南
11.Android开源项目SlidingMenu深切解析
12.MaterialDrawer使用指南

六、NDK模块开发

1、NDK 模块开发
2、JNI 模块
3、Native 开发工具
4、Linux 编程
5、底层图片处理
6、音视频开发
7、机器学习

七、Flutter技术进阶

1、Flutter跨平台开发概述
2、Windows中Flutter开发环境搭建
3、编写你的第一个Flutter APP
4、Flutter开发环境搭建和调试
5、Dart语法篇之基础语法(一)
6、Dart语法篇之集合的使用与源码解析(二)
7、Dart语法篇之集合操作符函数与源码分析(三)

八、微信小程序开发

1、小程序概述及入门
2、小程序UI开发
3、API操作
4、购物商场项目实战……

全套视频资料:

一、面试合集

二、源码解析合集


三、开源框架合集


欢迎大家一键三连支持,若需要文中资料,直接点击文末CSDN官方认证微信卡片免费领取【保证100%免费】↓↓↓

以上是关于Android UI-薄荷健康尺子的主要内容,如果未能解决你的问题,请参考以下文章

自定义控件 ——可拖动测量尺子

Android自定义尺子控件(选择身高体重等)

Android自定义尺子控件(选择身高体重等)

自定义控件 ——可拖动测量尺子

自定义控件 ——可拖动测量尺子

屏幕尺子(电脑尺子) 1.0 免费绿色版