之前整理过一些属性动画的基本操作,这一段时间的动画相关需求都安然度过了。直到这次……

一、另一种动画需求

多数交互中的动画都是让单个页面元素动起来,这种就很适合用属性动画实现。但是对于 多个元素、非页面内元素 的动画需求,就不方便用View+属性动画实现了。

举个例子,也就是这次做的:

波纹效果需要同时绘制 多个 同心圆,而且这些圆 不是页面内的元素,未触发之前不需要显示。如果用属性动画实现,至少需要在xml布局文件中添加多个ImageView画圆,效率低还不易复用。

二、WaveView分析

使用自定义View绘制动画的主要思路是这样的:

分解动画成帧,考虑如何在onDraw中绘制每一帧

提取出绘制所需参数,分为随时间变化和不可变两种,不可变参数可以暴露出去(setter方法/attribute设置)

总结随时间变化的参数变化规律,实现时间轴

按需求提供出播放,暂停,停止,重置等等方法

按照这个思路,一步步实现一下WaveView吧。

第一步:

在onDraw中画圆需要用到canvas.drawCircle方法,四个参数:圆心x、y坐标,半径和Paint。WaveView绘制的每一帧都是圆,区别是圆的半径,数量,透明度。还需要设置圆的最小半径和最大半径,以及扩散的时候两个圆的半径差。

每次绘制只需要把所有的圆画出来:

第二步:

扩散过程中随时间变化的参数只有半径和透明度。圆的数量,最小最大半径和半径差则是不可变参数。所有的都加了默认值,防止

第三步:

最艰难的一步,时间轴。我们需要一个定时触发的机制去改变mWaveList中的每一个值,还要同时修改paint的alpha值。这个变量嘛,还是越少越方便,波纹的效果是半径越大alpha越小,只要控制半径变化就可以计算出alpha。然后便是循环的问题,当波纹半径大于最大半径波纹就会消失,此时便可循环使用,再从最小半径扩散一次。

我这里的时间轴用了CountDownTimer,应该不是一种很好的选择,只是个人习惯写起来顺手了…

第四步:

最后这个就简单了,直接控制CountDownTimer的start和cancel就可以了。

三、再完善一下?

内部功能已经实现了,还要提取参数的设置方法,方便其他地方使用呀。java中需要添加setter/getter方法,用模版代码生成就好,kotlin的话直接把需要暴露的field改为public即可。

如果需要在xml布局文件中设置默认参数,还需要添加对应的attribute,现在这样已经够用了,我就不加了?

import android.content.Context

import android.graphics.Canvas

import android.graphics.Color

import android.graphics.Paint

import android.os.CountDownTimer

import android.util.AttributeSet

import android.view.View

class WaveView@JvmOverloads constructor(

context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0

) : View(context, attrs, defStyleAttr) {

private val paint:Paint = Paint()

public var mBgColor = Color.TRANSPARENT

public var mWaveColor = Color.WHITE

public var mRadiusMin = 0f

public var mRadiusMax = 1080f

public var mWaveInterval = 240f

//用每次扩散半径增加的值作为速度参数

public var speed = 10f

private val mWaveList = ArrayList()

private val timeline = object:CountDownTimer(300000,16){

override fun onTick(millisUntilFinished: Long) {

// 每个时间间隔都把正在扩散的波纹半径增加

for (i in 0 until mWaveList.size){

mWaveList[i] = mWaveList[i] + speed

if (mWaveList[i] < mRadiusMin + mWaveInterval){

break

}

}

//最外层波纹超过最大值时,重新把它添加到波纹队列末尾

if (mWaveList[0] > mRadiusMax){

mWaveList[0] = mRadiusMin

val newList = transList(mWaveList)

mWaveList.clear()

mWaveList.addAll(newList)

}

invalidate()

}

override fun onFinish() {

//尽量保证手动调用waveStop,就不会执行到这里

reset()

}

}

init {

initWave(mWaveList)

paint.color = mWaveColor

}

override fun onDraw(canvas: Canvas?) {

super.onDraw(canvas)

canvas!!.drawColor(mBgColor)

val centerX = canvas.width.div(2).toFloat()

val centerY = canvas.height.div(2).toFloat()

for (i in 0 until mWaveList.size){

paint.alpha = calcAlpha(mWaveList[i])

canvas.drawCircle(centerX, centerY, mWaveList[i], paint)

}

}

fun wave(){

timeline.start()

}

fun stopWave(){

timeline.cancel()

}

fun reset(){

timeline.cancel()

mWaveList.clear()

initWave(mWaveList)

}

private fun initWave(waveList: ArrayList){

val waveNum = ((mRadiusMax-mRadiusMin)/mWaveInterval).toInt() + 2

for (i in 1..waveNum){

waveList.add(mRadiusMin)

}

}

private fun transList(list: ArrayList):ArrayList{

val newList = ArrayList()

(1 until list.size).mapTo(newList) { list[it] }

newList.add(list[0])

return newList

}

// 通过半径计算透明度,趋势是半径越大越透明,直到看不见

private fun calcAlpha(r:Float):Int = ((mRadiusMax - r)/ mRadiusMax * 120).toInt()

}

复制代码

最终得到的就是这样的一个View啦,使用方法大概是这样的:

在xml中放一个WaveView

findViewById之后,set基本参数

在需要的时机执行wave()方法

四、后记

做成这样应该可以满足设计师dalao们的需求了,呼~

自定义View是一个涵盖内容很广泛的课题,除了完全实现一个可展示、可交互的控件,还能优化布局的绘制效率,实现迷之交互,以及这特别的动画效果,需要深入学习的内容还有很多呀。

近期在恶补Kotlin,打算进入实践了,所以写Demo的时候都用的Kotlin。但是目前的项目都是Java的,所以又翻译了一版Java的。完整代码见Github吧。

前往github

如有问题或是建议,欢迎留言评论。

android覆盖扩散动画,[Android]多层波纹扩散动画——自定义View绘制相关推荐

  1. android 水波纹扩散动画,[Android]多层波纹扩散动画——自定义View绘制

    之前整理过一些属性动画的基本操作,这一段时间的动画相关需求都安然度过了.直到这次-- 一.另一种动画需求 多数交互中的动画都是让单个页面元素动起来,这种就很适合用属性动画实现.但是对于 多个元素.非页 ...

  2. Android 自定义View绘制电池图标

    /*** @anthor GrainRain* @funcation 自定义View绘制电池* @date 2019/8/27*/ public class DrawBatteryView exten ...

  3. android自定义弧度按钮,Android 自定义View 绘制六边形设置按钮

    今天逛酷安的时候,发现酷安的设置按钮(截图的右上角),是一个六边形 + 中心圆的图标,所以又是一个自定义View练习对象了.画圆很简单,知道半径即可,而重点就在画出六边形. 酷安截图.png 最终效果 ...

  4. Android自定义View绘制闹钟

    Android自定义View绘制闹钟 本文简单实现了一个闹钟,扩展View,Canvas绘制 效果如下: 代码如下: package com.gaofeng.mobile.clock_demo;imp ...

  5. Android绘图机制(二)——自定义View绘制形, 圆形, 三角形, 扇形, 椭圆, 曲线,文字和图片的坐标讲解

    Android绘图机制(二)--自定义View绘制形, 圆形, 三角形, 扇形, 椭圆, 曲线,文字和图片的坐标讲解 我们要想画好一些炫酷的View,首先我们得知道怎么去画一些基础的图案,比如矩形,圆 ...

  6. css 波纹扩散_css3实现支付宝波纹扩散的功能原理

    今天讲一个比较简单的css3的特效吧. 之前在使用支付宝的时候,我偶然间发现支付宝有一个页面,有一个波纹扩散的特效,还挺有意思. 正巧这几天,我在开发小程序的时候,也遇到了这个需求,所以简单做了个de ...

  7. 【Android 仿微信通讯录 导航分组列表-下】自定义View为RecyclerView打造右侧索引导航栏IndexBar

    本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 转载请标明出处: http://blog.csdn.net/zxt0601/article/details/52420706 本文出 ...

  8. Android自定义View绘制流程

    Android视图层次结构简介 在介绍View绘制流程之前,咱们先简单介绍一下Android视图层次结构以及DecorView,因为View的绘制流程的入口和DecorView有着密切的联系. 我们平 ...

  9. android 每个块半径不同的扇形图,自定义view

    1.首先看效果图 2.自定义PieChartView,继承自View,下边为PieChartView代码 package com.yingjinbao.im.peach.customview; imp ...

最新文章

  1. 苗旺:因果推断,观察性研究和 2021 年诺贝尔经济学奖
  2. vector删除第i个元素_LeetCode每日一题 Q215数组中的第K个最大元素
  3. 又拍云张聪谈安全、HTTPS、自定义、CDN的未来趋势
  4. 使用HTML5的Canvas画布来剪裁用户头像
  5. 在函数中的局部程序(像是比局部变量还局部的部分)
  6. CSS常用单词-弹性盒(专业版)
  7. LVS负载均衡DR模式部署
  8. html创建表单用设么,如何使用HTML创建表单的发送
  9. 阿里巴巴(alibaba)系列_druid 数据库连接池_监控(一篇搞定)记录执行慢的sql语句...
  10. Bailian2931 期末考试第二题——比较数字个数【文本】
  11. c语言烟花表白程序代码,C语言实战之浪漫烟花表白程序代码
  12. 基于Python的视频解析器
  13. 蓝桥杯题库及答案python版_蓝桥杯试题库的历届真题版.doc
  14. Android 中的hook技术是什么
  15. 图像的简单copyPaste实现
  16. Marquee首尾相连不间断移动 开始完全显示
  17. jmeter 接口测试 签名_JMeter处理接口签名(sign)
  18. 问题描述:vcenter上数据存储的事件中有大量的警告,还有偶尔的报错,存储设备naa...的路径冗余已降级,路径。。已关闭,受影响的数据存储 与存储设备。。。连接丢失,路径。。已断开,受影响的存储
  19. Incapsula reese84 分析与破解
  20. 南昌人武学院计算机室,【志愿者日记】南昌大学人武学院:用行动感染身边的人...

热门文章

  1. 在WinAPI环境下获得1小时前系统时间
  2. 客户端控件调用服务器的参数
  3. Windows句柄-2
  4. C/C++ http协议发送字段,文件,单个和多张图片
  5. MFC中OnTimer函数的使用方法
  6. C语言的条件编译#if, #elif, #else, #endif、#ifdef, #ifndef
  7. C#调用C++DLL的小总结8---C++Dll中函数返回字符串指针
  8. pytorch list转tensor_PyTorch 52.PyTorch常用代码段合集
  9. linux 怎么设置静态ip,如何在Linux中设置静态IP地址和配置网络
  10. java quot;1quot;==quot;1quot;_JAVA: 为什么要使用quot;抽象类quot;? 使用quot;抽象类quot;有什么好处?...