Android开发杂记Android编程开发

记录一次Android自定义View的难忘教训

2020-07-15  本文已影响0人  浅吟且行的时光

一个倒计时控件:CountView extend JustifyTextView extend ImageView,CountView倒计时触发后,调用JustifyTextView中的方法setText(String text);使用invalidate(),进行重绘,而不是使用TextView setText(),调用requestLayout进行重绘,原因是:requestLayout()方法会一层一层调用父布局的:requestLayout()(会导致父布局重新进行测量、布局和绘制流程,这样会影响某些View不能正常显示:例如滑动显示菜单,布局变动时会自动关闭菜单显示,这不是我想要的结果),而invalidate()只针对当前变动的View进行重绘

主要问题:第一个方法会不断调用,第一次调用后会调用onDraw方法,但是UI上没显示画的结果,并且随后再也不调用onDraw方法

//JustifyTextView.java 一秒调用一次
public void setText(String text) {
        this.text = text;
        invalidate();
    }

//正常情况下每次调用invalidate();会调用下面的方法
@Override
protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (paint == null){
            initPaint();
        }
        Paint.FontMetrics fm = paint.getFontMetrics();
        float baseline = fm.descent - fm.ascent;

        canvas.drawText(text, desiredWidth/2, baseline, paint);
}

分析问题可能产生的原因:

requestLayout();
((View)getParent()).invalidate();
 forceLayout();
canvas.drawText(text, x, y, paint);
android:layout_width="wrap_content"
android:layout_height="wrap_content"
# 改为
android:layout_width="100dp"
android:layout_height="100dp"

最后

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        int width;
        int height;

        //Measure Width
        if (widthMode == MeasureSpec.EXACTLY) {
            //Must be this size
            width = widthSize;
        } else if (widthMode == MeasureSpec.AT_MOST) {
            //Can't be bigger than...
            width = Math.min(desiredWidth, widthSize);
        } else {
            //Be whatever you want
            width = desiredWidth;
        }

        //Measure Height
        if (heightMode == MeasureSpec.EXACTLY) {
            //Must be this size
            height = heightSize;
        } else if (heightMode == MeasureSpec.AT_MOST) {
            //Can't be bigger than...
            height = Math.min(desiredHeight, heightSize);
        } else {
            //Be whatever you want
            height = desiredHeight;
        }

        //MUST CALL THIS
        setMeasuredDimension(width, height);
    }
感悟:View绘制异常时,后面不会再调用:onDraw;没能静下心来,抓问题的主要矛盾,分析产生问题的主要原因,导致做了许多无用的尝试,浪费了将近一天时间!
上一篇下一篇

猜你喜欢

热点阅读