Android Xfermode 实战 实现圆形、圆角图片 练习(1)
我要做像这个圆形的头像:
主要通过 //使用SRC_IN
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
设置两个图形叠加的形式。
\
\
\
\
\
圆角图像时和圆形图像基本流程一致,
只是在画限制图像时
圆形图像是canvas.drawCircle(min/2, min/2, min/2, paint); 一个圆形
圆角图像是画一个圆角矩形
RectF rect = new RectF(0, 0, source.getWidth(), source.getHeight());
canvas.drawRoundRect(rect, mRadius, mRadius, paint);
\
然后设置paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
最后画图像canvas.drawBitmap(source, 0, 0, paint);
\
引用自定义View:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res/com.example.customview03"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<com.example.customview03.CustomImageView
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:id="@+id/customIamgeView"
android:layout_width="100dp"
android:layout_height="100dp"
custom:borderRadius="10dp"
custom:src="@drawable/b"
custom:type="circle" />
<com.example.customview03.CustomImageView
android:id="@+id/customIamgeView1"
android:layout_marginTop="30dp"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_below="@+id/customIamgeView"
android:layout_centerInParent="true"
custom:borderRadius="10dp"
custom:src="@drawable/b"
custom:type="round" />
</RelativeLayout>
\
自定义样式表:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 图片, 圆的半径, 是否显示圆形 -->
<attr name="borderRadius" format="dimension"></attr>
<attr name="type">
<enum name="circle" value="0"></enum>
<enum name="round" value="1"></enum>
</attr>
<attr name="src" format="reference"></attr>
<declare-styleable name="CustomImageView">
<attr name="borderRadius"></attr>
<attr name="type"></attr>
<attr name="src"></attr>
</declare-styleable>
</resources>
\
自定义View:
package com.example.customview03;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
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.util.Log;
import android.util.TypedValue;
import android.view.View;
public class CustomImageView extends View {
private int mRadius; //半径
private int mType; //自定义View形状 圆形, 圆角
private Bitmap mSrc; //图片
private int mWidth;
private int mHeight;
//画笔
private Paint mPaint;
public CustomImageView(Context context) {
this(context, null);
// TODO Auto-generated constructor stub
}
public CustomImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray typedArray = context.getTheme()
.obtainStyledAttributes(attrs, R.styleable.CustomImageView, defStyle, 0);
intView(typedArray);
}
private void intView(TypedArray typedArray) {
int n = typedArray.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = typedArray.getIndex(i);
switch (attr) {
case R.styleable.CustomImageView_borderRadius:
mRadius= typedArray.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10f,
getResources().getDisplayMetrics()));// 默认为10DP
break;
case R.styleable.CustomImageView_type:
mType = typedArray.getInt(attr, 0);//默认是圆形
break;
case R.styleable.CustomImageView_src:
mSrc = BitmapFactory.decodeResource(getResources(), typedArray.getResourceId(attr, 0));
break;
default:
break;
}
typedArray.recycle();
mPaint = new Paint();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measureSpec = MeasureSpec.getSize(widthMeasureSpec);
int measureMode = MeasureSpec.getMode(widthMeasureSpec);
if(measureMode == MeasureSpec.EXACTLY){
mWidth = measureSpec;
}else {
int desireByImg = getPaddingLeft()+getPaddingRight()+mSrc.getWidth();
if(measureMode == MeasureSpec.AT_MOST){//wrap_content
mWidth = Math.min(desireByImg, measureSpec);
}else {
mWidth = desireByImg;
}
}
//测量高度
measureSpec = MeasureSpec.getSize(heightMeasureSpec);
measureMode = MeasureSpec.getMode(heightMeasureSpec);
if(measureMode == MeasureSpec.EXACTLY){///match_parent
mHeight = measureSpec;
}else {
int desireByImg = getPaddingTop()+getPaddingBottom()+mSrc.getHeight();
if(measureMode == MeasureSpec.AT_MOST){//wrap_content
mHeight = Math.min(desireByImg, measureSpec);
}else {
mHeight = desireByImg;
}
}
setMeasuredDimension(mWidth, mHeight);
}
@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
try{
Log.i("tag", "onDraw()"+mType);
//根据type绘制
switch (mType) {
case 0://圆形
int minWidth = Math.min(mWidth, mHeight);
//绘制圆形, 按照图片最小边绘制
mSrc = Bitmap.createScaledBitmap( mSrc, minWidth, minWidth, false);
canvas.drawBitmap(createCircleImage(mSrc, minWidth), 0, 0, null);
break;
case 1: //圆角
canvas.drawBitmap(createRoundConerImage(mSrc), 0, 0, null);
break;
default:
break;
}
}catch(Exception e){
e.printStackTrace();
}
}
/**
* 按照原图和边长绘制圆形
* @param source
* @param min
* @return
*/
private Bitmap createCircleImage(Bitmap source, int min){
Log.i("tag", "createCircleiamge");
final Paint paint = new Paint();
paint.setAntiAlias(true);//抗锯齿
Bitmap target = Bitmap.createBitmap(min, min, Config.ARGB_8888);
//产生一个相同大小的画布
Canvas canvas = new Canvas(target);
//首先绘制圆形
paint.setColor(Color.RED);
canvas.drawCircle(min/2, min/2, min/2, paint);
//使用SRC_IN
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
//绘制图片
canvas.drawBitmap(source, 0, 0, paint);
return target;
}
/**
* 根据原图添加圆角
* @param source
* @return
*/
private Bitmap createRoundConerImage(Bitmap source){
final Paint paint = new Paint();
paint.setAntiAlias(true);
Bitmap target = Bitmap.createBitmap(mWidth, mHeight, Config.ARGB_8888);
Canvas canvas = new Canvas(target);
RectF rect = new RectF(0, 0, source.getWidth(), source.getHeight());
canvas.drawRoundRect(rect, mRadius, mRadius, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(source, 0, 0, paint);
return target;
}
}
\
\