WaveView
前言
之前公司要做一个标题栏的波浪效果,时间比较赶,就随便在网上找了个波浪控件 Demo。但是后来在该页面加了其他动画一起播放后,发现性能很差,掉帧很严重。仔细读了源码才发现,是用了一种很简单粗暴的方式实现正弦曲线的,有点微积分的概念,在竖直方向画了 n 条,n 为屏幕宽度。假设手机是 1080p 分辨率,一帧画面就调用了 drawLine() 方法 1080 次,几十毫秒就要刷新一次,一秒钟就要绘制几万次,性能肯定很差。然而搜了很多博客和 GitHub 开源的波浪控件,基本都是用这种方式实现,让我有点惊讶。
由于性能上不满足需求,就只能用另外的办法了。查了下发现可以用贝塞尔曲线来做,试了下性能还可以,和其他动画一起播放也不会掉帧了。在研究贝塞尔曲线后,萌生了一个优化上述实现三角函数曲线的想法,改用绘制路径的方式实现,这样一帧画面只需调一次 drawPath() 绘制一次,应该会比一帧画面绘制 n 条直线更好。试了果真也不掉帧了。
想了下还是开源个控件方便后人,不然可能像我那样走了弯路,网上很多例子都是比较旧的,性能较差。在元旦假期花时间封装了下,加入了大量的可配置参数,还是花了不少时间计算测试。保留贝塞尔曲线和三角函数曲线两种实现方式,我个人测试三角函数曲线绘制的性能比贝塞尔曲线的好一点点,不过贝塞尔曲线的线条更自然好看,所以两个方式都保留了,大家可以自己试下。应该能满足大部分的需求,有其他相关需求可以评论和我说,可以的话尽量满足。
简介
少啰嗦,看东西
WaveView 是一个可以高度自定义的波浪控件,能绘制出自己想要的曲线波浪
- 支持设置一个或两个波浪
- 支持分别设置波浪的颜色、振幅、波长、水位线高度、初始偏移量
- 支持分别设置移动一个波长的时间,支持开启和暂停动画
- 支持设置移动方向(左、右)
- 支持设置波浪位置(顶部、底部)
- 支持两种绘制方式(贝塞尔曲线和三角函数曲线)
用法
GitHub:https://github.com/CaiShenglang/WaveView
在 project 的 build.gradle 添加以下代码
allprojects {
repositories {
...
maven { url 'https://www.jitpack.io' }
}
}
在 app 的 build.gradle 添加依赖
dependencies {
implementation 'com.github.CaiShenglang:WaveView:1.0.3'
}
在 xml 添加 WaveView
<com.caisl.waveview.WaveView
android:id="@+id/wave_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cycleDuration="4000"
app:cycleDuration2="5000"
app:drawMode="bezier"
app:moveDirection="left"
app:startAnim="false"
app:waterLevelHeight="150dp"
app:waveAmplitude="10dp"
app:waveAmplitude2="8dp"
app:waveColor="#88afb8ff"
app:waveColor2="#e2c8ff"
app:waveLength="300dp"
app:waveLengthPercent2="0.8"
app:waveDefOffset="20dp"
app:waveDefOffsetPercent2="0.3"
app:waveCount="2"
app:waveLocation="top" />
自定义属性说明
自定义属性 | 类型 | 作用 |
---|---|---|
startAnim | boolean | 是否开启动画,默认开启 |
waveCount | integer | 波浪数量,默认显示一个 |
waterLevelHeight | dimension | 水位高度,默认是控件高度 - 最大振幅 |
waveColor | color | 第一个波浪的颜色 |
waveColor2 | color | 第二个波浪的颜色 |
waveAmplitude | dimension | 第一个波浪的振幅 |
waveAmplitude2 | dimension | 第二个波浪的振幅 |
waveLength | dimension | 第一个波浪的波长,默认是控件宽度 |
waveLength2 | dimension | 第二个波浪的波长,默认是控件宽度 |
waveLengthPercent | float | 第一个波浪占控件宽度的百分比 |
waveLengthPercent2 | float | 第二个波浪占控件宽度的百分比 |
waveDefOffset | dimension | 第一个波浪的初始偏移量 |
waveDefOffset2 | dimension | 第二个波浪的初始偏移量 |
waveDefOffsetPercent | float | 第一个波浪默认偏移量占波长的百分比 |
waveDefOffsetPercent2 | float | 第二个波浪默认偏移量占第二个波长的百分比 |
cycleDuration | integer | 第一个波浪移动一个周期的时长 |
cycleDuration2 | integer | 第二个波浪移动一个周期的时长 |
moveDirection | left、right | 移动方向,默认向右(向左、向右) |
waveLocation | top、bottom | 波浪位置,默认在底部(顶部、底部) |
drawMode | bezier、sin、cos | 绘制的模式,默认是贝塞尔曲线绘制(贝塞尔曲线、正弦曲线、余弦曲线) |
如果需要动态设置开始或停止动画
mWaveView = findViewById(R.id.wave_view);
mWaveView.startAnim(); // 开始或继续动画
mWaveView.stopAnim(); // 暂停动画