Android Xfermode 实战 实现圆形、圆角图片(1)

835 阅读2分钟

 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;  
	}

}


\

\