因为项目中要用到圆形头像,就是如下图所示的效果:


所以于是便有了此文。一开始看书,想着,应该怎么画边框圆形呢?后来参考了好多前辈的指导,终于实现了。代码如下:

package com.baby.tools;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.PorterDuffXfermode;import android.graphics.Rect;import android.graphics.Bitmap.Config;import android.graphics.PorterDuff.Mode;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import android.graphics.drawable.NinePatchDrawable;import android.util.AttributeSet;import android.widget.ImageView;import com.example.babybaycar.R;public class RoundImage extends ImageView {//(1)声明应用环境private Context mContext;//(1)声明圆环厚度private int mBorderThickness = 0;//(1)声明内外边框颜色private int mBorderInsideColor = 0;private int mBorderOutsideColor = 0;//(1)声明并初始化圆形的默认长宽private int mBorderWidth = 0;private int mBorderHeight = 0;//(1)声明默认颜色值是黑色private int defaultColor = 0xFFFFFFFF;public RoundImage(Context context) {super(context);mContext = context;}public RoundImage(Context context, AttributeSet attrs) {super(context, attrs);mContext = context; setRoundAttribute(attrs);}public RoundImage(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);mContext = context;//(3)在构造方法里,设置圆形的默认属性setRoundAttribute(attrs);}/* * (2)设置这个圆环的厚度,以及内边框和外边框的颜色; * 由于android 没有这个圆环,当然我们得自定义它的属性 * 所以在res/values/attrs.xml 文件里自定义边框厚度和 * 内外边框的颜色,然后在下面这个函数里去设定具体的值 */private void setRoundAttribute(AttributeSet attrs){/* * TypedArray 顾名思义,被定义了类型的数组,因此它就是 * 一个用来装载自定义的属性值的容器,被 obtainStyledAttributes(AttributeSet, int[], int, int)  * obtainAttributes(AttributeSet, int[]).所调用;google * 说,使用结束后记得调用recycle()来释放它 */TypedArray myAttrs = mContext.obtainStyledAttributes(attrs, R.styleable.roundedimageview);mBorderInsideColor = myAttrs.getColor(R.styleable.roundedimageview_border_inside_color,defaultColor);mBorderOutsideColor = myAttrs.getColor(R.styleable.roundedimageview_border_outside_color, defaultColor);mBorderThickness = myAttrs.getDimensionPixelSize(R.styleable.roundedimageview_border_thickness,0);}/* * (4)绘制圆形 * 由于Google在ImageView中已经有了onDraw方法是专门用来绘制图形的, * 所以这里我们不必自己新建方法,而直接重写父类ImageView的onDraw */@Overrideprotected void onDraw(Canvas canvas) {/* * 声明一个可画的对象,并从ImageView对象中 * 获取一个具体的对象(没有即为null),即实例化 */Drawable drawable = getDrawable();//如果我们要画的图片为空,那么就没有继续画圆环的必要了,返回if (drawable == null) {return;}//如果我们要画的图片的宽度或高度不符合要求,也没有画的必要if (getWidth() == 0 || getHeight()==0) {return;}/* * 同时应该注意到9Patch的图片也是有边框的,那么我们要加边框的 * 图片的应用类是继承了 NinePathcDrawable 的话,那么人家本身 * 有边框,我们也就没有加圆形边框的必要了,这个是个人理解; * 不晓得对否 */if(drawable.getClass() == NinePatchDrawable.class){return;}/* * 参考Google 官方文档,Android 画一个view 要经历两个过程 * 第一个是计算measure ,即计算这个view 所需要多大的尺寸空间 * 第二个是布局layout ,即要根据开发者的要求来放在哪个位置 * 所以,这里我们要先测量 */this.measure(0, 0);//获得该图片,转换成Bitmap 格式,好处理Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap();//要知道图片大小,才能计算出接下来所画圆形的半径if (mBorderWidth == 0) {mBorderWidth = getWidth();}if (mBorderHeight == 0) {mBorderHeight = getHeight();}//半径int radius = 0;/* * 这里要根据我们在layout中是否设置了内外边框颜色的需求而动手画圆 * 三种情况:A:border_inside_color 和 border_outside_color 什么都不设 *          B:设置了外边框 *          C:设置了内外边框,这时候就意味着要画个圆环了 *///取宽度与高度中最大的值为参考,注意画外圆时加上圆环厚度if (mBorderInsideColor != defaultColor&& mBorderOutsideColor != defaultColor) {radius = (mBorderWidth < mBorderHeight ? mBorderWidth: mBorderHeight) / 2 - 2 * mBorderThickness;// 画内圆drawCircleBorder(canvas, radius + mBorderThickness / 2,mBorderInsideColor);// 画外圆drawCircleBorder(canvas, radius + mBorderThickness+ mBorderThickness / 2, mBorderOutsideColor);} else if (mBorderInsideColor != defaultColor&& mBorderOutsideColor == defaultColor) {// 定义画一个边框radius = (mBorderWidth < mBorderHeight ? mBorderWidth: mBorderHeight) / 2 - mBorderThickness;drawCircleBorder(canvas, radius + mBorderThickness / 2,mBorderInsideColor);} else if (mBorderInsideColor == defaultColor&& mBorderOutsideColor != defaultColor) {// 定义画一个边框radius = (mBorderWidth < mBorderHeight ? mBorderWidth: mBorderHeight) / 2 - mBorderThickness;drawCircleBorder(canvas, radius + mBorderThickness / 2,mBorderOutsideColor);} else {// 没有边框radius = (mBorderWidth < mBorderHeight ? mBorderWidth: mBorderHeight) / 2;}//画圆形图像Bitmap roundBitmap = getCroppedRoundBitmap(bitmap, radius);canvas.drawBitmap(roundBitmap, mBorderWidth/2 - radius,mBorderHeight/2 - radius, null);}/** * 根据颜色和半径画圆边框,中间是空的 */private void drawCircleBorder(Canvas canvas,int radius,int color) {//新建画笔对象Paint paint = new Paint();/* * 先来了解下画笔的属性方法 * setAntiAlias: 设置画笔的锯齿效果,true则去掉锯齿; * setColor: 设置画笔颜色; * setARGB:  设置画笔的a,r,p,g值。 * setAlpha:  设置Alpha值,即透明度     * setTextSize: 设置字体尺寸     * setStyle:  设置画笔风格,空心或者实心; * setStrokeWidth: 设置空心的边框宽度。  * setFilterBitmap 如设为true,则图像在动画进行中会滤掉对Bitmap图像的优化操作,加快显示  * setDither 设定是否使用图像抖动处理,会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰      *///这里我们不要锯齿(难看),处理抖动,加快显示,空心,再设置颜色和边框宽度paint.setAntiAlias(true);paint.setColor(color);paint.setDither(true);paint.setFilterBitmap(true);paint.setStyle(Paint.Style.STROKE);paint.setStrokeWidth(mBorderThickness);canvas.drawCircle(mBorderWidth/2, mBorderHeight/2, radius, paint);}/** * 获取裁剪后的圆形图片 *  * @param radius *            半径 */public Bitmap getCroppedRoundBitmap(Bitmap bmp, int radius) {Bitmap scaledSrcBmp;int diameter = radius * 2;// 为了防止宽高不相等,造成圆形图片变形,因此截取长方形中处于中间位置最大的正方形图片int bmpWidth = bmp.getWidth();int bmpHeight = bmp.getHeight();int squareWidth = 0, squareHeight = 0;int x = 0, y = 0;Bitmap squareBitmap;if (bmpHeight > bmpWidth) {// 高大于宽squareWidth = squareHeight = bmpWidth;x = 0;y = (bmpHeight - bmpWidth) / 2;// 截取正方形图片squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth,squareHeight);} else if (bmpHeight < bmpWidth) {// 宽大于高squareWidth = squareHeight = bmpHeight;x = (bmpWidth - bmpHeight) / 2;y = 0;squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth,squareHeight);} else {squareBitmap = bmp;}if (squareBitmap.getWidth() != diameter|| squareBitmap.getHeight() != diameter) {scaledSrcBmp = Bitmap.createScaledBitmap(squareBitmap, diameter,diameter, true);} else {scaledSrcBmp = squareBitmap;}Bitmap output = Bitmap.createBitmap(scaledSrcBmp.getWidth(),scaledSrcBmp.getHeight(), Config.ARGB_8888);Canvas canvas = new Canvas(output);Paint paint = new Paint();Rect rect = new Rect(0, 0, scaledSrcBmp.getWidth(),scaledSrcBmp.getHeight());paint.setAntiAlias(true);paint.setFilterBitmap(true);paint.setDither(true);canvas.drawARGB(0, 0, 0, 0);canvas.drawCircle(scaledSrcBmp.getWidth() / 2,scaledSrcBmp.getHeight() / 2, scaledSrcBmp.getWidth() / 2,paint);paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));canvas.drawBitmap(scaledSrcBmp, rect, rect, paint);// bitmap回收(recycle导致在布局文件XML看不到效果)// bmp.recycle();// squareBitmap.recycle();// scaledSrcBmp.recycle();bmp = null;squareBitmap = null;scaledSrcBmp = null;return output;}}

如上代码主要参考了http://blog.csdn.net/alan_biao/article/details/17379925 这位大哥,谢谢他;我只是在 代码中加入了我自己的理解。如有不对,欢迎指出,谢谢。

Demo代码的话,上面那位大哥有给,所以我就不给了。再次谢谢他。代码版权归他所有。







更多相关文章

  1. 自定义Dialog步骤
  2. android shape stroke
  3. android 圆形 ImageView
  4. xml中自定义图形
  5. 让TextView的drawable与文字一起居中
  6. Android自定义控件实现环形播放进度条
  7. Android中利用shape定制控件边框
  8. Android修改圆形进度条ProgressBar的默认颜色
  9. Android实践之Drawable的使用

随机推荐

  1. Android踩坑日记:android7.0动态相机权限
  2. Greendao简单使用
  3. android http EOFException
  4. 使用Mac终端给安卓手机安卓apk
  5. Android:Xml(读取与存储)
  6. android文件命名错误Invalid file name:
  7. guest mode 无法record audio
  8. Android之ComponentCallbacks2
  9. Unable to cleanly close USB accessory
  10. 解决Android(安卓)SDK Manager下载太慢问