ClipPath
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;
public class ClipPathCircleView extends AppCompatImageView {
private Paint mPaint;
private int mRadius;
private Path mPath;
private RectF mRect;
private Bitmap mBitmap;
public ClipPathCircleView(Context context) {
super(context);
init();
}
public ClipPathCircleView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public ClipPathCircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
mPaint = new Paint();
mPaint.setDither(true);
mPaint.setAntiAlias(true);
mPath = new Path();
mRect = new RectF();
mBitmap = drawableToBitmap(getDrawable());
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int size = Math.min(getMeasuredWidth(),getMeasuredHeight());
mRadius = size / 2;
setMeasuredDimension(size,size);
}
@Override
protected void onDraw(Canvas canvas) {
mRect.set(0,0,mRadius*2,mRadius*2);
mBitmap = thumbImageWithMatrix(mRadius*2,mRadius*2,mBitmap);
mPath.addCircle(mRadius,mRadius,mRadius, Path.Direction.CCW);
canvas.clipPath(mPath);
canvas.drawBitmap(mBitmap,null,mRect,mPaint);
}
private Bitmap drawableToBitmap(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bd = (BitmapDrawable) drawable;
return bd.getBitmap();
}
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, w, h);
drawable.draw(canvas);
return bitmap;
}
private Bitmap zoomBitmap(int targetWidth,int targetHeight, int bitmapRes){
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(),bitmapRes,options);
float scaleW = options.outWidth / (targetWidth*1f);
float scaleH = options.outHeight / (targetHeight*1f);
int size = (int)Math.max(scaleW,scaleH);
if (size <= 1){
options.inSampleSize = 1;
}else {
options.inSampleSize = size;
}
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(getResources(),bitmapRes,options);
}
private Bitmap zoomBitmapV1(int targetWidth,int targetHeight, int bitmapRes){
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), bitmapRes, options);
options.inJustDecodeBounds = false;
options.inDensity = options.outWidth;
options.inTargetDensity = targetWidth;
return BitmapFactory.decodeResource(getResources(),bitmapRes,options);
}
public Bitmap thumbImageWithMatrix(float destWidth, float destHeight,Bitmap bitmapOrg) {
float bitmapOrgW = bitmapOrg.getWidth();
float bitmapOrgH = bitmapOrg.getHeight();
float bitmapNewW = (int) destWidth;
float bitmapNewH = (int) destHeight;
Matrix matrix = new Matrix();
matrix.postScale(bitmapNewW / bitmapOrgW, bitmapNewH / bitmapOrgH);
Bitmap destBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0, (int) bitmapOrgW, (int) bitmapOrgH, matrix, true);
return destBitmap;
}
}
BitmapShader
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;
public class BitmapShaderCircleView extends AppCompatImageView {
private Paint mPaint;
private int mRadius;
public BitmapShaderCircleView(@NonNull Context context) {
super(context);
init();
}
public BitmapShaderCircleView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public BitmapShaderCircleView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int size = Math.min(getMeasuredWidth(),getMeasuredHeight());
mRadius = size / 2;
setMeasuredDimension(size,size);
}
@Override
protected void onDraw(Canvas canvas) {
Bitmap bitmap = drawableToBitmap(getDrawable());
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
float mScale = (mRadius * 2.0f) / Math.min(bitmap.getHeight(), bitmap.getWidth());
Matrix matrix = new Matrix();
matrix.setScale(mScale, mScale);
bitmapShader.setLocalMatrix(matrix);
mPaint.setShader(bitmapShader);
canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);
}
private Bitmap drawableToBitmap(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bd = (BitmapDrawable) drawable;
return bd.getBitmap();
}
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, w, h);
drawable.draw(canvas);
return bitmap;
}
}
Xfermode
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Xfermode;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;
public class PorterDuffXfermodeCircleView extends AppCompatImageView {
private Paint mPaint;
private int mRadius;
private Xfermode mPorterDuffXfermode;
public PorterDuffXfermodeCircleView(@NonNull Context context) {
super(context);
init();
}
public PorterDuffXfermodeCircleView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public PorterDuffXfermodeCircleView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPorterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int size = Math.min(getMeasuredWidth(),getMeasuredHeight());
mRadius = size / 2;
setMeasuredDimension(size,size);
}
@Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (drawable == null) return;
Bitmap sourceBitmap = ((BitmapDrawable)getDrawable()).getBitmap();
if (sourceBitmap != null){
Bitmap bitmap = resizeBitmap(sourceBitmap,getWidth(),getHeight());
drawCircleBitmapByXfermode(canvas,bitmap);
}
}
private Bitmap resizeBitmap(Bitmap sourceBitmap,int dstWidth,int dstHeight){
int width = sourceBitmap.getWidth();
int height = sourceBitmap.getHeight();
float widthScale = ((float)dstWidth) / width;
float heightScale = ((float)dstHeight) / height;
float scale = Math.max(widthScale,heightScale);
Matrix matrix = new Matrix();
matrix.postScale(scale,scale);
return Bitmap.createBitmap(sourceBitmap,0,0,width,height,matrix,true);
}
private void drawCircleBitmapByXfermode(Canvas canvas,Bitmap bitmap){
final int sc = canvas.saveLayer(0,0,getWidth(),getHeight(),null,Canvas.ALL_SAVE_FLAG);
canvas.drawCircle(mRadius,mRadius,mRadius,mPaint);
mPaint.setXfermode(mPorterDuffXfermode);
canvas.drawBitmap(bitmap,0,0,mPaint);
canvas.restoreToCount(sc);
}
}
参考文章 Android圆形图片不求人,自定义View实现(BitmapShader使用) android圆形图片效果 Android 实现圆角/圆形图片的几种方式 Android绘制圆形图片的3个方法 浅谈Android实现圆形头像效果的几种思路和方法
|