8

我有 android 布局设计,其中我有一个AppBar布局,其中包含一个Toolbar和一个LinearLayout带有圆形Drawable的设计TextView。这是相同的高度。因此,当我尝试获取ToolbarAppBar高度/宽度时,它只返回 0。

活动主.xml:

    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?actionBarSize"
            android:background="@color/colorPrimary"
            app:layout_scrollFlags="enterAlways" />
       <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="?actionBarSize"
            android:layout_gravity="center_horizontal"
            android:background="@color/colorPrimary"
            android:orientation="horizontal"
            app:layout_scrollFlags="enterAlways">

            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_gravity="center_horizontal"
                android:layout_marginLeft="2dp"
                android:layout_weight="1"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/marked_questions"
                    style="@style/textview_summary_omr_toolbar_count"
                    android:background="@drawable/bg_percentage_default"
                    android:text="18" />

                <TextView
                    style="@style/textview_heading_summary_omr_toolbar"
                    android:text="Marked" />
            </LinearLayout>

            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_gravity="center_horizontal"
                android:layout_marginLeft="2dp"
                android:layout_weight="1"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/correct"
                    style="@style/textview_summary_omr_toolbar_count"
                    android:background="@drawable/bg_percentage_6"
                    android:text="18"

                    />

                <TextView
                    style="@style/textview_heading_summary_omr_toolbar"
                    android:text="Correct" />
            </LinearLayout>

            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_gravity="center_horizontal"
                android:layout_marginLeft="2dp"
                android:layout_weight="1"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/wrong"
                    style="@style/textview_summary_omr_toolbar_count"
                    android:background="@drawable/bg_percentage_wrong"
                    android:text="18" />

                <TextView
                    style="@style/textview_heading_summary_omr_toolbar"
                    android:text="Wrong" />
            </LinearLayout>


            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_gravity="center_horizontal"
                android:layout_marginLeft="2dp"
                android:layout_weight="1"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/conflicts"
                    style="@style/textview_summary_omr_toolbar_count"
                    android:background="@drawable/bg_percentage_3"
                    android:text="0" />

                <TextView
                    style="@style/textview_heading_summary_omr_toolbar"
                    android:text="Conflicts" />
            </LinearLayout>

            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_gravity="center_horizontal"
                android:layout_marginLeft="2dp"
                android:layout_weight="1"
                android:orientation="horizontal">

                <TextView
                    style="@style/textview_summary_omr_toolbar_count"
                    android:text="Score:"
                    android:textColor="@android:color/white" />

                <TextView
                    android:id="@+id/marks_scored"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:gravity="center"
                    android:text="18/30"
                    android:textColor="@android:color/white"
                    android:textSize="18sp" />

            </LinearLayout>


        </LinearLayout>
    </android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>

MainActivity.java: 在这里我正在初始化ToolbarandAppBar并尝试在日志中打印两者的宽度和高度,这使我返回零。

public class MainActivity extends AppCompatActivity {
  private Toolbar toolbar;
  private AppBarLayout app_bar;
protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       app_bar = (AppBarLayout) findViewById(R.id.app_bar);
       toolbar = (Toolbar) findViewById(R.id.toolbar);
       logToolbarLayoutParams();

}
private void logToolbarLayoutParams() {
        Log.d(TAG,"Toolbar width/Height"+this.toolbar.getWidth()+"/"+this.toolbar.getHeight());
        Log.d(TAG,"App_bar width/height"+this.app_bar.getWidth()+"/"+this.app_bar.getHeight());

}

我还在stackoverflow中提到了这个问题。

final AppBarLayout app_bar = (AppBarLayout) findViewById(R.id.app_bar);
                ViewTreeObserver vto = app_bar.getViewTreeObserver();
                vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                        app_bar.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                        Log.d(TAG, "Global layout");
                        logToolbarLayoutParams();
            }
        });

如果我在其中添加以下代码,MainActivity它将使我得到正确的高度和宽度Toolbar。从我之前提到的stackoverflow问题中,我了解到,视图没有绘制在屏幕上,所以我必须等待。但我的疑问是,我指定的设计不是一个复杂的设计?为什么要花很多时间在屏幕上绘制?我错过了什么吗?

我已经使用 Hierarchy Viewer 来找出导致子布局加载缓慢的原因。我发现我正在使用多重LinearLayout,其中单一RelativeLayout可用于获得相同的结构。我已将布局设计更改如下。我仍然面临同样的问题。

更新:activity_main.xml:

<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?actionBarSize"
            android:background="@color/colorPrimary"
            app:layout_scrollFlags="enterAlways" />
   <RelativeLayout
         android:id="@+id/summary_bottom_sheet"
         android:layout_width="match_parent"
         android:layout_height="?actionBarSize"
         android:layout_gravity="center_horizontal"
         android:background="@color/colorPrimary">


         <TextView
             android:id="@+id/marked_questions"
             style="@style/textview_summary_omr_toolbar_count"
             android:layout_alignParentLeft="true"
             android:layout_alignParentStart="true"
             android:background="@drawable/bg_percentage_default"
             android:text="18" />

         <TextView
             android:id="@+id/marked_textview"
             style="@style/textview_heading_summary_omr_toolbar"
             android:layout_toEndOf="@+id/marked_questions"
             android:layout_toRightOf="@+id/marked_questions"
             android:text="Marked" />


         <TextView
             android:id="@+id/correct"
             style="@style/textview_summary_omr_toolbar_count"
             android:layout_toEndOf="@+id/marked_textview"
             android:layout_toRightOf="@+id/marked_textview"
             android:background="@drawable/bg_percentage_6"
             android:text="18"

             />

         <TextView
             android:id="@+id/correct_textview"
             style="@style/textview_heading_summary_omr_toolbar"
             android:layout_toEndOf="@+id/correct"
             android:layout_toRightOf="@+id/correct"
             android:text="Correct" />


         <TextView
             android:id="@+id/wrong"
             style="@style/textview_summary_omr_toolbar_count"
             android:layout_toEndOf="@+id/correct_textview"
             android:layout_toRightOf="@+id/correct_textview"
             android:background="@drawable/bg_percentage_wrong"
             android:text="18" />

         <TextView
             android:id="@+id/wrong_textview"
             style="@style/textview_heading_summary_omr_toolbar"
             android:layout_toEndOf="@+id/wrong"
             android:layout_toRightOf="@+id/wrong"
             android:text="Wrong" />


         <TextView
             android:id="@+id/conflicts"
             style="@style/textview_summary_omr_toolbar_count"
             android:layout_toEndOf="@+id/wrong_textview"
             android:layout_toRightOf="@+id/wrong_textview"
             android:background="@drawable/bg_percentage_3"
             android:text="0" />

         <TextView
             android:id="@+id/conflicts_textview"
             style="@style/textview_heading_summary_omr_toolbar"
             android:layout_toEndOf="@+id/conflicts"
             android:layout_toRightOf="@+id/conflicts"
             android:text="Conflicts" />


         <TextView
             android:id="@+id/score_textview"
             style="@style/textview_summary_omr_toolbar_count"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_toEndOf="@+id/conflicts_textview"
             android:layout_toRightOf="@+id/conflicts_textview"
             android:background="@null"
             android:gravity="center"
             android:text="Score:"
             android:textColor="@android:color/white" />

         <TextView
             android:id="@+id/marks_scored"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_centerVertical="true"
             android:layout_gravity="center_vertical"
             android:layout_toEndOf="@+id/score_textview"
             android:layout_toRightOf="@+id/score_textview"
             android:gravity="center"
             android:text="18/30"
             android:textColor="@android:color/white"
             android:textSize="18sp" />
   </RelativeLayout>
 </android.support.design.widget.AppBarLayout>
 </android.support.design.widget.CoordinatorLayout>

以下是Hierarchy_viewer我正在获取的层次结构查看器图像

4

5 回答 5

3

你在想这个错误。您的布局没有任何问题(因为它与您的问题有关)。为了证明这一点,完全改变你的布局,然后再试一次

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recyclerView);
    Log.d("SomeTag", "w: " + recyclerView.getWidth() + ", h: " + recyclerView.getHeight());
    Log.d("SomeTag", "mw: " + recyclerView.getMeasuredWidth() + ", mh: " + recyclerView.getMeasuredHeight());
}

只有 1 个孩子的视图的输出仍然是

12-14 10:17:04.902 3004-3004/? D/SomeTag:w:0,h:0

12-14 10:17:04.902 3004-3004/? D/SomeTag:mw:0,mh:0

因此,您的布局没有任何问题(除非您确实用词不当。您调用了 logToolbarLayoutParams 方法,但您根本没有访问布局参数。您试图在布局传递发生之前获取视图对象的属性.也许这是你的困惑)。所以你缺少的是对 Android 的布局系统、视图组和视图的理解。Romain Guy 在 Devoxx 上有一次关于如何构建自定义 FlowLayout 的非常酷的演讲。网站已关闭或视频已被拉取,但这是 GitHub 中的代码如果您查看 onLayout 方法,您可以看到 ViewGroup 循环遍历它的所有子项并调用 child.layout()。在调用此方法之前,view.getWidth 和 view.getHeight 方法将返回 0。并且该方法由操作系统在调度时调用。所以基本上,您甚至在操作系统安排布局之前就试图立即访问宽度和高度。自己创建一个自定义视图组,添加一些断点,然后试一试。

于 2016-12-14T18:29:33.960 回答
1

toolbar.getWidth()测量布局会告诉你视图的宽度。 膨胀视图后,它的宽度和高度将始终是因为 a和 a都没有发生。
0measure()layout()

protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);
   toolbar = (Toolbar) findViewById(R.id.toolbar);

   // check after inflation -> will be 0
   logToolbarLayoutParams();
}

onGlobalLayout()报告正确的数据,因为——顾名思义——两者onMeasure() onLayout()被调用。视图的尺寸是已知的。这并不意味着视图已被绘制onDraw()是第三步,也是最后一步。

它也不会影响您的布局的复杂程度或您使用的视图。测量和布局通道不会在视图膨胀后立即发生。


要获得并使用正确的视图尺寸,您有 3 个选项:

  1. ViewTreeObserver.OnGlobalLayoutListener#onGlobalLayout()像你已经建议的那样使用
  2. 稍后检查大小,当您可以确定视图已被绘制时(例如,在用户交互时,在 中OnClickListener
  3. 去定制并创建自己的View. 在那里,您有机会处理所有onMeasure,onLayout和您onDraw自己!
于 2016-12-14T21:37:10.477 回答
0

绘图视图需要相当长的时间,但我们可以通过删除嵌套布局来减少,并通过使用相对布局或约束布局使视图层次结构平坦。

找到透支。从设置中选择“调试 GPU 过度绘制开发人员选项”中的“显示过度绘制区域”。

研究developer.android 上关于优化布局主题的这篇这篇重要文章

于 2016-12-14T11:20:03.207 回答
-1

我刚刚在同一案例中解决了同样的问题。所有ViewTreeObserver.OnGlobalLayoutListener()看起来很脏的解决方案都不适合我。在当前屏幕上了解宽度和高度的最简单方法如下所示:

toolbar.post(new Runnable() {
        @Override
        public void run() {
            int headerWidth = toolbar.getWidth();
            int headerHeight = toolbar.getHeight();
            // do whatever you want ...
        }
    });

view.post()将在视图的消息队列最后添加您的代码,此时所有大小都已计算完毕。恕我直言,那显然更容易理解OnGlobalLayoutListener()。希望它会帮助你。

无论如何,这个解决方案只是“延迟获取大小”,比如OnGlobalLayoutListener(). 但这是系统的正常行为,在屏幕上绘制视图需要一些时间。最好的方法是不要期望计算尺寸 - 相反,您应该协调 .xml 文件中视图之间的所有关系。属性喜欢WRAP_CONTENT并且MATCH_PARENT是解决此类问题的最简单方法

于 2016-12-14T11:10:22.217 回答
-2

您尝试在将视图附加到屏幕之前获取视图的宽度和高度您可以在 onAttach 方法中创建自定义视图和所需的 wath

于 2016-12-08T17:08:45.490 回答