自定义imageview中的圆角和圆形图片

/***
 *
 * 描述: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());
   }

}


你可能感兴趣的:(自定义imageview中的圆角和圆形图片)