直入主题,先看完成的效果图吧。(左边为实现的圆角图片,右边为原图。)
实现的步骤:
1.继承ImageView,重写onDraw方法;
2.定义画布;
3.通过getDrawable()获取图片,并对图片进行处理(压缩);
4.通过Canvas将处理后的图片画在自定义的Bitmap中;(第一层:目标层)
5.设置层与层之间的关系Paint.setXfermode(Xfermode xfermode):关键性的一步
6.继续通过Canvas画自定义的圆(第二层:遮罩层)
7.将画好的bitmap直接显示就OK了。
如下:
代码:
public class CircleImageView extends ImageView {
private Xfermode mXfermode = null;
private Paint mPaint = null;
public CircleImageView(Context context){
this(context,null);
}
public CircleImageView(Context context, AttributeSet attrs) {
super(context, attrs);
mXfermode = new PorterDuffXfermode(Mode.DST_IN);
mPaint = new Paint();
}
@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
//定义画布的大小,一般情况下,宽跟高是相等的,如果不相等,取小的值。
int r = getHeight()>getWidth()?getWidth():getHeight();
//创建一张空白的图片
Bitmap bitmap = Bitmap.createBitmap(r, r, Config.ARGB_8888);
//创建Canvas:如果把Canvas比作画师,那么bitmap就好一张画纸。
Canvas tempCanvas = new Canvas(bitmap);
//定义背景颜色
mPaint.setColor(Color.RED);
tempCanvas.drawRect(0, 0, r, r,mPaint);
Drawable drawable = getDrawable();
if(drawable != null){
int drawableW = drawable.getIntrinsicWidth();
int drawableH = drawable.getIntrinsicHeight();
//压缩图片:等比例压缩
int drawableMin = drawableH>drawableW?drawableW:drawableH;
float scale = r/(float)drawableMin;
drawable.setBounds(0, 0,(int)(scale*drawableW), (int)(scale*drawableH));
//第一层...目标层
drawable.draw(tempCanvas);
}
mPaint.reset();
mPaint.setFilterBitmap(true);
mPaint.setAntiAlias(true);
mPaint.setXfermode(mXfermode);
//第二层...遮罩层
tempCanvas.drawBitmap(makeSrc(r), 0, 0, mPaint);
mPaint.setXfermode(null);
//将画好的bitmap图片直接显示出来就行了
canvas.drawBitmap(bitmap, 0, 0, null);
}
/**
* 将该Bitmap作为遮罩层(圆)
* @param w
* @param h
* @return
*/
private Bitmap makeSrc(int r){
Bitmap bitmap = Bitmap.createBitmap(r, r, Config.ARGB_8888);
Canvas c = new Canvas(bitmap);
Paint p = new Paint();
p.setColor(Color.WHITE);
p.setAntiAlias(true);//消除锯齿
c.drawCircle(r/2, r/2, r/2, p);
return bitmap;
}
}
值得一说的:Canvas,Paint,Bitmap之间的关系。
Bitmap:画纸,其实就是位图。刚创建的张画纸是空白的,没有任何内容,经过Canvas可以在这里画出各种形状。
Paint:画笔,通过Paint,可以定义各种形状和字体颜色和风格。
Canvas:画师,功能强大,通过Canvas可以画出各种形状的图形。
所以总结一句话,就是画师拿着画笔在画纸上画画。
布局xml代码:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#00FFFF"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<com.datian.graphicdemo.CircleImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/dst1" />
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/dst1" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<com.datian.graphicdemo.CircleImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/dst3" />
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/dst3" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<com.datian.graphicdemo.CircleImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:src="@drawable/dst4" />
<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:src="@drawable/dst4" />
</LinearLayout>
</LinearLayout>
</ScrollView>