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.