ShapeDrawable 用于绘制各种形状,使用 Shape 类来绘图。
Shape 类只负责 drawable 的形状和大小,颜色(材质 Shader) 以及 bounds 仍由 ShapeDrawable 本身管理。
Shape 类的主要方法和属性:
public abstract class Shape implements Cloneable {
private float mWidth;
private float mHeight;
public abstract void draw(Canvas canvas, Paint paint);
public final void resize(float width, float height) {
//...
}
protected void onResize(float width, float height) {}
}
保存高宽,外部访问 resize,内部回调 onResize。
实现类 RectShape :
ublic class RectShape extends Shape {
private RectF mRect = new RectF();
@Override
public void draw(Canvas canvas, Paint paint) {
canvas.drawRect(mRect, paint);
}
@Override
protected void onResize(float width, float height) {
mRect.set(0, 0, width, height);
}
protected final RectF rect() {
return mRect;
}
}
实现类 OvalShape:
public class OvalShape extends RectShape {
@Override
public void draw(Canvas canvas, Paint paint) {
canvas.drawOval(rect(), paint);
}
}
其他 Shape 实现类也是类似的。
ShapeDrawable 通过 onDraw 函数把绘图的任务交给了 Shape 类:
@Override
public void draw(Canvas canvas) {
final Rect r = getBounds();
final ShapeState state = mShapeState;
final Paint paint = state.mPaint;
final int prevAlpha = paint.getAlpha();
paint.setAlpha(modulateAlpha(prevAlpha, state.mAlpha));
// only draw shape if it may affect output
if (paint.getAlpha() != 0 || paint.getXfermode() != null || paint.hasShadowLayer()) {
final boolean clearColorFilter;
if (mTintFilter != null && paint.getColorFilter() == null) {
paint.setColorFilter(mTintFilter);
clearColorFilter = true;
} else {
clearColorFilter = false;
}
if (state.mShape != null) {
// need the save both for the translate, and for the (unknown)
// Shape
final int count = canvas.save();
canvas.translate(r.left, r.top);
onDraw(state.mShape, canvas, paint);
canvas.restoreToCount(count);
} else {
canvas.drawRect(r, paint);
}
if (clearColorFilter) {
paint.setColorFilter(null);
}
}
// restore
paint.setAlpha(prevAlpha);
}
protected void onDraw(Shape shape, Canvas canvas, Paint paint) {
shape.draw(canvas, paint);
}
注意这段代码:
canvas.translate(r.left, r.top);
onDraw(state.mShape, canvas, paint);
canvas.restoreToCount(count);
在绘画前,先平移了一段距离,因为 Shape 默认是在 (0,0) 位置的。
@Override
protected void onResize(float width, float height) {
mRect.set(0, 0, width, height);
}
大小变化触发过程:
View 重画, view.drawBackground,setBackgoundBounds,shapeDrawable.onBoundsChange,updateShape,
shape.resize,onResize,shapeDrawable.draw,onDraw,shape.draw。