我自定义了一个viewgroup(FloatBorderLayout),里面放置了几个ImageView,然后在viewgroup内部invalidate(),那么应该会进入viewrootimpl执行performTraversal方法遍历view树对吧,那么viewgroup内所有的ImageView都会重新走一遍绘制流程,事实上并没有,viewgroup内部Imageview内容,大小,布局都没变,所以都不会执行吗?如果我重写viewgroup的ondraw方法,在canvas上绘制图形,每一次调用invalidate之前的图形都会被擦除,难道canvas每次invalidate都会重新创建吗,如果是的话,为什么Imageview的绘制流程方法都没有回调,很困惑,希望有人解答一下。
一句话:为什么viewgroup invalidate后所有ImageView都没有回调measure,layout,draw方法,canvas上的绘制的圆角框却改变了?
public class FloatBorderLayout extends RelativeLayout implements View.OnFocusChangeListener, View.OnClickListener {
private Paint mPaint;
private RectF mRectF;
private RectF oRectF;
private boolean isInit;
public FloatBorderLayout(Context context) {
this(context, null);
}
public FloatBorderLayout(Context context, AttributeSet attr) {
this(context, attr, 0);
}
public FloatBorderLayout(Context context, AttributeSet attr, int style) {
super(context, attr, style);
initBorderView();
}
private void initBorderView() {
setClickable(false);
setClipChildren(false);
oRectF = new RectF();
mRectF = new RectF();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStrokeWidth(3);
mPaint.setStyle(Paint.Style.STROKE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRoundRect(mRectF, 10, 10, mPaint);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
if (!isInit) {
isInit = !isInit;
for (int i = 0; i < getChildCount(); i++) {
getChildAt(i).setOnClickListener(this);
getChildAt(i).setOnFocusChangeListener(this);
}
}
}
@Override
public void onFocusChange(View view, boolean hasFocus) {
if (hasFocus) {
borderFly(getLocation(view, 1.2f, 1.2f), view);
imgScaleAnim(1.0f, 1.2f, 1.0f, 1.2f, 100, view);
} else {
imgScaleAnim(1.2f, 1.0f, 1.2f, 1.0f, 100, view);
}
}
private RectF getLocation(View view, float xScale, float yScale) {
RectF rectF = new RectF();
float left = view.getLeft();
float top = view.getTop();
float right = view.getRight();
float bottom = view.getBottom();
float oWidth = right - left;
float oHeight = bottom - top;
float deltaX = oWidth * (xScale - 1) / 2;
float deltaY = oHeight * (yScale - 1) / 2;
rectF.left = view.getLeft() - deltaX - 1;
rectF.top = view.getTop() - deltaY - 1;
rectF.right = view.getRight() + deltaX + 1;
rectF.bottom = view.getBottom() + deltaY + 1;
return rectF;
}
public void imgScaleAnim(float fromXscale, float toXscale, float fromYscale, float toYscale, long duration, View v) {
ScaleAnimation scaleAnimation = new ScaleAnimation(fromXscale, toXscale, fromYscale, toYscale,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnimation.setInterpolator(new AccelerateInterpolator());
scaleAnimation.setFillAfter(true);
scaleAnimation.setDuration(duration);
v.startAnimation(scaleAnimation);
}
public void borderFly(final RectF rect, final View view) {
switch (view.getId()) {
case R.id.category_movie:
mPaint.setColor(0xfffec96a);
break;
case R.id.category_music:
mPaint.setColor(0xffffa1b9);
break;
case R.id.category_game:
mPaint.setColor(0xffc8a5fd);
break;
case R.id.category_icontrol:
mPaint.setColor(0xffa0dbff);
break;
case R.id.category_setting:
mPaint.setColor(0xff93ffc2);
break;
}
valueAnimator = ValueAnimator.ofObject(new TypeEvaluator() {
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
RectF startRF = (RectF) startValue;
RectF endRF = (RectF) endValue;
float left = startRF.left + fraction * (endRF.left - startRF.left);
float right = startRF.right + fraction * (endRF.right - startRF.right);
float top = startRF.top + fraction * (endRF.top - startRF.top);
float bottom = startRF.bottom + fraction * (endRF.bottom - startRF.bottom);
return new RectF(left, top, right, bottom);
}
}, oRectF, rect);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mRectF = (RectF) animation.getAnimatedValue();
invalidate();
}
});
valueAnimator.setDuration(300);
valueAnimator.start();
valueAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
oRectF = mRectF;
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
}
}
Add it when initializing the custom layout
setWillNotDraw(false)
Try it out.