您的位置:首页 > 移动开发 > Android开发

Android BitmapShader 实现圆角图形,或圆图

2015-04-11 10:54 134 查看
今天我们要用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);
}


五,为了解决动态设置的属性,在屏幕发生旋转或者所在Activity久置后台后会重新绘制,这时之前设置的属性就会丢失的问题

我又重写了。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);
}
}


源代码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: