在Android中绘制之前测量所有视图层次结构

Posted

技术标签:

【中文标题】在Android中绘制之前测量所有视图层次结构【英文标题】:Measure all view hierarchy before drawing in Android 【发布时间】:2012-07-11 05:54:46 【问题描述】:

我有下一个视图层次结构:

     <LinearLayout 
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_
        android:layout_
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:gravity="center">
        <LinearLayout 
            android:layout_
            android:layout_
            android:background="@drawable/group_bg"
            android:gravity="center_vertical" 
            android:baselineAligned="false">
            <LinearLayout
                android:id="@+id/itemplace"
                android:layout_
                android:layout_
                android:layout_marginRight="5dp"
                android:layout_weight="1" >
                <include
                    android:layout_
                    android:layout_
                    layout="@layout/pin" />
            </LinearLayout>
            <FrameLayout
                android:layout_
                android:layout_
                android:background="@drawable/arrow_black"/>
        </LinearLayout>
    </LinearLayout>

在绘制此层次结构之前,我需要获取 itemplace 宽度。我无法使用 OnLayoutChangeListener,因为我使用的是 API 级别 7。

我知道我必须使用 measure() 和 layout() 方法来计算视图的大小,但我不知道该怎么做。

我的层次结构中的根视图必须填满屏幕的所有宽度,因此 itemplace 宽度取决于父大小、父填充和 FrameLayout 宽度。

我必须怎么做才能让它变宽?

【问题讨论】:

当您尝试获取长度时,视图的宽度是否返回 0? 【参考方案1】:

我找到了获取视图宽度的方法。我可以在 android 测量它之后但在 ViewTreeObserver 中使用 OnPreDrawListener 绘制之前得到它:

    view.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener()
    
        @Override
        public boolean onPreDraw()
        
            int avaliableWidth = view.getWidth() - view.getPaddingLeft() - view.getPaddingRight();

            Log.d("width", String.valueOf(avaliableWidth));

            return true;
        
    );

来自 Android 文档:

即将绘制视图树时调用的回调方法。 此时,树中的所有视图都已被测量并给出了一个 框架。客户可以使用它来调整他们的滚动边界,甚至 在绘制之前请求一个新的布局。

【讨论】:

但我也希望能够使用 measure() 和 layout() 方法自行计算视图宽度。怎么办?【参考方案2】:

这从 API 1 开始可用:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
    int parentHeight = MeasureSpec.getSize(heightMeasureSpec);

【讨论】:

我无法更改视图类。我只有从 LayoutInflater 返回的 View 对象。 好吧,你有 View view = ... 并且你需要 view 的 witdh 吗? 当宽度返回0时你使用什么方法? 顶部帖子的视图层次结构我从 LayoutInflater 膨胀并获取 View 对象。我知道,那就是视图必须填满所有屏幕宽度。这就是我所拥有的一切。在绘制层次结构之前,我需要从层次结构中获取一个视图的宽度。这就是全部任务。我已经找到了一种方法——使用 OnPreDrawListener。但是,如果我知道像 Android 那样使用 measure() 和 layout() 获取视图宽度的其他方法,那就太好了。 首先我尝试调用 measure(MeasureSpec.EXACTLY, MeasureSpec.EXACTLY);然后我调用 layout(0, 0, screenWidth, 100); Android文档说,使用这两种方法Android在绘制之前计算视图的宽度和高度。但是使用这个方法后,view.getMeasuredWidth() 返回 0。

以上是关于在Android中绘制之前测量所有视图层次结构的主要内容,如果未能解决你的问题,请参考以下文章

[译]Android view 测量布局和绘制的流程

Android - 任何Activity的根视图层次结构中存在的所有视图的相对路径生成器

测量在 UIViewController 及其所有子视图中绘制视图需要多长时间

iOS 视图与视图层次结构(内容根据iOS编程)

如何将视图层次结构和内容输出到文件?

android view的 绘制流程