title: 自定义形状波浪进度
date: 2017-7-24 12:41:59
tags:
- Android
category: Android
今天碰到个需求,要求以波浪进度填充自定义透明形状,废话不多说,直接上最终效果图
![20170724_wave_progress.gif](https://img.haomeiwen.com/i6854811/fbb0871f9b9229df.gif?imageMogr2/auto-orient/strip
思路
通过判断Bitmap
对象的像素颜色,对非透明像素进行颜色更改。波浪曲线采用sin曲线π到2π区间段,和将时间取余并和x坐标相加得到波浪y轴坐标,再加上百分比*Bitmap高度。核心算法如下:
![](https://img.haomeiwen.com/i6854811/12a9c877531c2609.png)
private int getWaveY(int x) {
double sinX = Math.PI + (((((System.currentTimeMillis() / (1000 / waveSpeed)) + x) % waveLength)) / (double) waveLength * Math.PI);
int waveHeight = (int) (waveHeightMax * (Math.sin(sinX) + 1));
int y = (int) ((100 - progress) / 100f * bitmap.getHeight());
y -= waveHeight;
return y;
}
这里的waveSpeed
、waveLength
、waveHeightMax
均定义成全局变量,可以很方便的定制波浪移动速度、波浪长度、波浪高度。
使用SurfaceView
为了达到比较好的性能,使用SurfaceView
在子线程绘图。
性能优化
因为这里涉及逐个像素操作,所以遍历的运算量很大,一定要对遍历的量进行控制,否则会很卡。
我这里采用控制图片大小的方式
***
bitmap = setBitmapSize(bitmap, calculateSize * bitmap.getWidth() / bitmap.getHeight(), calculateSize);
***
/**
* 缩放图片
*
* @param bitmap 原图片
* @param newWidth
* @param newHeight
* @return
*/
private Bitmap setBitmapSize(Bitmap bitmap, int newWidth, int newHeight) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
float scaleWidth = (newWidth * 1.0f) / width;
float scaleHeight = (newHeight * 1.0f) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
}
通过calculateSize
控制循环次数在有限的范围内,并在最终绘制Bitmap时使用区域绘制函数:
private void draw() {
Canvas canvas = mHolder.lockCanvas();
canvas.drawBitmap(bitmap, rectBitmap, rectCanvas, mPaint);
mHolder.unlockCanvasAndPost(canvas);
}
注意事项
- 为了达到
SurfaceView
透明效果,需要加入以下两句代码
setZOrderOnTop(true);
mHolder.setFormat(TRANSLUCENT);
- 从
Drawable
中得到的Bitmap
不能直接setPixel()
,必须重新Bitmap.createBitmap()
,或Bitmap.copy()
,使得isMutable
属性为true
,得到新的Bitmap
对象才能操作像素,否则会报IllegalStateException
网友评论