android - 为什么viewgroup invalidate,他的子view没有回调draw方法

 他w与他说 发布于 2022-10-28 10:33

我自定义了一个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) {

            }
        });
    }
}
1 个回答
  • 你在初始化自定义布局的时候添加上setWillNotDraw(false)试试看。

    2022-11-12 01:45 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有