Child Views 花太多时间在屏幕上画画
Child Views Taking too much time to draw on screen
我有 android 布局设计,其中我有一个 AppBar
布局,其中将包含一个 Toolbar
和另一个 LinearLayout
带圆圈的设计 Drawable
作为 TextView
。这是相同的高度。因此,当我尝试获取 Toolbar
或 AppBar
height/width 时,它只返回 0。
activity_main.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:
在这里,我正在初始化 Toolbar
和 AppBar
并尝试在日志中打印两者的宽度和高度,这让我返回零。
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());
}
我在 Whosebug 中也提到了这个问题。
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
的正确高度和宽度。从我之前提到的Whosebug问题,我知道,视图没有绘制在屏幕上,所以我必须等待。但我的疑问是,我指定的设计不是一个复杂的设计吗?
为什么在屏幕上画画要花很多时间?我错过了什么吗?
我已经使用 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>
下面是层级查看器我正在获取的图片
您尝试在将视图附加到屏幕之前获取其宽度和高度
您可以在 onAttach 方法中创建自定义视图和 wath
我刚刚在同一个案例中解决了同样的问题。 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()
。
希望对你有所帮助。
无论如何,这个解决方案只是 "delayed getting sizes",就像 OnGlobalLayoutListener()
。但这是系统的正常行为,在屏幕上绘制视图需要一些时间。最好的方法是不要期望计算尺寸 - 相反,您应该协调 .xml 文件中视图之间的所有关系。 WRAP_CONTENT
和 MATCH_PARENT
等属性是解决此类问题的最简单方法
绘制视图需要相当长的时间,但我们可以通过删除嵌套布局来减少时间,并通过使用 RelativeLayout 或 Constrain 布局使视图层次结构平坦。
寻找透支。 Select "Show overdraw areas" 在设置中的调试 GPU 透支开发者选项中。
你想错了。您的布局没有任何问题(因为它与您的问题有关)。为了证明这一点,彻底改变你的布局再试一次
@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 个 child 的视图的输出仍然是
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,但你根本没有访问布局参数。你试图获取视图的属性 object 在布局传递发生之前。也许这是你的困惑)。所以你缺少的是对 Android 的布局系统、视图组和视图的理解。 Romain Guy 曾在 Devoxx 上就如何构建自定义 FlowLayout 进行了一场非常酷的演讲。网站已关闭或视频已被拉出,但 here's the code in GitHub 如果您查看 onLayout 方法,您可以看到 ViewGroup 循环遍历所有 children 并调用 child.layout() .在调用此方法之前,view.getWidth 和 view.getHeight 方法将 return 0。并且 OS 在调度它时调用此方法。所以基本上,您甚至在 OS 安排布局之前就试图立即访问宽度和高度。自己做一个自定义视图组,添加一些断点,试一试。
toolbar.getWidth()
会告诉你视图的宽度 它已经 测量 和 铺设出.
在膨胀视图后,它的宽度和高度将始终为 0
,因为 measure()
和 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()
是第三步,也是 最后 步。
它也不会影响您的布局的复杂程度或您使用的视图。测量和布局过程不会在视图 inflation 之后立即发生。
要获取和使用正确的视图尺寸,您有 3 个选项:
- 像您已经建议的那样使用
ViewTreeObserver.OnGlobalLayoutListener#onGlobalLayout()
- 稍后检查大小,当您可以确定视图已绘制时,(例如,在用户交互时,在
OnClickListener
中)
- 自定义并创建您自己的
View
。您将有机会自己处理所有 onMeasure
、onLayout
和 onDraw
!
我有 android 布局设计,其中我有一个 AppBar
布局,其中将包含一个 Toolbar
和另一个 LinearLayout
带圆圈的设计 Drawable
作为 TextView
。这是相同的高度。因此,当我尝试获取 Toolbar
或 AppBar
height/width 时,它只返回 0。
activity_main.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:
在这里,我正在初始化 Toolbar
和 AppBar
并尝试在日志中打印两者的宽度和高度,这让我返回零。
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());
}
我在 Whosebug 中也提到了这个问题。
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
的正确高度和宽度。从我之前提到的Whosebug问题,我知道,视图没有绘制在屏幕上,所以我必须等待。但我的疑问是,我指定的设计不是一个复杂的设计吗?
为什么在屏幕上画画要花很多时间?我错过了什么吗?
我已经使用 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>
下面是层级查看器
您尝试在将视图附加到屏幕之前获取其宽度和高度 您可以在 onAttach 方法中创建自定义视图和 wath
我刚刚在同一个案例中解决了同样的问题。 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()
。
希望对你有所帮助。
无论如何,这个解决方案只是 "delayed getting sizes",就像 OnGlobalLayoutListener()
。但这是系统的正常行为,在屏幕上绘制视图需要一些时间。最好的方法是不要期望计算尺寸 - 相反,您应该协调 .xml 文件中视图之间的所有关系。 WRAP_CONTENT
和 MATCH_PARENT
等属性是解决此类问题的最简单方法
绘制视图需要相当长的时间,但我们可以通过删除嵌套布局来减少时间,并通过使用 RelativeLayout 或 Constrain 布局使视图层次结构平坦。
寻找透支。 Select "Show overdraw areas" 在设置中的调试 GPU 透支开发者选项中。
你想错了。您的布局没有任何问题(因为它与您的问题有关)。为了证明这一点,彻底改变你的布局再试一次
@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 个 child 的视图的输出仍然是
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,但你根本没有访问布局参数。你试图获取视图的属性 object 在布局传递发生之前。也许这是你的困惑)。所以你缺少的是对 Android 的布局系统、视图组和视图的理解。 Romain Guy 曾在 Devoxx 上就如何构建自定义 FlowLayout 进行了一场非常酷的演讲。网站已关闭或视频已被拉出,但 here's the code in GitHub 如果您查看 onLayout 方法,您可以看到 ViewGroup 循环遍历所有 children 并调用 child.layout() .在调用此方法之前,view.getWidth 和 view.getHeight 方法将 return 0。并且 OS 在调度它时调用此方法。所以基本上,您甚至在 OS 安排布局之前就试图立即访问宽度和高度。自己做一个自定义视图组,添加一些断点,试一试。
toolbar.getWidth()
会告诉你视图的宽度 它已经 测量 和 铺设出.
在膨胀视图后,它的宽度和高度将始终为 0
,因为 measure()
和 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()
是第三步,也是 最后 步。
它也不会影响您的布局的复杂程度或您使用的视图。测量和布局过程不会在视图 inflation 之后立即发生。
要获取和使用正确的视图尺寸,您有 3 个选项:
- 像您已经建议的那样使用
ViewTreeObserver.OnGlobalLayoutListener#onGlobalLayout()
- 稍后检查大小,当您可以确定视图已绘制时,(例如,在用户交互时,在
OnClickListener
中) - 自定义并创建您自己的
View
。您将有机会自己处理所有onMeasure
、onLayout
和onDraw
!