Escrevi esta resposta porque, mesmo depois de passar por várias páginas do StackOverflow, não consegui entender claramente o significado de attachToRoot. Abaixo está o método inflate () na classe LayoutInflater.
View inflate (int resource, ViewGroup root, boolean attachToRoot)
Dê uma olhada no arquivo activity_main.xml , no layout button.xml e no arquivo MainActivity.java que criei.
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);
}
Quando executamos o código, não vemos o botão no layout. Isso ocorre porque o layout do nosso botão não é adicionado ao layout principal da atividade, pois o attachToRoot está definido como false.
O LinearLayout possui um método addView (exibição de exibição) que pode ser usado para adicionar Views ao LinearLayout. Isso adicionará o layout do botão ao layout principal da atividade e tornará o botão visível quando você executar o código.
root.addView(view);
Vamos remover a linha anterior e ver o que acontece quando configuramos attachToRoot como true.
View view = inflater.inflate(R.layout.button, root, true);
Mais uma vez, vemos que o layout do botão é visível. Isso ocorre porque attachToRoot anexa diretamente o layout inflado ao pai especificado. Que neste caso é LinearLayout raiz. Aqui, não precisamos adicionar as visualizações manualmente, como fizemos no caso anterior, com o método addView (View view).
Por que as pessoas estão obtendo IllegalStateException ao definir attachToRoot como true para um Fragmento.
Isso ocorre porque, para um fragmento, você já especificou onde colocar seu layout de fragmento em seu arquivo de atividade.
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.add(R.id.root, fragment)
.commit();
O add (int parent, Fragment fragment) adiciona o fragmento que possui seu layout ao layout pai. Se definirmos attachToRoot como true, você receberá IllegalStateException: O filho especificado já tem um pai. Como o layout do fragmento já foi adicionado ao layout pai no método add ().
Você sempre deve passar false para attachToRoot ao inflar fragmentos. O trabalho do FragmentManager é adicionar, remover e substituir fragmentos.
De volta ao meu exemplo. E se fizermos as duas coisas?
View view = inflater.inflate(R.layout.button, root, true);
root.addView(view);
Na primeira linha, LayoutInflater anexa o layout do botão ao layout raiz e retorna um objeto View que contém o mesmo layout do botão. Na segunda linha, adicionamos o mesmo objeto View ao layout raiz pai. Isso resulta na mesma IllegalStateException que vimos com fragmentos (o filho especificado já tem um pai).
Lembre-se de que existe outro método inflate () sobrecarregado, que define o padrão attachToRoot como true por padrão.
View inflate (int resource, ViewGroup root)