今天我们要用ImageView的继承类来实现这个效果,依然属于自定义范畴!
既然是自定义,那我们就来复习一下自定义的基本步骤吧:
1,自定义属性
2,在构造方法中获取自定义属性值
3,重写onMeasure方法,调整布局
4,重写onDraw方法绘图。
首先我们先看一下效果图吧,如果觉得效果图很臭,那就没有看下去的必要了!
到了这里,我就不废话了!开始附上我的代码了!
一,自定义属性,
1,type属性,来判断图片是圆角图,还是原图(即是第一个图的样式,还是第二个图的样式),type的值我用了枚举类型
2,bitmapRadius,如果是圆角,则圆角半径的值
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="borderRadius" format="dimension" />
<attr name="type">
<enum name="circle" value="0" />
<enum name="round" value="1" />
</attr>
<declare-styleable name="RoundImageView">
<attr name="borderRadius" />
<attr name="type" />
</declare-styleable>
</resources>
二,在构造方法中拿到属性的值,并初始化矩阵对象了mMatrix,和画笔对象mPaint
private int type;// 自定义图片的类型 0,为圆角形,1,为圆形
private static final int TYPE_ROUND = 0;
private static final int TYPE_CIRCLE = 1;
private int bitmapRadius;// 圆角的半径
private static final int RADIUS_DEFAULT = 10;
private int radius;//圆的半径
private Paint mPaint;// 画笔对象
private BitmapShader mShader;// 图形控制
private Matrix mMatrix;//矩阵对象用于缩放图片
//view的大小
private int mWidth;
private RectF mRectF;
/**
* 第二步
* @param context
*/
public CustomImageView1(Context context) {
this(context, null, 0);
}
public CustomImageView1(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomImageView1(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray typeArray=context
.obtainStyledAttributes(attrs,R.styleable.CustomImageView);
//默认为10dip
bitmapRadius=typeArray.getDimensionPixelOffset(R.styleable.CustomImageView_radiusRadius,
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, RADIUS_DEFAULT, getResources().getDisplayMetrics()));
//默认为圆
type=typeArray.getInt(R.styleable.CustomImageView_type, TYPE_CIRCLE);
typeArray.recycle();
mMatrix=new Matrix();
mPaint=new Paint();
mPaint.setAntiAlias(true);//消除锯齿
}
三在onMeasure中调整控件宽高
因为圆图的话,高宽是相等的,这里取了两者的较小值!
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if(type==TYPE_CIRCLE){
mWidth=Math.min(getMeasuredWidth(), getMeasuredHeight());
radius=mWidth/2;
setMeasuredDimension(mWidth, mWidth);
}
}
四,onDraw方法中绘图
1,先得到图对象,并把图对象Drawable封装到位图对象Bitmap中!
2,得到位图对象后,利用Matrix按比例缩放图像(这里就用到了bitmapShader对象)
3,最后才是绘制图像
1,的实现方法:
private Bitmap drawableToBitmap(){
Drawable drawable=getDrawable();
if(drawable==null){
return null;
}
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);
//将图片画在画布canvas上,并放在容器bitmap中
drawable.draw(canvas);
return bitmap;
}
2,的实现方法:
private void setUpBitmapShaper(){
Bitmap bitmap=drawableToBitmap();
if(bitmap==null){
return;
}
mShader=new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP);
float scale;
if(type==TYPE_CIRCLE){
//圆形
scale=mWidth*1.0f/Math.min(bitmap.getWidth(), bitmap.getHeight());
}else{
//圆角形
scale=Math.max(getWidth()*1.0f/bitmap.getWidth()*1.0f
, getHeight()*1.0f/bitmap.getHeight()*1.0f);
}
mMatrix.setScale(scale,scale);
mShader.setLocalMatrix(mMatrix);
mPaint.setShader(mShader);
}
3,的实现方法:
@Override
protected void onDraw(Canvas canvas) {
if(getDrawable()==null){
return;
}
setUpBitmapShaper();
if(type==TYPE_CIRCLE){
canvas.drawCircle(radius, radius, radius, mPaint);
}else{
canvas.drawRoundRect(mRectF,bitmapRadius, bitmapRadius, mPaint);
}
//canvas.drawCircle(cx, cy, RADIUS_DEFAULT, paint);
}
我又重写了。onSaveInstanceState方法和onRestoreInstanceState方法
private static final String STATE_INSTANCE="state_instance";
private static final String STATE_TYPE="state_type";
private static final String STATE_RADIUS="state_radius";
//只有需要reCreate一個Activity時,才会去调用它,比如,横竖切屏,改变语言,activity久置后台重新启动
@Override
protected Parcelable onSaveInstanceState() {
Bundle bd=new Bundle();
bd.putParcelable(STATE_INSTANCE, super.onSaveInstanceState());
bd.putInt(STATE_TYPE, type);
bd.putInt(STATE_RADIUS, bitmapRadius);
return bd;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if(state instanceof Bundle){
Bundle bd=(Bundle) state;
super.onRestoreInstanceState(bd.getParcelable(STATE_INSTANCE));
type=bd.getInt(STATE_TYPE);
bitmapRadius=bd.getInt(STATE_RADIUS);
}else{
super.onRestoreInstanceState(state);
}
}