/***
*
* 描述:1.自定义属性
* 2.获取自定义view的属性值,并初始化相关的对象
* 3.测量view的大小
* 4.对图片进行美化即渲染器
* 5.绘制
* 6.状态的存储与恢复
* 项目名称:bitmapshader
* 类名称:RoundImageView
*
* @author:白小兵
* @Date:2016-3-23上午10:09:30
*/
public class RoundImageView extends ImageView {
private Paint mPaint;//画笔
private static final int BODER_RADIUS_DEFAULT=20;
private int mBorderRadius;//圆角边框的半径,主要在绘制圆角图片时使用
private int mRadius;//圆角的图片的大小
private Matrix matrix;//3x3矩阵用来放大缩小图片
private BitmapShader mBitmapShader;//图像渲染器
private int mWidth;//放置图片的view控件的宽度
private RectF mRectF;//用来表示一个矩形区域
private int type;//用于存储所绘制的view的形状
private static final String STATE_INSTANCE="state_instance";
private static final String STATE_TYPE="state_type";
private static final String STATE_BORDER="state_border";
private static final int TYPE_CIRCLE=0;
private static final int TYPE_ROUND=1;
public RoundImageView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint=new Paint();
mPaint.setAntiAlias(true);//去除图片边缘锯齿
matrix=new Matrix();
TypedArray ta=context.obtainStyledAttributes(attrs,R.styleable.RoundImageView);
mBorderRadius=ta.getDimensionPixelSize(R.styleable.RoundImageView_borderRadius,
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,BODER_RADIUS_DEFAULT,getResources().getDisplayMetrics()));
type=ta.getInt(R.styleable.RoundImageView_type,TYPE_CIRCLE);//默认情况下是圆形
ta.recycle();//对TypedArray进行回收,减少资源的占用
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
/**
* 如果是圆形强制改变view的宽高,以小值为主
*/
if (type==TYPE_CIRCLE) {
mWidth=Math.min(getMeasuredWidth(),getMeasuredHeight());//测量出view控件的高度和宽度中最小的一个作为圆形的直径
mRadius=mWidth/2;//设定圆形图片的半径
setMeasuredDimension(mWidth,mWidth);// 设置view的大小
}
}
/**
*
* 功能: 初始化bitmapShader
* @author:白小兵
* @date:2016-3-23上午10:17:29
*/
private void setUpShader(){
Drawable drawable=getDrawable();
if (drawable==null) {
return;
}
Bitmap bitmap=drawableToBitmap(drawable);
/**
* CLAMP 拉伸 这个拉伸是横向的最后一行的像素进行重复,纵行的最后一行像素重复
REPEAT 重复
MIRROR 镜像
*/
//把bitmap作为着色器给指定区域绘制bitmap
mBitmapShader=new BitmapShader(bitmap,TileMode.CLAMP,TileMode.CLAMP);
float scale=1.0f;//控件的大小与bitmap中对应的图片的比例
if (type==TYPE_CIRCLE) {
int mSize=Math.min(bitmap.getWidth(),bitmap.getHeight());//取bitmap宽度和高度中最小的值为圆形图片的直径
scale=mWidth*1.0f/mSize;
}else if (type==TYPE_ROUND) {
//如果图片的宽高与view的宽高不匹配,计算出缩放的比例,缩放后的图片的宽高要大于view的宽高,所以这里取他们的最大值
scale=Math.max(getWidth()*1.0f/bitmap.getWidth(),getHeight()*1.0f/bitmap.getHeight());
}
//bitmapShader的矩阵,主要用于设置图片的缩放
matrix.setScale(scale,scale);
mBitmapShader.setLocalMatrix(matrix);
mPaint.setShader(mBitmapShader);
}
private Bitmap drawableToBitmap(Drawable drawable){
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bd=(BitmapDrawable)drawable;
return bd.getBitmap();
}
int width=drawable.getIntrinsicWidth();//获取drawable中图片宽度
int height=drawable.getIntrinsicHeight();//获取drawable中对应图片的高度
Bitmap bitmap=Bitmap.createBitmap(width, height,
/**
* 其中ARGB_8888 32位 每个像素占4位,用来保存透明度以及红绿蓝,图片的质量比较高,但是很耗费内存
* RGB_565 16位 每个像素占8位 R占5位,G占6位,B占5位,不包含图片的透明度
*/
drawable.getOpacity()!=PixelFormat.OPAQUE?Bitmap.Config.ARGB_8888:Bitmap.Config.RGB_565);//理解:PixelFormat.OPAQUE表示对透明度没有要求
Canvas canvas=new Canvas(bitmap);//创建画布对象
drawable.setBounds(0, 0, width,height);//设置drawable的图片区域
drawable.draw(canvas);//在画布上画绘制图形
return bitmap;
}
@Override
protected void onDraw(Canvas canvas) {
if (getDrawable()==null) {
return;
}
setUpShader();
if (type==TYPE_ROUND) {
canvas.drawRoundRect(mRectF,mBorderRadius,mBorderRadius, mPaint);
}else{
canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//圆角图片的区域
if (type==TYPE_ROUND) {
mRectF=new RectF(0, 0, getWidth(), getHeight());
}
}
/**
* 用于保存当前view的状态
*/
@Override
protected Parcelable onSaveInstanceState() {
Bundle bundle=new Bundle();
bundle.putParcelable(STATE_INSTANCE, super.onSaveInstanceState());
bundle.putInt(STATE_TYPE,type);
bundle.putInt(STATE_BORDER,mBorderRadius);
return bundle;
}
/***
* 在重新启动直接从内存中调用保存的数据
*/
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (state instanceof Bundle) {
Bundle bundle=(Bundle)state;
super.onRestoreInstanceState(bundle.getParcelable(STATE_INSTANCE));
this.type=bundle.getInt(STATE_TYPE);
this.mBorderRadius=bundle.getInt(STATE_BORDER);
}else{
super.onRestoreInstanceState(state);
}
}
/**
*
* 功能: 对于圆角图片设置边框时半径
* @author:白小兵
* @date:2016-3-23下午2:17:09
*/
public void setBorderRadius(int mBorderRadius){
int pxVal=dp2px(mBorderRadius);
if (this.mBorderRadius!=pxVal) {
this.mBorderRadius=pxVal;
invalidate();//调用父类的方法进行重新绘制
}
}
/***
*
* 功能:设置需要的类型
* @param type
* @return
* @author:白小兵
* @date:2016-3-23下午2:27:23
*/
public void setType(int type){
if (this.type!=type) {
this.type=type;
if (this.type!=TYPE_CIRCLE&&this.type!=TYPE_ROUND) {
this.type=TYPE_CIRCLE;
}
requestLayout();//重新布局
}
}
private int dp2px(int dpVal){
return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, getResources().getDisplayMetrics());
}
}