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

今天我们要用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);
    	}
    }


源代码下载












  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值