【Android】Android自定义带board的圆角控件
来源:互联网 发布:eclipse不编译java 编辑:程序博客网 时间:2024/06/01 19:05
介绍
圆角控件常用于头像,按钮,图标等,用途十分广泛,而且常常配合board使用。
在IOS中,UIVIew的CALayer层已经提供了圆角和board的方法,所以圆角控件的制作非常简单,只需要类似以下简单代码即可实现:
view.layer.cornerRadius = 20; view.layer.borderColor = [UIColor yellowColor].CGColor; view.layer.borderWidth = 10; view.clipsToBounds = YES;
而在Android中,系统并没有提供这么直接的方式,所以想要实现同样的效果需要费点心了。本文将会介绍一种在Android中实现带board属性的圆角控件的方法。该方法定义了一个RoundImageView重写了ImageView的onDraw方法,并加入了一些自定义的属性,最后实现以上同样效果的代码非常简洁:
<com.me.obo.circleboardimage.circleview.RoundImageView android:layout_width="80dp" android:layout_height="80dp" android:src="@drawable/head" attr:border_width="3dp" attr:corner_y="40dp" attr:corner_x="40dp" attr:border_color="#FFFFFF"/>
下面就介绍如何实现这样一个RoundImageView
遮罩
在Android中,遮罩功能非常强大,可以用于生成两张图片相互截取的结果。
具体参数和遮罩的效果可以见链接: Android 实现遮罩
在RoundImageView中,遮罩用于清除控件外圈的内容,从而获取到圆角的效果。这里的思路是先获取到控件本身所绘制的图片,之后获取圆角矩形遮罩图片,然后两个图片采用DST_IN遮罩模式来截取中间的遮罩效果,即:
代码实现如下:
// 获取imageview原先的图片 super.onDraw(mDestCanvas); // 创建矩形,表示圆角矩形 if (mRoundRectClip == null) { mRoundRectClip = new RectF(mBorderValue, mBorderValue, getWidth() - mBorderValue, getHeight() - mBorderValue); } // 绘制圆角矩形 mSrcCanvas.drawRoundRect(mRoundRectClip,mCornerXValue,mCornerYValue,mNomalPaint); // 使用遮罩画笔扣除原图中的圆角矩形外面的部分 mDestCanvas.drawBitmap(mSrcBitmap,0,0,mPaintClip);
在获取到遮罩处理的图片之后,为其添加board将会变得容易,也就是在外圈绘制出一个带有宽度的圆即可。
代码实现如下:
// 创建board的矩形 if (mRoundRectBorder == null) { mRoundRectBorder = new RectF(mBorderValue / 2, mBorderValue / 2, getWidth() - mBorderValue / 2, getHeight() - mBorderValue / 2); } // 绘制board mDestCanvas.drawRoundRect(mRoundRectBorder, mCornerXValue, mCornerYValue, mPaintBoard);
整个RoundImageView完整的代码如下:
package com.me.obo.circleboardimage.circleview;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.graphics.RectF;import android.util.AttributeSet;import android.widget.ImageView;import com.me.obo.circleboardimage.R;/** * Created by obo on 16/5/11. * Email:obo1993@gmail.com * Git:https://github.com/OboBear * Blog:http://blog.csdn.net/leilba */public class RoundImageView extends ImageView { private float mCornerXValue ; private float mCornerYValue ; private float mBorderValue ; private int mBorderColor ; public RoundImageView(Context context, AttributeSet attrs) { super(context, attrs); // 获取自定义参数 TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundImageView); // board颜色 mBorderColor = typedArray.getColor(R.styleable.RoundImageView_border_color,Color.argb(0,0,0,0)); // 获取X方向曲率 mCornerXValue = typedArray.getDimension(R.styleable.RoundImageView_corner_x,0); // 获取Y方向曲率 mCornerYValue = typedArray.getDimension(R.styleable.RoundImageView_corner_y,0); // board宽 mBorderValue = typedArray.getDimension(R.styleable.RoundImageView_border_width,0); // 用完需要recycle typedArray.recycle(); initPaints(); } private void initPaints() { // 创建普通画笔 if (mNomalPaint == null) { mNomalPaint = new Paint(); mNomalPaint.setAntiAlias(true); } // 创建遮罩画笔 if (mPaintClip == null) { mPaintClip = new Paint(); mPaintClip.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); mPaintClip.setAntiAlias(true); } // 创建board的画笔 if (mPaintBoard == null) { mPaintBoard = new Paint(); mPaintBoard.setColor(mBorderColor); mPaintBoard.setStyle(Paint.Style.STROKE); mPaintBoard.setStrokeWidth(mBorderValue); mPaintBoard.setAntiAlias(true); } } Bitmap mDestBitmap; Bitmap mSrcBitmap; Canvas mDestCanvas; Canvas mSrcCanvas; Paint mPaintClip; Paint mNomalPaint; Paint mPaintBoard; RectF mRoundRectClip; RectF mRoundRectBorder; @Override protected void onDraw(Canvas canvas) { // 创建遮罩图片和画布 if (mDestBitmap == null) { mDestBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); mSrcBitmap = Bitmap.createBitmap(getWidth(),getHeight(), Bitmap.Config.ARGB_8888); mDestCanvas = new Canvas(mDestBitmap); mSrcCanvas = new Canvas(mSrcBitmap); } // 获取imageview原先的图片 super.onDraw(mDestCanvas); // 创建矩形,表示圆角矩形 if (mRoundRectClip == null) { mRoundRectClip = new RectF(mBorderValue, mBorderValue, getWidth() - mBorderValue, getHeight() - mBorderValue); } // 绘制圆角矩形 mSrcCanvas.drawRoundRect(mRoundRectClip,mCornerXValue,mCornerYValue,mNomalPaint); // 使用遮罩画笔扣除原图中的圆角矩形外面的部分 mDestCanvas.drawBitmap(mSrcBitmap,0,0,mPaintClip); // 创建board的矩形 if (mRoundRectBorder == null) { mRoundRectBorder = new RectF(mBorderValue / 2, mBorderValue / 2, getWidth() - mBorderValue / 2, getHeight() - mBorderValue / 2); } // 绘制board mDestCanvas.drawRoundRect(mRoundRectBorder, mCornerXValue, mCornerYValue, mPaintBoard); // 绘制最终的圆角带有board的图 canvas.drawBitmap(mDestBitmap,0,0,mNomalPaint); }}
自定义Attribute
可能有人要问,圆角弯曲度和board的参数是如何传递到RoundImageView里的。实际上,这里采用了自定义Attribute的方式,该操作需要到res/values 目录下创建 attr.xml 文件,在里面写上自定义的参数名称以及类型:
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="RoundImageView"> <attr name="border_width" format="dimension"/> <attr name="border_color" format="color"/> <attr name="corner_x" format="dimension"/> <attr name="corner_y" format="dimension"/> </declare-styleable></resources>
有了这个,就可以在RoundImageView的构造方法里面,获取到自定义attri的值了
public RoundImageView(Context context, AttributeSet attrs) { super(context, attrs); // 获取自定义参数 TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundImageView); // board颜色 mBorderColor = typedArray.getColor(R.styleable.RoundImageView_border_color,Color.argb(0,0,0,0)); // 获取X方向曲率 mCornerXValue = typedArray.getDimension(R.styleable.RoundImageView_corner_x,0); // 获取Y方向曲率 mCornerYValue = typedArray.getDimension(R.styleable.RoundImageView_corner_y,0); // board宽 mBorderValue = typedArray.getDimension(R.styleable.RoundImageView_border_width,0); // 用完需要recycle typedArray.recycle(); initPaints(); }
在layout里使用的时候,需要在layout的xml开头里面申请自定义的参数即可
xmlns:attr="http://schemas.android.com/apk/res-auto"最后,在layout里面调用RoundImageView的代码非常简洁:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:attr="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/darker_gray" android:orientation="vertical"> <com.me.obo.circleboardimage.circleview.RoundImageView android:layout_width="80dp" android:layout_height="80dp" android:src="@drawable/head" attr:border_width="3dp" attr:corner_y="40dp" attr:corner_x="40dp" attr:border_color="#FFFFFF"/> <com.me.obo.circleboardimage.circleview.RoundImageView android:layout_width="180dp" android:layout_height="180dp" android:src="@drawable/head" attr:border_width="2dp" attr:corner_y="40dp" attr:corner_x="40dp" attr:border_color="#FF0000" android:scaleType="fitXY"/> </LinearLayout>效果如下:
资源下载
RoundImageView
2 0
- 【Android】Android自定义带board的圆角控件
- android自定义带倒影的ImageView控件
- Android自定义控件 -- 带边框的TextView
- Android带日程安排的自定义日历控件
- android自定义带动画的柱状图控件
- Android自定义控件带弹性
- android自定义控件(组合控件)--带删除按钮的EditText
- 【组合控件】android自定义控件之带文字的ImageView
- Android 自定义控件/带资源的控件打包jar问题
- Android自定义控件开发系列(二)——带清除按钮的圆角输入框
- Android--自定义带点击事件监控的Spinner控件
- Android--自定义带点击事件监控的Spinner控件
- Android自定义控件——带阴影的ImageView(ShaderImageView)
- Android自定义点击带声音的控件TextView/Button/ListView
- [Android自定义控件]带加载进度条的ImageView
- Android 自定义控件之 带刻度的进度条
- Android自定义带消息提醒控件
- Android EditText 自定义控件 带消除功能
- HTTP的一些状态消息参考
- 第五届山东省ACM Full Binary Tree
- Servlet的生命周期和web.xml
- 三层学习偶得之修改自己电脑的名称
- Eclipse 中 CVS show histoy 显示空白
- 【Android】Android自定义带board的圆角控件
- python2.x和python3.x中raw_input( )和input( )区别
- php实现文件上传
- java WEB 表单 验证码问题与解决
- new和malloc的区别&delete和free的区别
- iOS开发 -关于使用iOS沙盒路径遇到的问题
- Unix环境高级编程(阅读笔记)----中断的系统调用,自动重启动的函数
- mysql插入数据乱码
- iOS 获取手机的型号,系统版本,软件名称,软件版本