一种简单明了的圆形头像实现方式
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;
}