Android ImageView圆角,绘制ImageView边框;Bitmap圆角

来源:互联网 发布:中大网络继续教育学院 编辑:程序博客网 时间:2024/06/05 14:57

因为项目中有ImageView圆角的需求,但是网上的例子都不尽如人意,所以自己写了一个,现将其粘贴出来,供各位大神点评.


首先说一下自己的实现思路:

1.通过自定义属性,定义圆角图片的圆角弧度;边框的颜色,宽度等

2.在onDraw(canvas)方法中,使用缓冲机制(就是在bitmap上面实现圆角图片的实现,然后再将bitmap绘制出来;因为直接绘制到canvas上面,当使用Xfermode后,设置属性之后,发现无法实现圆角效果,所以无意中发现了缓冲机制,实现了圆角图片)

3.通过canvas得到ImageView占用的范围矩形,然后通过它创建一个RectF,实现圆角边框


技术点:

1.Xfermode,可以查看http://blog.csdn.net/u010947098/article/details/44541927

2.Canvas,Paint,Rect,RectF,可以查看http://blog.csdn.net/u010947098/article/details/44574171


下面的RoundCanvasView类继承了ImageView类,重写的onDraw(Canvas canvas)方法

package com.example.headroundcanvasdemo.view;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.graphics.Rect;import android.graphics.RectF;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.util.Log;import android.widget.ImageView;import com.example.headroundcanvasdemo.R;public class RoundCanvasView extends ImageView {public final static String TAG="HeadRoundCanvasView";/**需要设置圆角的源图片*/private Bitmap mBitmap;/**绘制圆角bitmap的画笔*/private Paint mPaint;/**绘制的矩形区域*/private Rect rect;/**绘制带有圆角的矩形区域*/private RectF rectF;/**圆角bitmap的圆角弧度*/private int roundRadius = 40;/**屏幕密度*/private DisplayMetrics displayMetrics; /**ImageView所占的宽*/private float width = 80;/**ImageView所占的高*/private float height = 80;/**边框颜色*/private int borderColor = -1;/**边框宽度*/private int borderWidth = 2;/** * 设置需要设置圆角的源图片, 并进行缩放 * @param bitmap 源图片 * @param isInvalidate 是否通知View组件重绘 */public void setBitmap(Bitmap bitmap, boolean isInvalidate){//创建一个矩阵Matrix m = new Matrix();//设置bitmap缩放;当小于0时,bitmap缩小;当大于1时,方法m.setScale(width/mBitmap.getWidth(), height/mBitmap.getHeight());//产生新的位图this.mBitmap = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(), mBitmap.getHeight(), m, true);//判断是否通知view重绘if(isInvalidate){invalidate();}}public RoundCanvasView(Context context) {this(context, null);}public RoundCanvasView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public RoundCanvasView(Context context, AttributeSet attrs,int defStyleAttr) {super(context, attrs, defStyleAttr);//初始化init(context, attrs);}/*** * 初始化操作 */private void init(Context context, AttributeSet attrs) {//初始化画笔mPaint = new  Paint();//初始化颜色mPaint.setColor(Color.BLACK);//抗锯齿mPaint.setAntiAlias(true);//获得密度displayMetrics = getResources().getDisplayMetrics();if(attrs != null){TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RoundAngleImage);//在构造方法中,调用getWidth()和getHeight()方法,获取到的宽高都为0;//getWidth()和getHeight()方法在OnDraw方法中,都能正确返回;//所以把一部分初始化操作放到OnDraw方法中,比如获取ImageView的宽高.//得到ImageView的宽度//width = array.getDimension(R.styleable.RoundAngleImage_roundWidth, 80);//Log.i(TAG, "width = "+width);//width = getWidth();//Log.i(TAG, "getWidth() = "+getWidth());//width = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, width, displayMetrics);//得到ImageView的高度//height = array.getDimension(R.styleable.RoundAngleImage_roundHeight, 80);//Log.i(TAG, "height = "+height);//height = getHeight();//Log.i(TAG, "getHeight() = "+getHeight());//height = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, height, displayMetrics);//Log.i(TAG, "height = "+height);//得到圆角弧度roundRadius = array.getInteger(R.styleable.RoundAngleImage_roundRadius, 40);Log.i(TAG, "roundRadius = "+roundRadius);//roundRadius = 40;//得到边框颜色borderColor = array.getColor(R.styleable.RoundAngleImage_roundBorderColor, Color.RED);Log.i(TAG, "borderColor = "+borderColor);//borderColor = Color.RED;//得到边框宽度borderWidth = array.getInteger(R.styleable.RoundAngleImage_roundBorderWidth, 2);Log.i(TAG, "borderWidth = "+borderWidth);//borderWidth = 2;//获得Bitmap位图Drawable drawable  = array.getDrawable(R.styleable.RoundAngleImage_roundImageSrc);mBitmap = ((BitmapDrawable)drawable).getBitmap();//mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_head_2).copy(Bitmap.Config.ARGB_8888, true);Log.i(TAG, "mBitmap = "+mBitmap.toString());//回收array.recycle();}else{//得到ImageView的宽度//width = 80;//width = getWidth();//width = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, width, displayMetrics);//得到ImageView的高度//height = 80;//height = getHeight();//height = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, height, displayMetrics);//得到圆角弧度roundRadius = 40;//得到边框颜色borderColor = Color.RED;//得到边框宽度borderWidth = 2;//获得Bitmap位图mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_head_2).copy(Bitmap.Config.ARGB_8888, true);}}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//Log.i(TAG, "getWidth() = "+getWidth());//Log.i(TAG, "getHeight() = "+getHeight());//得到ImageView的宽度width = getWidth();//得到ImageView的高度height = getHeight();//创建一个矩形rect = new Rect(0, 0, (int)width, (int)height);//通过上面创建的矩形,生成一个圆角矩形rectF = new RectF(rect);//将获得的位图进行处理setBitmap(mBitmap, false);//获得圆角的Bitmap位图Bitmap roundBitmap = getCroppedBitmap(mBitmap);//将圆角位图绘制到Canvas上面canvas.drawBitmap(roundBitmap, 0, 0, null);//回收bitmap;//使用bitmap.recycle()方法,可能会报java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@420e97f0异常//改为下面这种方式就不会出现这样的问题了if(roundBitmap != null && !roundBitmap.isRecycled()){roundBitmap = null;}if(mBitmap != null && !mBitmap.isRecycled()){mBitmap = null;}//创建边框RectFRectF borderRectF = getBorderLineRectF(canvas);//创建边框画笔Paint borderPaint = getBorderPaint(borderColor, borderWidth);//绘制边框canvas.drawRoundRect(borderRectF, roundRadius, roundRadius, borderPaint);}/*** * 利用Bitmap进行缓冲,将圆角图片绘制到bitmap中 * @param bmp 源位图  * @return 圆角的Bitmap图片 */private Bitmap getCroppedBitmap(Bitmap bmp){//通过ImageView的大小生成位图Bitmap output = Bitmap.createBitmap((int)width, (int)height, Bitmap.Config.ARGB_8888);//创建一个画布,将位图传入,表示在此位图上面绘制Canvas canvas2 = new Canvas(output);//相当于清屏的作用canvas2.drawARGB(0, 0, 0, 0);//绘制圆角的矩形canvas2.drawRoundRect(rectF, roundRadius, roundRadius, mPaint);//设置画笔的Xfermode属性SRC_INmPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));//将位图绘制到矩形上面canvas2.drawBitmap(bmp, rect, rect, mPaint);//返回,通过设置Xfermode,最后得到的是圆角的Bitmap位图return output;}/*** * ImageView边框的RectF * @param canvas 画布 * @param borderWidth 边框的宽度 * @return */private RectF getBorderLineRectF(Canvas canvas){//通过画布得到ImageView所占用的矩形区域Rect borderRect = canvas.getClipBounds();//设置边框的宽度borderRect.left++;borderRect.top++;borderRect.right--;borderRect.bottom--;//创建圆角矩形RectF borderRectF = new RectF(borderRect);return borderRectF;}/** * ImageView边框的Paint * @param color 画笔的颜色 * @return 返回Paint */private Paint getBorderPaint(int borderColor, int borderWidth){//画笔Paint borderPaint = new Paint();//颜色borderPaint.setColor(borderColor);//style属性borderPaint.setStyle(Paint.Style.STROKE);//画笔的宽度borderPaint.setStrokeWidth(borderWidth);return borderPaint;}}


定义一个attr.xml的文件,放在values目录下面,内容如下:

<?xml version="1.0" encoding="utf-8"?><resources>        <declare-styleable name="RoundAngleImage">        <!-- 原始图片资源 -->        <attr name="roundImageSrc" format="reference"/>        <!-- 圆角图片的圆角弧度 -->        <attr name="roundRadius" format="integer"/>        <!-- ImageView的宽度 -->        <!-- <attr name="roundWidth" format="dimension"/> -->        <!-- ImageView的高度 -->        <!-- <attr name="roundHeight" format="dimension"/> -->        <!-- 边框的颜色 -->        <attr name="roundBorderColor" format="color|reference"/>        <!-- 边框的宽度 -->        <attr name="roundBorderWidth" format="integer"/>    </declare-styleable>    </resources>
使用示例如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    xmlns:round="http://schemas.android.com/apk/res/com.example.headroundcanvasdemo"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <com.example.headroundcanvasdemo.view.RoundCanvasView        android:layout_width="80dp"        android:layout_height="80dp"        android:layout_centerHorizontal="true"        android:layout_centerVertical="true"        round:roundBorderColor="@android:color/holo_red_dark"        round:roundBorderWidth="2"        round:roundImageSrc="@drawable/ic_head_2"        round:roundRadius="40" />    <!--round:roundWidth="80dp"    round:roundHeight="80dp"--></RelativeLayout>

下面的为Bitmap位图生成圆角Bitmap方法:

这里有一个问题:

为什么我在方法里面不能使用Matrix创建一个矩阵,用来压缩bitmap图片,使其生成符合我的标准长宽的bitmap?

希望能够为我解答,谢谢.

public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) {  // // 创建一个矩阵//Matrix m = new Matrix();//// 设置bitmap缩放;当小于0时,bitmap缩小;当大于1时,方法//m.setScale(320 / bitmap.getWidth(), 320 / bitmap.getHeight());//// 产生新的位图//Bitmap mBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),//bitmap.getHeight(), m, true);        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),          bitmap.getHeight(), Config.ARGB_8888);          Canvas canvas = new Canvas(output);          final int color = 0xff424242;          final Paint paint = new Paint();          final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());          final RectF rectF = new RectF(rect);          paint.setAntiAlias(true);          canvas.drawARGB(0, 0, 0, 0);          paint.setColor(color);          canvas.drawRoundRect(rectF, roundPx, roundPx, paint);          paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));          canvas.drawBitmap(bitmap, rect, rect, paint);          return output;      }





0 0
原创粉丝点击