💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
### 6.3 自定义Drawable Drawable的使用范围很单一,一个是作为ImageView中的图像来显示,另外一个就是作为View的背景,大多数情况下Drawable都是以View的背景这种形式出现的。Drawable的工作原理很简单,其核心就是draw方法。在第5章中,我们分析了View的工作原理,我们知道系统会调用Drawable的draw方法来绘制View的背景,从这一点我们明白,可以通过重写Drawable的draw方法来自定义Drawable。 通常我们没有必要去自定义Drawable,这是因为自定义的Drawable无法在XML中使用,这就降低了自定义Drawable的使用范围。某些特殊情况下我们的确想自定义Drawable,这也是可以的。下面演示一个自定义Drawable的实现过程,我们通过自定义Drawable来绘制一个圆形的Drawable,并且它的半径会随着View的变化而变化,这种Drawable可以作为View的通用背景,代码如下所示。 public class CustomDrawable extends Drawable { private Paint mPaint; public CustomDrawable(int color) { mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(color); } @Override public void draw(Canvas canvas) { final Rect r = getBounds(); float cx = r.exactCenterX(); float cy = r.exactCenterY(); canvas.drawCircle(cx, cy, Math.min(cx, cy), mPaint); } @Override public void setAlpha(int alpha) { mPaint.setAlpha(alpha); invalidateSelf(); } @Override public void setColorFilter(ColorFilter cf) { mPaint.setColorFilter(cf); invalidateSelf(); } @Override public int getOpacity() { // not sure, so be safe return PixelFormat.TRANSLUCENT; } } 在上面的代码中,draw、setAlpha、setColorFilter和getOpacity这几个方法都是必须要实现的,其中draw是最主要的方法,这个方法就和View的draw方法类似,而setAlpha、setColorFilter和getOpacity这三个方法的实现都比较简单,这里不再多说了。在上面的例子中,参考了ShapeDrawable和BitmapDrawable的源码,所以说,源码是一个很好的学习资料,有些技术细节我们不清楚,就可以查看源码中类似功能的实现以及相应的文档,这样就可以更有针对性地解决一些问题。 上面的例子比较简单,但是流程是完整的,读者可以根据自己的需要实现更复杂的自定义Drawable。另外getIntrinsicWidth和getIntrinsicHeight这两个方法需要注意一下,当自定义的Drawable有固有大小时最好重写这两个方法,因为它会影响到View的wrap_content布局,比如自定义Drawable是绘制一张图片,那么这个Drawable的内部大小就可以选用图片的大小。在上面的例子中,自定义的Drawable是由颜色填充的圆形并且没有固定的大小,因此没有重写这两个方法,这个时候它的内部大小为-1,即内部宽度和内部高度都为-1。需要注意的是,内部大小不等于Drawable的实际区域大小,Drawable的实际区域大小可以通过它的getBounds方法来得到,一般来说它和View的尺寸相同。