Conhecendo melhor o método inflate

Quando queremos criar itens customizados para uma ListView do Android, geralmente criamos um Adapter para isso. Algo parecido com isso:

public class MeuAdapter extends BaseAdapter {

	private Activity activity;
	private String[] elementos;

	public MeuAdapter(Activity activity) {
		this.activity = activity;
		this.elementos = new String[]{"Elemento 1", "Elemento 2", 
					"Elemento 3", "Elemento 4", "Elemento 5"};
	}
	
	public View getView(int posicao, View convertView, ViewGroup parent) {

	}

	public int getCount() {
		return elementos.length;
	}

	public Object getItem(int posicao) {
		return elementos[posicao];
	}

	public long getItemId(int posicao) {
		return 0;
	}
}

Dentro do método getView precisamos transformar numa View o xml contendo o layout do item da lista, para isso usamos o método inflate do LayoutInflater.

Esse código é bastante comum:

public View getView(int posicao, View convertView, ViewGroup parent) {
	LayoutInflater inflater = activity.getLayoutInflater();

	View layout = inflater.inflate(R.layout.item_da_lista, null);

	//popula o layout...

	return layout;
}

O que significa aquele null no segundo argumento do inflate?

public View inflate(int resource, ViewGroup root);

Se você olhar com mais calma, perceberá que existe uma outra assinatura do método inflate que recebe três argumentos:

public View inflate(int resource, ViewGroup root, boolean attachToRoot);

Qual a diferença entre esses dois métodos?

Quando fazemos…

inflater.inflate(R.layout.item_da_lista, null);

…Estamos omitindo o root (ou o pai) desse elemento a ser inflado. Em outras palavras, como o Android não sabe quem é o pai desse layout, todas as propriedades que precisam de informações do pai para serem calculadas são simplesmente sobrescritas. Veja um exemplo:

<LinearLayout
	android:layout_width="match_parent"
	android:layout_height="200dp">

	<TextView
		android:text="Texto qualquer"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"/>
</LinearLayout>

Perceba que esse item deve ter uma altura fixa de 200 dp. Porém, ao ser renderizado, esse item não ficará com essa altura. O inflate sobrescreverá tanto o layout_width quanto o layout_height para algo que não dependa de informação do pai (que passamos null) e colocará wrap_content.

Nesse momento, muitos desenvolvedores resolvem contornar esse “bug” utilizando padding nos seus itens. Porém, esse “bug” desaparece quando entendemos a segunda versão desse método inflate:

public View inflate(int resource, ViewGroup root, boolean attachToRoot);

Precisamos passar um root diferente de null. Mas quem seria?

Note que o próprio getView nos sugere um root (ou um parent) válido no seu terceiro argumento:

public View getView(int posicao, View convertView, ViewGroup parent) {
	LayoutInflater inflater = activity.getLayoutInflater();

	View layout = inflater.inflate(R.layout.item_da_lista, ??, ??);

	//...

	return layout;
}

Então, vamos passar justamente esse ViewGroup parent como root no inflate:

inflater.inflate(R.layout.item_da_lista, parent, ??);

Agora só precisamos entender esse terceiro argumento: attachToRoot.

Quando temos um parent, podemos decidir se queremos que nosso item seja anexado a esse pai ou não. Geralmente, quando criamos uma view programaticamente, para que ela seja renderizada, passamos true no terceiro argumento.

No entanto, a responsabilidade de anexar nosso item à view não é nossa, é do próprio Adapter! Nesse caso, deixamos false:

public View getView(int posicao, View convertView, ViewGroup parent) {
	LayoutInflater inflater = activity.getLayoutInflater();

	View layout = inflater.inflate(R.layout.item_da_lista, parent, false);

	//...

	return layout;
}

Dessa forma, como nosso item_da_lista tem um parent diferente de null, suas propriedades serão respeitadas.

6 Comentários

  1. Jonathan 27/01/2015 at 12:35 #

    Parabéns pelo post, simples e objetivo.

  2. Vanderson assis 02/02/2015 at 08:06 #

    Bom dia Rafael! Ótimo post cara.
    Velho, fiz o curso de ANDROID que você ministra no alura e gostaria de saber se você tem algum curso online que possa me indicar para aprender desenvolvimento de jogos de forma mais avançada. Pode ser em português ou inglês mesmo.

    Abraço!

  3. Vanderson assis 02/02/2015 at 08:07 #

    Cara, seu nome é Felipe, não sei da onde tirei Rafael no comentário acima hahahah…

  4. Thiago 11/02/2015 at 22:26 #

    Muito válido, se me deparasse com esse problema usaria o padding que é chato demais…

    show Felipe!

  5. Robson De Souza 25/02/2015 at 09:33 #

    Post excelente. Claro e objetivo.

  6. Gigi 01/04/2016 at 17:02 #

    Isso foi tao helpful! Tao claro e objetivo!

    Obrigada e parabéns!

Deixe uma resposta