美文网首页Android开发杂记Android编程开发
记录一次Android自定义View的难忘教训

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

作者: 浅吟且行的时光 | 来源:发表于2020-07-15 14:26 被阅读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);
    }
    

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

    • onDraw没调用是因为 invalidate(),调用不对?换做下面几个方法都不行,看来不是这个问题
    requestLayout();
    ((View)getParent()).invalidate();
     forceLayout();
    
    • 尝试在子View(CountView)中进行绘制,仍然只绘制一次
    • 对ImageView设置背景,仍然无果
    • 对View绘制的起始坐标进行多次设置尝试,仍然不行
    canvas.drawText(text, x, y, paint);
    
    • 改变xml布局中控件的wrap_content为指定宽高,终于显示出来
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    # 改为
    android:layout_width="100dp"
    android:layout_height="100dp"
    

    最后

    • 通过重新实现onMeasure方法(xml中仍然采用wrap_content),动态设置View的宽高,达到正常显示的效果
     @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;没能静下心来,抓问题的主要矛盾,分析产生问题的主要原因,导致做了许多无用的尝试,浪费了将近一天时间!

    相关文章

      网友评论

        本文标题:记录一次Android自定义View的难忘教训

        本文链接:https://www.haomeiwen.com/subject/isbdhktx.html