实现一个清新美观的加载按钮

今日科技快讯

近日,文化部部署北京、上海、广东、浙江等地文化市场综合执法机构,对50家主要网络表演经营单位进行集中执法检查,虎牙直播、YY直播、龙珠直播、火猫直播、秒拍等30家内容违规的网络表演平台被依法查处。同时关停了“悟空TV”等11家手机表演平台。

作者简介

不知不觉又到周五,有了本公众号的陪伴,是不是感觉时间过得很快呢?提前祝大家周末愉快。

本篇是 frank909 的第六篇投稿了!今天他给大家细致地分析了自己的一个自定义View,思路很不错,希望大家喜欢。

frank909 的博客地址:

http://blog.csdn.net/briblue

前言

在 Dribble 上偶然看到了一组交互如下:

当时在心里问自己能不能做,答案肯定是能做的,不过我比较懒,觉得中间那个伸缩变化要编写很多代码,所以懒得理。后来,为了不让自己那么浮躁,也为了锻炼自己的耐心程度,还是坚持实现它了。这个过程,觉得自己还是有所收获,把握了一些想当然的细节,输理了对于自定义 View 的流程。

我将这个自定义 View,起了一个名字叫做 LoadButton。

这篇文章涉及到的知识点有如下:

1. 自定义 View 时的基本流程,包含 attrs.xml 中属性的编写,构造方法中属性的获取,onMeasure() 中尺寸的测量。onDraw() 中界面的实现。
2. 可以让 Android 初学者再次感受一次回调机制的美妙。
3. 属性动画的基本使用。

先确定尺寸

先观察 LoadView 的形态。

上面的显示的是两种形状,一个是圆角矩形,另外一个就是圆。两个形态尺寸区别是,高相同,宽度不一致。

我们再进一步分析形态 1。 

形态 1 可以看成是左右两个半圆和中间一个矩形。再回顾下示例图片中的动画表现。 

圆角矩形最终变成了一个圆。我们可以用线框图来渐进表现它。

当进行动画时,中间的矩形部分不停地缩小,当它缩小为 0 时,形态 1 就转变成了形态2。

上面的能够说明什么呢?说明 LoadButton 由 3 个部分组成,左右的半圆和中间的矩形,即使是 形态2 也可以看做是左右半圆和中间宽度为 0 的矩形组成。 

细化尺寸

我们进一步讨论尺寸相关的情况。

我们知道对于普通开发者而言,自定义一个 View 测量尺寸的时候我们通常要关注的测量模式是 MeasureSpec.EXACTLY 和 MeasureSpec.AT_MOST 两种。要了解更多详细的信息可以阅读我写的这篇博:

长谈:关于 View Measure 测量机制,让我一次把话说完

http://blog.csdn.net/briblue/article/details/72190143

接下来,我们详细讨论一下这两种情况。

  • MeasureSpec.EXACTLY

当一个 View 的 layout_width 或者 layout_height 的取值为 match_parent 或 30dp 这样具体的数值时,这就表明它的测量模式是 MeasureSpec.EXACTLY。它已经获得了精确的数值了,按照常理我们是不应该再去干涉它,parent 给出的建议尺寸是什么,我们就把尺寸设置成什么,但是结合开发的实际情况来看,我们有一个底线,为了保证 LoadView 的完整性,也就是再差的情况下,parent 给出来的建议尺寸也不能小于 形态2。否则如下图情况就不是我们想要的了

  • MeasureSpec.AT_MOST

当一个 View 的 layout_width 或者 layout_height 的取值为 wrap_content 时,它的测量模式就是 MeasureSpec.AT_MOST,这个时候我们需要自己根据内容计算尺寸。而 LoadButton 的内容是什么呢?它的内容有 text 还有 加载成功或者加载失败的图片。因为图片大小在 形态2 中的圆形内可以确认。所以问题的关键就在于 LoadButton 文字内容宽高的尺寸测量。

text 内容自然是居中显示,然后它距离中间的 rect 上下左右间距也要考虑。这个时候的 rect 尺寸就是相对应的文字尺寸加上相对应方向上的 padding 值,这些 padding 值通过在 attrs.xml 中自定义属性然后在布局文件中赋予。

最后整体 LoadButton 尺寸自然是中间 rect 加上左右两个半圆的半径,但是这还不是最终的尺寸,最终的尺寸还是要和 parent 给的建议尺寸比较,不能大于它。

上面分析了尺寸测量相关,所以顺着思路进行的话,编码也只是水到渠成的事情了。

绘制

测量是在 onMeasure() 方法中进行,而绘制就是在 onDraw() 方法中进行的,这是 Android 开发者都知道的事情。所以这一节的重点在于 onDraw() 这个方法。

为了不给读者造成困扰,我先张贴自定的属性,及在构造方法中获取属性值的代码。其它的细节应该看名字就大概知道了。attrs.xml:

然后在 LoadButton 的构造方法中获取这些值。

形态1的绘制,借助于Path的力量

android 绘制图形离不开 Canvas,Canvas 可以直接绘制 直线、矩形、圆、椭圆,但是 LoadButton 的 形态1 怎么绘制呢?它是一个不规则的闭合图形,直接用 Canvas 的话肯定不行,所以得借助另外一个类 Path,Path 中文译做路径,可以专门处理这种情况,而且可以处理比这复杂的情况,具体情况请读者们自己查阅相应资料与教程。

我们再来观察 形态1 到 形态2 的转变过程。 

这是个中间矩形从初始值变为 0 的过程,我们用 rectWidth 表示这个矩形的宽度值,因为在 onDraw() 方法中,LoadButton 尺寸确定,所以我们很容易得到它的中心点,所以我们可以中心点坐标为参考坐标,然后以 rectWidth 为变量创建一个 path,这个 path 实现了 LoadButton 的轮廓。

以 rectWidth 为变量建立 path 的好处时,当从 形态1 到 形态2 转变的过程,肯定是 rectWidth 数值变化的过程,而对于其它数值是不变的,所以重绘的时候 LoadButton 能够很轻松地处理这种情况。

我们到这一步的时候已经能够准确地绘制了 LoadButton 的轮廓。现在需要精确地绘制它的内容,只有这样才是完整的 LoadButton。

我们先需要给 LoadButton 定义一些状态。

LoadButton的状态

它们的状态转换如下: 

LoadButton 的状态转换由用户点击按钮触发。所以 LoadButton 需要在内部设置一个 OnClickListenner。

1. 当在 Initial 状态下点击时,它会转换到 Folding 状态下。

2. Foding 状态结束后,由 形态 1 转变成形态 2。自然就进入了 Loading 状态。 

3. Loading 状态有 3 个走向,加载成功后,用户通过相应 API 设置状态为 Successed。加载失败后,用户可以设置状态为 Error。如果在 Loading 状态下点击按钮,会进入 Paused 状态。

4. 在 Paused 状态下点击按钮,LoadButton 重新进入 Loading 状态。

5. 在 Successed 或者 Error 状态下点击按钮,将通过回调对象,通知调用者点击事件的发生。

我们在 LoadButton 的构造方法中设置这样的内部的 OnClickListenner。

状态的绘制

Initial 状态下其实就是中间一个 text 文本居中显示,相关代码如下:

Folding 状态其实就是不显示文字的 Inital 状态,不同的还有它的 rectwidth 每次重绘时会变小,最终会由 Initial 的 形态1 过渡到 Loading 状态下的 形态2。在 Initial 状态下点击按钮会调用一个动画,这个动画用于展示 形态1 到 形态2 的过程。

这里是一个典型的属性动画应用场景,通过不断改变属性 rectWidth 的值来进行重绘,而对于绘制这一方面,文章前面部分有说过 LoadButton 通过以中心坐标为参考,以 mRectWidth 为变量建立了一个 Path 来绘制轮廓。

另外,大家可以注意到,shrinkAnim 有一个监听器,我设置为了 LoadButton 本身。

在收缩动画结束的时候,我调用了 load() 方法用来将状态设置为 Loading,并进行加载动画。

我们先看看 Loading 状态下的绘制,它是 形态2 ,也就是在一个圆形内有一个正在加载无限循环的动画。思路也很简单,用进度条的背景色画一个圆圈,然后用进度条的前景色绘制相应角度的弧,并且这个弧的半径和进度条的半径一样。

上面有两个关键的变量 progressReverse 和 circleSweep。progressReverse 用来表示动画是否需要翻转,circleSweep 表示每次绘制的时候从起始角度扫描的角度。

正常情况下,起始角度是 270 度不变,如果动画翻转时,它是 270 + circleSweep 的值,具体为什么这样做,大家可以观看之前的图像来思考一下。

加载的动画自然也是属性动画控制的,这个动画让 circleSweep 从 0 到 360 之间不停地变化。并且在每次循环的时候,将 progressReverse 变量置反。

Paused 状态是当 LoadButton 在 Loading 状态下,用户点击了按钮,这个时候按钮会显示一个暂停图标。

至于显示方面,非常简单就是给一个 drawable 设置好 bound 范围然后显示。稍后我会给出代码。

Successed 状态和 Error 状态实现过程基本上是一致的。但是它们被点击的时候,需要通知点击者。所以我们需要定义一个回调接口。

LoadListenner.onClick() 方法中的参数,isSuccessed 为真告诉点击者加载成功了的信息。否则提示加载失败。needLoading() 方法用来告诉点击者当在 Paused 状态下点击按钮时,调用者应该重新加载了。

它们的显示代码如下:

另外,需要注意的是 Successed 和 Error 状态,需要开发者根据实际情况决定调用。

将 LoadButton 重置为 Initial 状态用 reset() 方法。

到此,整个 LoadButton 实现逻辑已经完成。接下来我们可以编写代码测试。

测试

我们添加一个 LoadButton 到布局文件,然后用 3 个 Button 来测试它成功、失败、重置的情况。

测试结果:

总结

本文的主题并不难,但是如果要实现它也需要细心。关键是编码的时候,要先设计分析,之后就是一气呵成、水到渠成的事情了。

通过演练这个项目,我觉得自己还是有些收获。

  • 复习了自定义 View 的基本流程。特别是对 onMeasure() 这一块有更深的理解。

  • 复习了属性动画的使用。

  • 复习了 Canvas 和 Path 的基本用法。

  • 演练了状态模式下的编程。

  • 享受回调机制带来的美妙感受。

如果有人认为好用,我想把它上传到 jcenter 仓库,目的也是为了演练怎么上传 Android 模块到开源库。喜欢这篇文章就给我一个赞吧,需要你们的鼓励。哈哈。

项目地址:

https://github.com/frank909zhao/LoadButton

更多

每天学习累了,看些搞笑的段子放松一下吧。关注最具娱乐精神的公众号,每天都有好心情。

如果你有好的技术文章想和大家分享,欢迎向我的公众号投稿,投稿具体细节请在公众号主页点击“投稿”菜单查看。

欢迎长按下图 -> 识别图中二维码或者扫一扫关注我的公众号:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 当然可以!你可以使用Java编写一个样式美观的计算器app。您可以使用Java图形用户界面(GUI)库(如Swing、JavaFX等)来实现用户界面,并使用Java中的基本计算功能(如加减乘除等)实现计算器的功能。您还可以添加其他功能(例如百分比计算、正负数切换等)来提高计算器的实用性。祝您编写成功! ### 回答2: 要实现一个样式美观的计算器app,需要运用Java的图形界面编程技术。 首先,你可以使用Java Swing或JavaFX等GUI库来设计和创建计算器的用户界面。这些库提供了丰富的组件和布局管理器,可以帮助你创建各种图形元素,例如按钮、标签、文本框等。你可以利用这些组件来设计漂亮的界面,并根据需要自定义它们的样式和布局。 其次,你需要实现计算器的逻辑功能。通过编写Java代码,可以处理用户的输入和计算逻辑。你可以使用Java的数学类库来执行各种数学运算,例如加减乘除、求平方根等。通过合理的算法设计和编程技巧,确保计算逻辑的准确性和高效性。 另外,为了增强用户体验,你可以添加一些动画效果和交互功能。例如,当用户点击按钮时,可以添加按钮按下的动画效果;你还可以提供键盘输入支持,让用户可以通过键盘输入进行计算。 最后,为了确保计算器的功能稳定和易于维护,建议进行测试和调试。你可以编写单元测试用例,覆盖各种情况,确保计算器在各种输入条件下都能正确运行。同时,对代码进行调试,修复可能存在的bug,并进行代码优化,提高计算器的性能和稳定性。 总之,通过运用Java的图形界面编程技术,设计漂亮的用户界面,实现正确高效的计算逻辑,并增强用户体验,你可以成功地实现一个样式美观的计算器app。 ### 回答3: 要实现一个样式美观的计算器app,可以利用Java编程语言来完成。首先,在设计界面方面,可以使用Java的图形用户界面(GUI)库,如Swing或JavaFX。这些库提供了丰富的组件和布局管理器,可以帮助我们创建漂亮的界面。 在设计方面,可以采用现代风格的按钮、输入框和显示屏等元素,并使用合适的颜色和字体来搭配。可以使用布局管理器来确定组件的位置和大小,以确保界面的美观性和响应性。 在实现计算功能方面,可以利用Java提供的数学库和字符串处理功能。可以使用函数和操作符来处理各种数学运算,例如加法、减法、乘法和除法等。在接收用户输入时,可以使用文本框或按钮来获取用户的操作,并将计算结果显示在显示屏上。 为了提高app的用户体验,可以添加一些额外功能,例如撤销、清空输入和保存历史记录等。此外,还可以实现一些高级功能,如科学计算和单位转换等。 在构建完成后,应该进行测试和调试以确保app的功能正常运行。可以检查计算结果是否准确,并确保界面的响应性和美观性。 总的来说,使用Java编程语言,结合GUI库和相关功能来实现一个样式美观的计算器app是可行的。通过合理的设计和实现,可以创建一个功能强大且界面美观的计算器app,提供良好的用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值