Android自定义电量控件中过度绘制与思考
2017-10-13 14:06
405 查看
一、概述
最近在优化公司应用时,发现几年前写的自定义电量空间存在严重的过度绘制。虽然很小一个控件影响不了太大,但本着责(强)任(迫)心(症) 还是毅然决然做个优化,同时也针对过度绘制做一点总结思考。过度绘制参考文章:
http://blog.csdn.net/lmj623565791/article/details/45556391;
自定义电量控件 下载地址
二、效果图
大家能区分下图中1和2、3和4之间的区别吗(颜色差别忽略不考虑)?其实差别不大,尤其是在小图模式下,几乎没有差别。
再来看一张图:
这里想必大家能够清楚看到区别了,这是手机开了过度绘制调试的结果,很明显可以看到,1和3 的电池存在明显的过度绘制,尤其是电池内部电量部分,甚至开始变红,说明该区域一次被绘制了4次,性能非常茶差。
接下来 我们通过源码分析,具体代码可以 在这里下载 下载地址
以下是1和3的源码(不推荐,只贴了关键onDraw的代码):
// 这是 1和3 的代码,过度绘制不采取 @Override protected void onDraw(Canvas canvas) { int width = getMeasuredWidth(); int height = getMeasuredHeight(); int bodyWidth = width - border; int powerWidth = width - border * 5; int powerHeight = height - border * 4; // 这里是画底部圆角矩形 RectF ovalf = new RectF(0, 0, bodyWidth, height);// 设置个新的长方形 mPaint.setColor(mainColor); mPaint.setAntiAlias(true);// 设置画笔的锯齿效果 mPaint.setStyle(Paint.Style.FILL); canvas.drawRoundRect(ovalf, radio, radio, mPaint);//第二个参数是x半径,第三个参数是y半径 // 这里是画第二层圆角矩形-作为电池内空白区域颜色填充 RectF ovalf2 = new RectF(border, border, bodyWidth - border, height - border);// 设置个新的长方形 mPaint.setColor(bgColor); float radioIn = radio - 2f; if (radioIn < 0) { radioIn = 0; } canvas.drawRoundRect(ovalf2, radioIn, radioIn, mPaint);//第二个参数是x半径,第三个参数是y半径 mPaint.setColor(mainColor); // 这里开始话电池剩余电量层 根据百分比显示不同宽度 RectF rightRect = new RectF(bodyWidth, height * 1 / 3, width, height * 2 / 3);// 设置个新的长方形 canvas.drawRect(rightRect, mPaint); if (power < 0) { power = 0; } else if (power > 1) { power = 1; } RectF powerRect = new RectF(border + border, border + border, border + border + powerWidth * power, border + border + powerHeight);// 设置个新的长方形 canvas.drawRect(powerRect, mPaint); super.onDraw(canvas); }
以上实现方式是通过多个图层多次覆盖 达到最后电池样式的效果,方便易懂,但带来的负面影响是巨大的,过度绘制导致该控件在复杂的页面上呈现时,会导致延迟加载等问题,带来较差的体验和性能的开销。
接下来我们来讲讲一种较优的实现方式。先上代码:
@Override protected void onDraw(Canvas canvas) { int width = getMeasuredWidth(); int height = getMeasuredHeight(); mPaint.setColor(mainColor); // ====这里开始画电池边框,中间镂空不填充===== mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(border); mPaint.setAntiAlias(true); int bodyWidth = width - border; // 电量主体部分的宽度,不包括正极标志矩形部分,正极矩形宽度为border,高度为height/3 int bodyHeight = height; // 电量主体部分的高度 RectF ovalf = new RectF(border/2, border/2, bodyWidth - border/2, bodyHeight - border/2);// 设置个新的长方形,边框以线中间为基准计算 canvas.drawRoundRect(ovalf, radio, radio, mPaint);//第二个参数是x半径,第三个参数是y半径 // ====这里画正极图标===== mPaint.setStyle(Paint.Style.FILL); mPaint.setStrokeWidth(0); mPaint.setAntiAlias(true);// 设置画笔的锯齿效果 RectF rightRect = new RectF(bodyWidth, height * 1 / 3, width, height * 2 / 3);// 设置个新的长方形 canvas.drawRect(rightRect, mPaint); // ====画电量百分比===== int powerWidth = bodyWidth - border * 4; // 显示电量百分比部分宽度 int powerHeight = bodyHeight - border * 4; // 显示电量百分比部分高度 RectF powerRect = new RectF(border * 2, border * 2, border*2 + powerWidth * power, border * 2 + powerHeight);// 设置个新的长方形 canvas.drawRect(powerRect, mPaint); super.onDraw(canvas); }
整体思路就是不重叠。我们不在同一块区域多次绘制,就不会出现过度绘制的情况。同时底色使用透明镂空的方式也可以和其他控件融为一体。
代码很简单,其实就是想说,我们在自定义控件的时候也要考虑多个因素,采取一种最优雅的解决方案。
最后再附上一遍自定义电量控件下载地址相关文章推荐
- Android使用GridLayout绘制自定义日历控件
- Android 自定义UI控件一.View的基本绘制
- android绘制自定义view时,控件大小的测量与确定问题
- Android圆环形自定义进度条控件的绘制
- Android自定义控件之——文字圆形边框(将文字绘制在圆中间)
- Android 自定义View过度绘制性能优化<7>
- Android自定义控件之——文字圆形边框(将文字绘制在圆中间)
- Android自定义控件之——文字圆形边框(将文字绘制在圆中间)
- android绘制自定义view时,控件大小的测量与确定问题,代码演示
- (总结篇)Android 牛不牛?决定于自定义View控件(一)——view绘制流程(onMeasure,onLayout,onDraw)
- Android自定义组合控件以及使用方法_1
- Android性能优化课程:过度绘制
- Android 过度绘制简单的分析
- android自定义View创建一个Path绘制多边形,贝塞尔曲线,
- Android自定义view动态绘制百分比圆环进度条
- 自定义android用户控件,使用回调函数实现自定义事件
- android之视频播放系统VideoView和自定义VideoView控件的应用
- Android绘图系列(二)——自定义View绘制基本图形
- android自定义控件之滚动广告条