【问题标题】:Calling TextView.setText() redraws entire screen in spite of view hierarchy尽管视图层次结构不同,但调用 TextView.setText() 会重绘整个屏幕
【发布时间】:2014-03-12 04:27:16
【问题描述】:

在我的应用程序中,我有一个每秒更新的时间显示。每次用于秒字段的 TextView 更改时,开发人员选项->显示表面更新工具都会闪烁整个屏幕。我环顾四周,真的只能找到this question,这很好地说明了没有办法阻止 TextView 导致至少部分窗口重新布局。所以我确定要验证我的 TextView 是否包装在它们自己的容器中,但我仍然遇到同样的问题。每次调用 setText() 都会导致整个视图闪烁。

我的层次结构如下:

  • 片段
    • RelativeLayout(片段根视图)
      • 线性布局
        • 相对布局
          • 我的时间文本视图
      • 其他各种很少更改的视图组件

如果可能,我想解决这个问题。如果可能的话,我确实需要尝试减少我的观看次数,并且我计划继续努力,但这仍然是我想从应用中删除的问题。

【问题讨论】:

    标签: android android-layout textview


    【解决方案1】:

    当硬件加速开启时,显示表面更新会在整个屏幕上闪烁,但这并不意味着整个窗口都已重绘。您可以使用另一个选项来准确显示在硬件加速开启时屏幕的哪一部分被重绘(“显示 GPU 视图更新”)。

    【讨论】:

    • 好的,这更有意义,谢谢。现在我只需要减少查看次数。
    【解决方案2】:

    我遇到了一个类似的问题,我正在更新一个导致每次测量都通过的计时器。如果你有一些测量起来很昂贵的东西,比如 ListView,它会影响性能。就我而言,我有一个 ListView,它在计时器更新时不需要更改大小,所以我制作了一个自定义 ListView 持有者来阻止度量级联到 ListView。现在运行顺利!

    public class CustomListviewHolderLayout extends FrameLayout {
    
        public int currentWidth = 0;
        public int currentHeight = 0;
    
        public CustomListviewHolderLayout(Context context) {
            super(context);
        }
    
        public CustomListviewHolderLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public CustomListviewHolderLayout(Context context, AttributeSet attrs,
                int defStyle) {
            super(context, attrs, defStyle);
        }
    
        @Override
        protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
            //Debug Prints
            String wMode = "";
            switch(MeasureSpec.getMode(widthMeasureSpec)){
                case MeasureSpec.AT_MOST:
                    wMode = "AT_MOST"; break;
                case MeasureSpec.EXACTLY:
                    wMode = "EXACTLY"; break;
                case MeasureSpec.UNSPECIFIED:
                    wMode = "UNSPECIFIED"; break;
                default:
                    wMode = "";
            }
            String hMode = "";
            switch(MeasureSpec.getMode(heightMeasureSpec)){
                case MeasureSpec.AT_MOST:
                    hMode = "AT_MOST"; break;
                case MeasureSpec.EXACTLY:
                    hMode = "EXACTLY"; break;
                case MeasureSpec.UNSPECIFIED:
                    hMode = "UNSPECIFIED"; break;
                default:
                    hMode = "";
            }
            Log.i("RandomCustomListViewHolder", "wMode = " + wMode + ", size = " + MeasureSpec.getSize(widthMeasureSpec));
            Log.i("RandomCustomListViewHolder", "hMode = " + hMode + ", size = " + MeasureSpec.getSize(heightMeasureSpec));
            //only remeasure child listview when the size changes (e.g. orientation change)
            if(getChildCount() == 1){
                if(((MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) ||
                    (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.AT_MOST))
                  &&((MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) ||
                    (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST))){
                    //check if height dimensions are different than before
                    int newWidth =  MeasureSpec.getSize(widthMeasureSpec);
                    int newHeight = MeasureSpec.getSize(heightMeasureSpec);
                    if((newWidth != currentWidth) || (newHeight != currentHeight)){
                        //remeasure if different
                        Log.i("RandomCustomListViewHolder", "measuring listView");
                        View childView = getChildAt(0);
                        childView.measure(widthMeasureSpec, heightMeasureSpec);
                        currentWidth = newWidth;
                        currentHeight = newHeight;
                        this.setMeasuredDimension(newWidth, newHeight);
                    } else {
                        //still set this view's measured dimension
                        this.setMeasuredDimension(newWidth, newHeight);     
                    }               
                } else {
                    //Specify match parent if one of the dimensions is unspecified
                    this.setMeasuredDimension(ViewGroup.LayoutParams.MATCH_PARENT,
                            ViewGroup.LayoutParams.MATCH_PARENT);                   
                }
            } else {
                //view does not have the listview child, measure normally 
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);           
                currentWidth = 0;
                currentHeight = 0;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-23
      • 2021-05-31
      • 2011-04-08
      • 1970-01-01
      • 2017-07-11
      • 1970-01-01
      • 2018-09-14
      • 1970-01-01
      相关资源
      最近更新 更多