先把代码贴上。为了方便分析,所以有些System.out.println。
public class CircleImageView extends ImageView {
private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;
private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
private static final int COLORDRAWABLE_DIMENSION = 2;
private static final int DEFAULT_BORDER_WIDTH = 0;
private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
private static final boolean DEFAULT_BORDER_OVERLAY = false;
private final RectF mBorderRect = new RectF();
private final RectF mDrawableRect = new RectF();
private final Matrix mShaderMatrix = new Matrix();
private final Paint mBitmapPaint = new Paint();
private final Paint mBorderPaint = new Paint();
private int mBorderColor = DEFAULT_BORDER_COLOR;
private int mBorderWidth = DEFAULT_BORDER_WIDTH;
private Bitmap mBitmap;
private BitmapShader mBitmapShader;
private int mBitmapHeight;
private int mBitmapWidth;
private float mDrawableRadius;
private float mBorderRadius;
private ColorFilter mColorFilter;
private boolean mReady;
private boolean mSetupPending;
private boolean mBorderOverlay;
public CircleImageView(Context context) {
super(context);
init();
System.out.println("CircleImageView1");
}
public CircleImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
System.out.println("CircleImageView2");
}
public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
System.out.println("CircleImageView3");
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyleAttr, 0);
mBorderWidth = array.getDimensionPixelSize(R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH);
mBorderColor = array.getColor(R.styleable.CircleImageView_border_color, DEFAULT_BORDER_COLOR);
mBorderOverlay = array.getBoolean(R.styleable.CircleImageView_border_overlay, DEFAULT_BORDER_OVERLAY);
System.out.println("CircleImageView3.1");
array.recycle();
System.out.println("CircleImageView3.2");
init();
System.out.println("CircleImageView3.3");
}
private void init() {
System.out.println("init1");
super.setScaleType(SCALE_TYPE);
System.out.println("init2");
mReady = true;
if (mSetupPending) {
System.out.println("init+mSetupPending");
setup();
mSetupPending = false;
}
System.out.println("init3");
}
@Override
public ScaleType getScaleType() {
return SCALE_TYPE;
}
@Override
public void setScaleType(ScaleType scaleType) {
if (scaleType != SCALE_TYPE) {
throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));
}
}
@Override
public void setAdjustViewBounds(boolean adjustViewBounds) {
if (adjustViewBounds) {
throw new IllegalArgumentException("adjustViewBounds not supported.");
}
}
@Override
protected void onDraw(Canvas canvas) {
System.out.println("onDraw1");
if (getDrawable() == null) {
return;
}
canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint);
// canvas.drawCircle(getWidth() / 2, getHeight() / 2, 400, mBitmapPaint);
if (mBorderWidth != 0) {
canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, mBorderPaint);
// canvas.drawCircle(getWidth() / 2, getHeight() / 2, 400, mBorderPaint);
}
System.out.println("onDraw2");
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
System.out.println("onSizeChanged1");
setup();
System.out.println("onSizeChanged2");
}
@Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
System.out.println("setImageBitmap1");
mBitmap = bm;
System.out.println("setImageBitmap2");
setup();
System.out.println("setImageBitmap3");
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
System.out.println("onMeasure");
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
System.out.println("onLayout");
}
@Override
public void setColorFilter(ColorFilter cf) {
if (cf == mColorFilter) {
return;
}
mColorFilter = cf;
mBitmapPaint.setColorFilter(mColorFilter);
invalidate();
}
private void setup() {
System.out.println("setup1");
if (!mReady) {
System.out.println("mSetupPending = true;");
mSetupPending = true;
return;
}
System.out.println("setup2");
if (mBitmap == null) {
return;
}
System.out.println("setup3");
mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mBitmapPaint.setAntiAlias(true);
mBitmapPaint.setShader(mBitmapShader);
mBorderPaint.setStyle(Paint.Style.STROKE);
mBorderPaint.setAntiAlias(true);
mBorderPaint.setColor(mBorderColor);
mBorderPaint.setStrokeWidth(mBorderWidth);
mBitmapHeight = mBitmap.getHeight();
mBitmapWidth = mBitmap.getWidth();
mBorderRect.set(0, 0, getWidth(), getHeight());
mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2, ((mBorderRect.width() - mBorderWidth) / 2));
mDrawableRect.set(mBorderRect);
if (!mBorderOverlay) {
mDrawableRect.inset(mBorderWidth, mBorderWidth);
}
mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width() / 2);
System.out.println("setup4");
updateShaderMatrix();
System.out.println("setup5");
invalidate();
System.out.println("setup6");
}
@Override
public void invalidate() {
super.invalidate();
System.out.println("invalidate");
}
public void updateShaderMatrix() {
System.out.println("updateShaderMatrix1");
float scale;
float dx = 0;
float dy = 0;
mShaderMatrix.set(null);
if (mBitmapWidth * mDrawableRect.height() > mBitmapHeight * mDrawableRect.width()) {
scale = mDrawableRect.height() / (float) mBitmapHeight;
dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
} else {
scale = mDrawableRect.width() / (float) mBitmapWidth;
dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
}
System.out.println("mShaderMatrix.setScale(scale, scale)");
mShaderMatrix.setScale(scale, scale);
System.out.println("mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top)");
mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top);
System.out.println("mBitmapShader.setLocalMatrix(mShaderMatrix)");
mBitmapShader.setLocalMatrix(mShaderMatrix);
System.out.println("updateShaderMatrix2");
}
}
用的是setImageBitmap,下面是输出结果:
09-07 14:11:50.176 13540-13540/com.example.myselfimageview I/System.out: CircleImageView3
09-07 14:11:50.177 13540-13540/com.example.myselfimageview I/System.out: CircleImageView3.1
09-07 14:11:50.177 13540-13540/com.example.myselfimageview I/System.out: CircleImageView3.2
09-07 14:11:50.177 13540-13540/com.example.myselfimageview I/System.out: init1
09-07 14:11:50.177 13540-13540/com.example.myselfimageview I/System.out: invalidate
09-07 14:11:50.177 13540-13540/com.example.myselfimageview I/System.out: init2
09-07 14:11:50.177 13540-13540/com.example.myselfimageview I/System.out: init3
09-07 14:11:50.177 13540-13540/com.example.myselfimageview I/System.out: CircleImageView3.3
09-07 14:11:50.177 13540-13540/com.example.myselfimageview I/System.out: CircleImageView2
09-07 14:11:50.412 13540-13540/com.example.myselfimageview I/System.out: invalidate
09-07 14:11:50.412 13540-13540/com.example.myselfimageview I/System.out: setImageBitmap1
09-07 14:11:50.412 13540-13540/com.example.myselfimageview I/System.out: setImageBitmap2
09-07 14:11:50.412 13540-13540/com.example.myselfimageview I/System.out: setup1
09-07 14:11:50.412 13540-13540/com.example.myselfimageview I/System.out: setup2
09-07 14:11:50.412 13540-13540/com.example.myselfimageview I/System.out: setup3
09-07 14:11:50.412 13540-13540/com.example.myselfimageview I/System.out: setup4
09-07 14:11:50.412 13540-13540/com.example.myselfimageview I/System.out: updateShaderMatrix1
09-07 14:11:50.412 13540-13540/com.example.myselfimageview I/System.out: mShaderMatrix.setScale(scale, scale)
09-07 14:11:50.412 13540-13540/com.example.myselfimageview I/System.out: mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top)
09-07 14:11:50.412 13540-13540/com.example.myselfimageview I/System.out: mBitmapShader.setLocalMatrix(mShaderMatrix)
09-07 14:11:50.412 13540-13540/com.example.myselfimageview I/System.out: updateShaderMatrix2
09-07 14:11:50.412 13540-13540/com.example.myselfimageview I/System.out: setup5
09-07 14:11:50.412 13540-13540/com.example.myselfimageview I/System.out: invalidate
09-07 14:11:50.413 13540-13540/com.example.myselfimageview I/System.out: setup6
09-07 14:11:50.413 13540-13540/com.example.myselfimageview I/System.out: setImageBitmap3
09-07 14:11:50.451 13540-13540/com.example.myselfimageview I/System.out: onMeasure
09-07 14:11:50.467 13540-13540/com.example.myselfimageview I/System.out: onSizeChanged1
09-07 14:11:50.467 13540-13540/com.example.myselfimageview I/System.out: setup1
09-07 14:11:50.467 13540-13540/com.example.myselfimageview I/System.out: setup2
09-07 14:11:50.467 13540-13540/com.example.myselfimageview I/System.out: setup3
09-07 14:11:50.467 13540-13540/com.example.myselfimageview I/System.out: setup4
09-07 14:11:50.467 13540-13540/com.example.myselfimageview I/System.out: updateShaderMatrix1
09-07 14:11:50.467 13540-13540/com.example.myselfimageview I/System.out: mShaderMatrix.setScale(scale, scale)
09-07 14:11:50.467 13540-13540/com.example.myselfimageview I/System.out: mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top)
09-07 14:11:50.467 13540-13540/com.example.myselfimageview I/System.out: mBitmapShader.setLocalMatrix(mShaderMatrix)
09-07 14:11:50.467 13540-13540/com.example.myselfimageview I/System.out: updateShaderMatrix2
09-07 14:11:50.467 13540-13540/com.example.myselfimageview I/System.out: setup5
09-07 14:11:50.467 13540-13540/com.example.myselfimageview I/System.out: invalidate
09-07 14:11:50.467 13540-13540/com.example.myselfimageview I/System.out: setup6
09-07 14:11:50.467 13540-13540/com.example.myselfimageview I/System.out: onSizeChanged2
09-07 14:11:50.467 13540-13540/com.example.myselfimageview I/System.out: onLayout
09-07 14:11:50.474 13540-13573/com.example.myselfimageview E/GED: Failed to get GED Log Buf, err(0)
09-07 14:11:50.476 13540-13573/com.example.myselfimageview I/OpenGLRenderer: Initialized EGL, version 1.4
09-07 14:11:50.476 13540-13573/com.example.myselfimageview W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
09-07 14:11:50.480 13540-13573/com.example.myselfimageview I/OpenGLRenderer: Initializing program atlas...
09-07 14:11:50.495 13540-13540/com.example.myselfimageview I/System.out: onMeasure
09-07 14:11:50.495 13540-13540/com.example.myselfimageview I/System.out: onLayout
09-07 14:11:50.496 13540-13540/com.example.myselfimageview I/System.out: onDraw1
09-07 14:11:50.496 13540-13540/com.example.myselfimageview I/System.out: onDraw2
根据输出结果,一开始进入的是这个方法:
public CircleImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
System.out.println("CircleImageView2");
}
这里this(context, attrs, 0);
表示的是调用public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr){......}
这个方法。
public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
System.out.println("CircleImageView3");
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyleAttr, 0);
mBorderWidth = array.getDimensionPixelSize(R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH);
mBorderColor = array.getColor(R.styleable.CircleImageView_border_color, DEFAULT_BORDER_COLOR);
mBorderOverlay = array.getBoolean(R.styleable.CircleImageView_border_overlay, DEFAULT_BORDER_OVERLAY);
System.out.println("CircleImageView3.1");
array.recycle();
System.out.println("CircleImageView3.2");
init();
System.out.println("CircleImageView3.3");
}
运行到了init();
就进入了private void init(){.......};
方法:
private void init() {
System.out.println("init1");
super.setScaleType(SCALE_TYPE);
System.out.println("init2");
mReady = true;
if (mSetupPending) {
System.out.println("init+mSetupPending");
setup();
mSetupPending = false;
}
System.out.println("init3");
}
运行到super.setScaleType(SCALE_TYPE);
时,触发了invalidate
。紧接着往下运行,给mReady
赋值为true。但是因为mSetupPending
是false,所以没能进入if模块,而是直接结束init方法。
private void init(){.......};
方法运行 结束后,public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr){......}
该方法也结束了。然后回到public CircleImageView(Context context, AttributeSet attrs){......}
方法,结束本方法,然后触发了invalidate
方法 。
然后执行的是继承了ImageView
后重写的setImageBitmap
方法
@Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
System.out.println("setImageBitmap1");
mBitmap = bm;
System.out.println("setImageBitmap2");
setup();
System.out.println("setImageBitmap3");
}
可以看到setImageBitmap
内的方法执行到了setup
的时候,进入了setup
方法。
private void setup() {
System.out.println("setup1");
if (!mReady) {
System.out.println("mSetupPending = true;");
mSetupPending = true;
return;
}
System.out.println("setup2");
if (mBitmap == null) {
return;
}
System.out.println("setup3");
mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mBitmapPaint.setAntiAlias(true);
mBitmapPaint.setShader(mBitmapShader);
mBorderPaint.setStyle(Paint.Style.STROKE);
mBorderPaint.setAntiAlias(true);
mBorderPaint.setColor(mBorderColor);
mBorderPaint.setStrokeWidth(mBorderWidth);
mBitmapHeight = mBitmap.getHeight();
mBitmapWidth = mBitmap.getWidth();
mBorderRect.set(0, 0, getWidth(), getHeight());
mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2, ((mBorderRect.width() - mBorderWidth) / 2));
mDrawableRect.set(mBorderRect);
if (!mBorderOverlay) {
mDrawableRect.inset(mBorderWidth, mBorderWidth);
}
mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width() / 2);
System.out.println("setup4");
updateShaderMatrix();
System.out.println("setup5");
invalidate();
System.out.println("setup6");
}
在setup
方法执行到updateShaderMatrix();
时,又进入了updateShaderMatrix方法。
public void updateShaderMatrix() {
System.out.println("updateShaderMatrix1");
float scale;
float dx = 0;
float dy = 0;
mShaderMatrix.set(null);
if (mBitmapWidth * mDrawableRect.height() > mBitmapHeight * mDrawableRect.width()) {
scale = mDrawableRect.height() / (float) mBitmapHeight;
dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
} else {
scale = mDrawableRect.width() / (float) mBitmapWidth;
dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
}
System.out.println("mShaderMatrix.setScale(scale, scale)");
mShaderMatrix.setScale(scale, scale);
System.out.println("mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top)");
mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top);
System.out.println("mBitmapShader.setLocalMatrix(mShaderMatrix)");
mBitmapShader.setLocalMatrix(mShaderMatrix);
System.out.println("updateShaderMatrix2");
}
在整一个updateShaderMatrix
方法执行完后,回到setup
方法继续往下执行,触发了invalidate方法,然后结束setup
方法。然后回到setImageBitmap
方法,结束setImageBitmap
方法,然后进行onMeasure
方法。而后进入onSizeChanged
方法,调用了父类的super.onSizeChanged(w, h, oldw, oldh);
后,进入setup
方法。当执行到updateShaderMatrix();
时候,又进入了updateShaderMatrix();
方法。updateShaderMatrix();
整一个方法块运行结束后,回到setup
方法,结束setup
方法。然后回到onSizeChanged
方法,结束onSizeChanged
方法,进行onLayout
。
然后再进行一次onMeasure
和onLayout
验证,然后进行ondraw
。