android 通用圆角控件

红色字为总结日记--写给未来的我

圆角控件就是对 View的Canvas进行改变轮廓的处理

改变轮廓两种方式:
1.剪切(clip())
剪切clip是对画布进行剪切,只对剪切后的绘制起效果。
ps:Canvas的图形变换平移、放缩、旋转、错切、裁剪都是只对后面的绘制起效果,
对应Matrix中preXXX,Matrix变换分为preXXX,postXXX,setXXX;preXXX将新的变换操作插到队列前,postXXX将新的变换操作插到队列后,setXXX是先reset()清除前面的变换操作并设置新的变换操作,且都是只对后面的绘制起效果。
Canvas的save,restore对变换操作进行保存,和还原,带参的restoreToCount(save()),可以指定还原到第几次保存的状态。


2.遮罩(PorterDuffXfermode)
安卓提供多种遮罩模式选择

遮罩是设置在Paint上的只对 当前绘制的操作有效

下面利用这两种方式实现圆角控件


onDraw
onDrawForeground
dispatchDraw
这三个回调函数都是可以操作View的Canvas;onDraw,onDrawForeground这两个是在View绘制背景,自身内容和前景时回调的 只有设置了背景、自身内容、前景时才会配回调,并且对这两个函数的参数Canvas上的操作,只对背景、自身内容、前景有效。
dispatchDraw是绘制子控件时的回调,参数Canvas可以对子控件的画布进行处理。

通用圆角控件必须对子控件的对应位置也是原价所以我门选择在dispatchDraw中进行圆角处理。

剪切(clip())

    @Override    protected void dispatchDraw(Canvas canvas) {        int width = getWidth();        int height = getHeight();        Path path = new Path();        path.moveTo(0, topLeftRadius);        path.arcTo(new RectF(0, 0, topLeftRadius * 2, topLeftRadius * 2), -180, 90);        path.lineTo(width - topRightRadius, 0);        path.arcTo(new RectF(width - 2 * topRightRadius, 0, width, topRightRadius * 2), -90, 90);        path.lineTo(width, height - bottomRightRadius);        path.arcTo(new RectF(width - 2 * bottomRightRadius, height - 2 * bottomRightRadius, width, height), 0, 90);        path.lineTo(bottomLeftRadius, height);        path.arcTo(new RectF(0, height - 2 * bottomLeftRadius, bottomLeftRadius * 2, height), 90, 90);        path.close();        canvas.clipPath(path);        super.dispatchDraw(canvas);    }

效果图:

上图能看到明显的锯齿 因为 安卓虽提供了抗锯齿功能但是是在Paint上操作的 clip过程没有用到Paint 无法达到抗锯齿目的;

遮罩(PorterDuffXfermode)

写法一

 @Override    protected void dispatchDraw(Canvas canvas) {        super.dispatchDraw(canvas);        drawTopLeft(canvas);//用PorterDuffXfermode        drawTopRight(canvas);//用PorterDuffXfermode        drawBottomLeft(canvas);//用PorterDuffXfermode        drawBottomRight(canvas);//用PorterDuffXfermode    }

效果图:

上图有黑色底色,view的Canvas底层画布的BItmap是 RGB_565的所以怎么画都有一个黑色底色。

我们可以new Canvas一个底层画布的BItmap是 ARGB_8888的绘制完后 再把这个底层画布的BItmap 绘制到View 的Canvas上

写法二

    @Override    protected void dispatchDraw(Canvas canvas) {        Bitmap bitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);        Canvas newCanvas = new Canvas(bitmap);        super.dispatchDraw(newCanvas);        drawTopLeft(newCanvas);        drawTopRight(newCanvas);        drawBottomLeft(newCanvas);        drawBottomRight(newCanvas);        canvas.drawBitmap(bitmap,0,0,imagePaint);//        invalidate();    }

效果图:

实现了,但是这种映射方式实现的 如果子控件中存在滑动控件,滑动时无法实时刷新,用Glide加载image到ImageView中时,WebView load时 都无法实时刷新,出现无法加载的效果,虽然可以加上invalidate通知刷新 但是掉帧明显

我们只能用回写法一 但是要解决黑色背景的问题
只要加上一句代码 就能解决 默认黑色背景的问题

canvas.saveLayer(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), imagePaint,Canvas.ALL_SAVE_FLAG);
 @Override    protected void dispatchDraw(Canvas canvas) {canvas.saveLayer(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), imagePaint,Canvas.ALL_SAVE_FLAG);        super.dispatchDraw(canvas);        drawTopLeft(canvas);//用PorterDuffXfermode        drawTopRight(canvas);//用PorterDuffXfermode        drawBottomLeft(canvas);//用PorterDuffXfermode        drawBottomRight(canvas);//用PorterDuffXfermode        canvas.restore();    }

效果图:

因为view的Canvas底层画布的BItmap是 RGB_565
我们只要在保存为图层就行了。用过Photoshop的都知道默认底层画布是不透明的,要先解锁,而这里解锁就是保存为图层。

相关链接:http://blog.csdn.net/oyuanwa/article/details/51197546

源码地址:https://github.com/Y-bao/RoundAngleFrameLayout

更多相关文章

  1. android 自定义控件(底部icon点击效果)
  2. Android应用优化(7)数据库操作
  3. 【Android】学习笔记(4)――基本控件之ProgressBar
  4. Android要完?来看看谷歌的下一代操作系统Fuchsia长什么样
  5. Android(安卓)的 Sqlite基本操作
  6. Android(安卓)利用OnDraw实现自定义View
  7. Android中的表格布局详解
  8. Android中给系统控件添加配置的自定义属性
  9. Android(安卓)Studio中Button等控件的Text属性英文默认大写的解

随机推荐

  1. Jquery ready和window.onload方法区别
  2. jquery插件——仿新浪微博限制输入字数的
  3. KendoUI和jQuery 1.9.0的问题
  4. jQuery.zTree 点击节点展开折叠子节点
  5. jquery 生成table表格 部分代码
  6. 如何部署Bower安装的软件包?
  7. 用WordPress决定jQuery的版本?
  8. jQuery无法从localhost检索数据
  9. 如何使用jquery ajax获取api数据?
  10. 用jquery 绑定一个按钮click事件后,第一次