我写了这个答案,因为即使在浏览了几个 StackOverflow 页面后,我也无法清楚地理解 attachToRoot 的含义。下面是 LayoutInflater 类中的 inflate() 方法。
View inflate (int resource, ViewGroup root, boolean attachToRoot)
看看我创建的 activity_main.xml 文件、button.xml 布局和 MainActivity.java 文件。
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
button.xml
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LayoutInflater inflater = getLayoutInflater();
LinearLayout root = (LinearLayout) findViewById(R.id.root);
View view = inflater.inflate(R.layout.button, root, false);
}
当我们运行代码时,我们不会在布局中看到按钮。这是因为我们的按钮布局没有添加到主活动布局中,因为 attachToRoot 设置为 false。
LinearLayout 有一个 addView(View view) 方法,可用于将 View 添加到 LinearLayout。这会将按钮布局添加到主活动布局中,并在您运行代码时使按钮可见。
root.addView(view);
让我们删除上一行,看看当我们将 attachToRoot 设置为 true 时会发生什么。
View view = inflater.inflate(R.layout.button, root, true);
我们再次看到按钮布局是可见的。这是因为 attachToRoot 直接将膨胀的布局附加到指定的父级。在这种情况下是根 LinearLayout。在这里,我们不必像之前使用 addView(View view) 方法那样手动添加视图。
为什么人们在将片段的 attachToRoot 设置为 true 时会收到 IllegalStateException。
这是因为对于片段,您已经指定了在活动文件中放置片段布局的位置。
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.add(R.id.root, fragment)
.commit();
add(int parent, Fragment fragment) 将具有其布局的片段添加到父布局。如果我们将 attachToRoot 设置为 true,您将得到 IllegalStateException: The specified child has a parent。由于片段布局已经在 add() 方法中添加到父布局中。
在对 Fragment 进行膨胀时,您应该始终为 attachToRoot 传递 false。添加、删除和替换 Fragment 是 FragmentManager 的工作。
回到我的例子。如果我们两者都做呢。
View view = inflater.inflate(R.layout.button, root, true);
root.addView(view);
在第一行中,LayoutInflater 将按钮布局附加到根布局并返回一个包含相同按钮布局的 View 对象。在第二行中,我们将相同的 View 对象添加到父根布局。这会导致我们在 Fragments 中看到的相同的 IllegalStateException(指定的子级已经有父级)。
请记住,还有另一个重载的 inflate() 方法,它默认将 attachToRoot 设置为 true。
View inflate (int resource, ViewGroup root)