1、前言
Drawable 在我们的日常开发中是经常使用的,而且非常的有用。能够在canvas上绘制,而且相比于View,并不需要去考虑measure、layout,仅仅只要去考虑如何draw(canavs)。我们在学习和使用 Drawable 的时候,当然不能只了解官方提供给我们的那些传统的用法,我们应该学会自定义实现自己想要的效果。
2、原理
Drawable 的原理我们如果要自定义的话是必须了解的,主要是这个方法:
- draw(Canvas canvas)
和View一样,我们是在 draw() 里面对 Canvas 画布进行绘制,我们这个画布就是从 Drawable 附着的 View对象那里来的。draw() 是我们唯一的核心方法。
3、CircleDrawable
这个 Drawable 是用来对图片做圆形处理的,将图片的 Bitmap 对象传入,就会得到一个圆形的 Drawable 资源。
public class CircleDrawable extends Drawable {
private Paint mPaint;
private int mWidth;
private Bitmap mBitmap;
public CircleDrawable(Bitmap bitmap) {
this.mBitmap = bitmap;
BitmapShader bitmapShader = new BitmapShader(mBitmap, TileMode.CLAMP, TileMode.CLAMP);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setShader(bitmapShader);
mWidth = Math.min(mBitmap.getWidth(), mBitmap.getHeight());
}
@Override
public void draw(Canvas canvas) {
// TODO Auto-generated method stub
canvas.drawCircle(mWidth/2, mWidth/2, mWidth/2, mPaint);
}
@Override
public void setAlpha(int alpha) {
// TODO Auto-generated method stub
mPaint.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter cf) {
// TODO Auto-generated method stub
mPaint.setColorFilter(cf);
}
@Override
public int getOpacity() {
// TODO Auto-generated method stub
return PixelFormat.TRANSLUCENT;
}
@Override
public int getIntrinsicHeight() {
// TODO Auto-generated method stub
return mWidth;
}
@Override
public int getIntrinsicWidth() {
// TODO Auto-generated method stub
return mWidth;
}
}
这个代码是很简单的,因为我们设置的是个圆形,所以宽高是一样的,我们用的是位图,所以需要一个着色器,TitleMode是图片平铺的方式,这个与 BitmapDrawable 是一样的。设置 Paint 属性相信大家都是驾轻就熟啦,重写方法也没什么。draw() 因为我们只是做基础的圆形,所以用用canvas 的 drawCircle() 即可。另外,还有getIntrinsicWidth() 和 getIntrinsicHeight() 虽然不是必须重写的方法,但为了在View使用wrap_content的时候,提供一下尺寸,我们也重写它。我们可以拿它去和其它获得宽高的方法比较:
- getWidth() 是实际显示的宽度。
- getMeasureWidth() 是测量宽度,在布局之前计算出来的。
- getIntrinsicWidth() 是原有宽度,有时候原有宽度可能很大,但是实际上空间不够,所有效果上并没有那么大,这个方法可以获得原有宽度,可以辅助测量的时候选择合适的展示宽度。
- getMinimumWidth() 是最小宽度,是XML参数定义里的 minWidth,也是一个辅助测量展示的参数。
这个圆形 Drawable 的原有的值当然是我们测量的mWidth。
public class CustomerDrawableActivity extends Activity {
private ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_customer);
iv = (ImageView) findViewById(R.id.iv);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.picture);
iv.setImageDrawable(new RoundDrawable(bitmap));
}
}
4、RoundDrawable
这是给图片设置圆角的 Drawable,代码也很简单。
public class RoundDrawable extends Drawable {
private Paint mPaint;
private RectF rectF;
private Bitmap mBitmap;
public RoundDrawable(Bitmap bitmap) {
this.mBitmap = bitmap;
BitmapShader bitmapShader = new BitmapShader(mBitmap, TileMode.CLAMP, TileMode.CLAMP);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setShader(bitmapShader);
}
@Override
public void draw(Canvas canvas) {
// TODO Auto-generated method stub
canvas.drawRoundRect(rectF, 30, 30, mPaint);
}
@Override
public void setBounds(int left, int top, int right, int bottom) {
rectF = new RectF(left, top, right, bottom);
}
@Override
public void setAlpha(int alpha) {
// TODO Auto-generated method stub
mPaint.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter cf) {
// TODO Auto-generated method stub
mPaint.setColorFilter(cf);
}
@Override
public int getOpacity() {
// TODO Auto-generated method stub
return PixelFormat.TRANSLUCENT;
}
@Override
public int getIntrinsicHeight() {
// TODO Auto-generated method stub
return mBitmap.getHeight();
}
@Override
public int getIntrinsicWidth() {
// TODO Auto-generated method stub
return mBitmap.getWidth();
}
}
RoundDrawable 与 CircleDrawable 不一样的就是,我们还多了一个 setBounds() 方法,这是给我们 Drawable 提供边界的尺寸,就是绘制的范围。
用法和 CircleDrawable 是一致的。
以上就是自定义Drawable的内容了,这两种Drawable都是比较基础和常用的,如果你想要实现比较复杂的内效果,可以以这个为基础去搭建修改。当然 xml 的效果也足够强大,我们在开发的时候可不能忘掉它哦。
结束语:本文仅用来学习记录,参考查阅。