精简版BitmapShader实现圆形头像和圆角方形头像

一种简单明了的圆形头像实现方式

这里写图片描述

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.widget.ImageView;

public class MyCircleView extends ImageView {

	private Paint paint = new Paint(); // 图片画笔
	private Paint paint2 = new Paint(); // 边框画笔
	Matrix mShaderMatrix = new Matrix();
	private Bitmap mBitmap;
	private BitmapShader bs;
	private int bitmapheight;
	private int bitmapwidth;
	private float rudius; // 圆形图片半径
	private int borderWidth = 0; // 边框宽度
	private int borderColor = Color.RED; // 边框颜色

	public MyCircleView (Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		// TODO Auto-generated method stub
		super.onSizeChanged(w, h, oldw, oldh);

		update();
	}
	
	@Override
	public void setImageResource(int resId) {
		// TODO Auto-generated method stub
		super.setImageResource(resId);
	        update();
	}
	
	@Override
	public void setImageBitmap(Bitmap bm) {
		// TODO Auto-generated method stub
		super.setImageBitmap(bm);
	        update();
	}

	/**
	 * @param borderWidth
	 */
	public void setBorderWidth(int borderWidth){
		this.borderWidth = borderWidth;
		update();
	}
	
	/**
	 * @param borderColor
	 */
	public void setBorderColor(int borderColor){
		this.borderColor = borderColor;
		update();
	}
	
	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		// super.onDraw(canvas);

		canvas.drawCircle(getWidth()/2, getHeight()/2, rudius, paint);
		if (borderWidth != 0) {
			canvas.drawCircle(getWidth()/2, getHeight()/2, rudius-(borderWidth/2), paint2);
		}
	}
	
	private void update() {
		// TODO Auto-generated method stub
		if (null == getDrawable()) {
			return;
		}
		BitmapDrawable bd = (BitmapDrawable) getDrawable();
        mBitmap = bd.getBitmap();

		bs = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
		paint.setAntiAlias(true);
		paint.setDither(true);
		paint.setShader(bs);
		
		paint2.setStyle(Paint.Style.STROKE);
		paint2.setAntiAlias(true);
		paint2.setDither(true);
		paint2.setColor(borderColor);
		paint2.setStrokeWidth(borderWidth);
		
		bitmapwidth = mBitmap.getWidth();
		bitmapheight = mBitmap.getHeight();
		
		rudius = Math.min(getWidth()/2, getHeight()/2);

		setShaderMatrix();
		invalidate();
	}

    private void setShaderMatrix() {
        float scale;
        float dx = 0;
        float dy = 0;

        mShaderMatrix.set(null);
        
		// 根据View和图片的宽高比对图片进行缩小或放大
        if (bitmapwidth * getHeight() > getWidth() * bitmapheight) {
            scale = getHeight() / (float) bitmapheight;
            dx = (getWidth() - bitmapwidth * scale) * 0.5f;
        } else {
            scale = getWidth() / (float) bitmapwidth;
            dy = (getHeight() - bitmapheight * scale) * 0.5f;
        }

        mShaderMatrix.setScale(scale, scale);
        mShaderMatrix.postTranslate(dx,dy);

        bs.setLocalMatrix(mShaderMatrix);
    }

}

初始化完View后直接设置属性就可以了

	MyCircleView circle_img = (MyCircleView ) findViewById(R.id.circle_img);
	circle_img.setImageResource(R.drawable.b);
	circle_img.setBorderWidth(14);
	circle_img.setBorderColor(Color.BLUE);

也可以更改onDraw方法,画出圆角方形图片,

protected void onDraw(Canvas canvas) {
	//	super.onDraw(canvas);
	// 设置矩形各边位置
	float l = 0;
	float t = 0;
	float r = 0;
	float b = 0;
	// 设置圆角半径
	float rx = 0; 
	float ry = 0;
	
	// 判断是长图还是宽图,来设置矩形四个边的位置
	if (getHeight() > getWidth()) {
		t = (getHeight()-getWidth())/2;
		r = getWidth();
		b = (getHeight()+getWidth())/2;
		
	} else {
		l = (getWidth()-getHeight())/2;
		t = 0;
		r = (getWidth()+getHeight())/2;
		b = getWidth();
	}
	// 找出一个最小边,设置圆角半径为该边的1/6。
	rx = ry = Math.min(getWidth(), getHeight())/6;
	
	RectF rect = new RectF(l, t, r, b);
	canvas.drawRoundRect(rect, rx, ry, paint);
	if (borderWidth != 0) {
		// 画边框时,应减去边框的宽度,
		RectF rect2 = new RectF((borderWidth/2)+l, t+(borderWidth/2), r-(borderWidth/2), b-(borderWidth/2));
		canvas.drawRoundRect(rect2, rx-(borderWidth/2), ry-(borderWidth/2), paint2);
	}
}

这里写图片描述
也可以根据需求画出椭圆、三角形等其他形状
如果要自定义xml属性要先写一个attr文件,定义属性

	<resources>
	    <declare-styleable name="MyView">
	        <attr name="borderWidth" format="dimension"/>
	        <attr name="borderColor" format="color"/>
	    </declare-styleable>
	</resources>

不要忘记在xml布局文件中加上
xmlns:mystyle="http://schemas.android.com/apk/res/com.example.xxxxxx"

其中mystyle是自己定义名字(随便起名字),com.example.xxxxxx是自己项目的包名

	<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
	    xmlns:tools="http://schemas.android.com/tools"
	    xmlns:mystyle="http://schemas.android.com/apk/res/com.example.xxxxxx"
	    android:layout_width="match_parent"
	    android:layout_height="match_parent"

	    <com.example.xxxxxx.MyCircleView 
	        android:id="@+id/circle_img2"
	        android:layout_width="200dp"
	        android:layout_height="200dp"
	        mystyle:borderColor="@android:color/holo_red_light"
	        mystyle:borderWidth="12dp"/>
	    
	 </RelativeLayout>

重写的构造方法,获取xml中的参数

public MyCircleView (Context context) {
	this(context, null);
}

public MyCircleView (Context context, AttributeSet attrs) {
	this(context, attrs, 0);
}

public MyCircleView (Context context, AttributeSet attrs, int defStyle) {
	super(context, attrs, defStyle);
	TypedArray ob = context.obtainStyledAttributes(attrs, R.styleable.MyView, defStyle, 0);
	
	// getDimension 和 getColor的第二个参数都是给的默认值
	float borderWidth = ob.getDimension(R.styleable.MyView_borderWidth, 6);
	int borderColor = ob.getColor(R.styleable.MyView_borderColor, Color.BLUE);
	
	// 把获取到的值赋值给变量
	this.borderWidth = borderWidth;
	this.borderColor = borderColor;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值