Layouts nas visualizações
Um layout define a estrutura de uma interface do usuário no seu app, como em
uma
atividade. Todos os elementos do
layout são criados usando uma hierarquia de
objetos
View
e
ViewGroup
. Um View
geralmente desenha algo que o usuário pode ver e
interagir. Um ViewGroup
é um contêiner invisível que define
a estrutura do layout para View
e outros objetos
ViewGroup
, como mostrado na Figura 1.
![](https://developer.android.com/static/images/viewgroup_2x.png?authuser=7&hl=pt-br)
Objetos View
geralmente são chamados de widgets e podem ser uma das
muitas subclasses, como
Button
ou
TextView
. Os
objetos ViewGroup
geralmente são chamados de layouts e podem ser de
um dos vários tipos que oferecem uma estrutura de layout diferente, como
LinearLayout
ou
ConstraintLayout
.
Um layout pode ser declarado de duas maneiras:
- Declarar elementos da interface em XML. O Android fornece um vocabulário XML
direto que corresponde às classes e subclasses de
View
, como as de widgets e layouts. Você também pode usar o Layout Editor do Android Studio para criar o layout XML usando uma interface de arrastar e soltar. - Instanciar elementos do layout no momento da execução. Seu app pode criar objetos
View
eViewGroup
e manipular as propriedades deles de forma programática.
Declarar a interface em XML permite separar a apresentação do app do código que controla o comportamento dele. O uso de arquivos XML também facilita o fornecimento de diferentes layouts para diferentes tamanhos e orientações de tela. Isso é discutido em Suporte a tamanhos de tela diferentes.
O framework do Android oferece flexibilidade para usar um ou ambos os métodos para criar a interface do seu app. Por exemplo, você pode declarar os layouts padrão do app em XML e modificar o layout durante a execução.
Programação do XML
Com o vocabulário XML do Android, é possível projetar rapidamente layouts de interface e os elementos de tela que eles contêm, da mesma forma que você cria páginas da Web em HTML com uma série de elementos aninhados.
Cada arquivo de layout precisa conter exatamente um elemento raiz, que precisa ser um objeto
View
ou ViewGroup
. Depois de definir o elemento
raiz, é possível adicionar outros objetos de layout ou widgets como elementos filhos para
criar gradualmente uma hierarquia View
que defina o layout. Por
exemplo, este é um layout XML que usa um LinearLayout
vertical para
manter um TextView
e um Button
:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a Button" /> </LinearLayout>
Depois de declarar o layout em XML, salve o arquivo com a
extensão .xml
no diretório res/layout/
do projeto Android para que ele seja compilado corretamente.
Para saber mais sobre a sintaxe de um arquivo XML de layout, consulte Recurso de layout.
Carregar o recurso XML
Ao compilar o aplicativo, cada arquivo de layout XML é compilado em um
recurso View
. Carregue o recurso de layout na implementação de callback
Activity.onCreate()
do app. Para isso, chame
setContentView()
,
transmitindo a referência ao recurso de layout no formato:
R.layout.layout_file_name
. Por exemplo, se o layout XML
for salvo como main_layout.xml
, carregue-o para
Activity
da seguinte maneira:
Kotlin
fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) setContentView(R.layout.main_layout) }
Java
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_layout); }
O framework do Android chama o método de callback onCreate()
no
seu Activity
quando o Activity
é iniciado. Para mais
informações sobre ciclos de vida de atividades, consulte
Introdução às
atividades.
Atributos
Cada objeto View
e ViewGroup
oferece suporte à própria
variedade de atributos XML. Alguns atributos são específicos de um objeto
View
. Por exemplo, TextView
é compatível com o atributo
textSize
. No entanto, esses atributos também são herdados por objetos View
que estendem essa classe. Alguns são comuns a todos os objetos
View
, porque são herdados da classe raiz View
, como
o atributo id
. Outros atributos são considerados parâmetros
de layout, que descrevem determinadas orientações
de layout do objeto View
, conforme definido pelo objeto pai
ViewGroup
desse objeto.
ID
Qualquer objeto View
pode ter um ID de número inteiro associado para
identificar exclusivamente o View
dentro da árvore. Quando o app é
compilado, esse ID é referenciado como um número inteiro, mas o ID normalmente é atribuído
no arquivo XML de layout como uma string no atributo id
. Esse é um
atributo XML comum a todos os objetos View
e é definido pela
classe View
. Você a usa com muita frequência. A sintaxe de um ID dentro de uma
tag XML é a seguinte:
android:id="@+id/my_button"
O símbolo a (@) no início da string indica que
o analisador XML analisa e expande o restante da string de ID e a identifica como
um recurso de ID. O símbolo de adição (+) significa que esse é um novo nome de recurso
que precisa ser criado e adicionado aos recursos no arquivo
R.java
.
O framework do Android oferece muitos outros recursos de ID. Ao referenciar um
ID de recurso do Android, você não precisa do símbolo de adição, mas precisa adicionar o
namespace do pacote android
da seguinte maneira:
android:id="@android:id/empty"
O namespace do pacote android
indica que você está referenciando
um ID da classe de recursos android.R
, e não da classe de recursos
locais.
Para criar visualizações e referenciá-las no app, você pode usar um padrão comum da seguinte maneira:
- Defina uma visualização no arquivo de layout e atribua a ela um ID exclusivo, como no
exemplo a seguir:
<Button android:id="@+id/my_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/my_button_text"/>
- Crie uma instância do objeto de visualização e capture-a no layout,
normalmente no método
onCreate()
, conforme mostrado no exemplo a seguir:Kotlin
val myButton: Button = findViewById(R.id.my_button)
Java
Button myButton = (Button) findViewById(R.id.my_button);
Definir IDs para objetos de visualização é importante ao criar um
RelativeLayout
.
Em um layout relativo, as visualizações irmãs podem definir o layout relativo a outra
visualização irmã, que é referenciada pelo ID exclusivo.
Um ID não precisa ser exclusivo em toda a árvore, mas precisa ser exclusivo dentro da parte da árvore pesquisada. Muitas vezes, pode ser a árvore inteira, por isso é melhor torná-la única sempre que possível.
Parâmetros de layout
Os atributos de layout XML com o nome layout_something
definem
parâmetros de layout para a View
adequados para a
ViewGroup
em que ela reside.
Cada classe ViewGroup
implementa uma classe aninhada que estende
ViewGroup.LayoutParams
.
Essa subclasse contém tipos de propriedade que definem o tamanho e a posição de cada
visualização filha, conforme apropriado para o grupo de visualizações. Como mostrado na Figura 2, o grupo
de visualizações mãe define parâmetros de layout para cada visualização filha, incluindo o grupo
de visualizações filhas.
![](https://developer.android.com/static/images/layoutparams.png?authuser=7&hl=pt-br)
Cada subclasse LayoutParams
tem a própria sintaxe para definir
valores. Cada elemento filho precisa definir um LayoutParams
apropriado para o pai, embora também possa definir um LayoutParams
diferente para os próprios filhos.
Todos os grupos de visualizações incluem largura e altura, usando layout_width
e layout_height
, e cada visualização é necessária para defini-las. Muitas
LayoutParams
incluem margens e bordas opcionais.
É possível especificar largura e altura com medidas exatas, mas talvez você não queira fazer isso com frequência. Normalmente, você usa uma destas constantes para definir a largura ou a altura:
wrap_content
: instrui a visualização a se redimensionar de acordo com as dimensões exigidas pelo conteúdo.match_parent
: instrui a visualização a assumir o maior tamanho permitido pelo grupo de visualizações pai.
Em geral, não recomendamos especificar uma largura e altura de layout usando
unidades absolutas, como pixels. Uma abordagem melhor é usar medidas relativas,
como unidades de pixel de densidade independente (dp, na sigla em inglês), wrap_content
ou
match_parent
, porque isso ajuda o app a ser exibido corretamente em
vários tamanhos de tela de dispositivos. Os tipos de medidas aceitos são definidos no
recurso de layout.
Posição do layout
Uma visualização tem geometria retangular. Ele tem um local, expresso como um par de coordenadas esquerda e superior, e duas dimensões, expressas como largura e altura. A unidade de localização e de dimensões é o pixel.
Você pode recuperar a localização de uma visualização invocando os métodos
getLeft()
e
getTop()
.
O primeiro retorna a coordenada esquerda (x) do retângulo que representa
a visualização. O último retorna a coordenada superior (y) do retângulo
que representa a visualização. Esses métodos retornam a localização da visualização em relação à
mãe. Por exemplo, quando getLeft()
retorna 20, isso significa que a
visualização está localizada 20 pixels à direita da borda esquerda do pai
direto.
Além disso, há métodos convenientes para evitar cálculos desnecessários:
ou seja,
getRight()
e
getBottom()
.
Esses métodos retornam as coordenadas das bordas direita e inferior do
retângulo que representa a visualização. Por exemplo, chamar getRight()
é
semelhante ao seguinte cálculo: getLeft() + getWidth()
.
Tamanho, preenchimento e margens
O tamanho de uma visualização é expresso por largura e altura. Uma visualização tem dois pares de valores de largura e altura.
O primeiro par é conhecido como largura medida e
altura medida. Essas dimensões definem o tamanho que a visualização
quer ter dentro do elemento pai. Para conferir as dimensões medidas, chame
getMeasuredWidth()
e
getMeasuredHeight()
.
O segundo par é conhecido como largura e altura ou, às vezes,
largura do desenho e altura do desenho. Essas dimensões definem o
tamanho real da visualização na tela, no momento do desenho e após o layout. Esses
valores podem ser diferentes da largura e da altura medidas. Você
pode conferir a largura e a altura chamando
getWidth()
e
getHeight()
.
Para medir as dimensões, a visualização leva em conta o preenchimento. O padding
é expresso em pixels para as partes esquerda, superior, direita e inferior da visualização.
Você pode usar o padding para deslocar o conteúdo da visualização por um número específico de
pixels. Por exemplo, um padding esquerdo de dois empurra o conteúdo da visualização dois pixels
para a direita da borda esquerda. É possível definir o padding usando o método
setPadding(int, int, int, int)
e consultá-lo chamando
getPaddingLeft()
,
getPaddingTop()
,
getPaddingRight()
e
getPaddingBottom()
.
Embora uma visualização possa definir um padding, ela não é compatível com margens. No entanto,
os grupos de visualizações são compatíveis com margens. Consulte
ViewGroup
e
ViewGroup.MarginLayoutParams
para mais informações.
Para mais informações sobre dimensões, consulte Dimensão.
Além de definir margens e padding de forma programática, também é possível defini-los nos layouts XML, conforme mostrado no exemplo a seguir.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="16dp" android:padding="8dp" android:text="Hello, I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:paddingBottom="4dp" android:paddingEnd="8dp" android:paddingStart="8dp" android:paddingTop="4dp" android:text="Hello, I am a Button" /> </LinearLayout>
O exemplo anterior mostra a margem e o padding sendo aplicados. A
TextView
tem margens e padding uniformes aplicados em toda a parte, e
o Button
mostra como aplicá-los de forma independente a bordas
diferentes.
Layouts comuns
Cada subclasse da ViewGroup
oferece uma maneira exclusiva de
exibir as visualizações aninhadas dentro dela. O tipo de layout mais flexível e
que fornece as melhores ferramentas para manter sua hierarquia de layout superficial é
ConstraintLayout
.
Confira abaixo alguns dos tipos de layout comuns integrados à plataforma Android.
![](https://developer.android.com/static/images/ui/linearlayout-small.png?authuser=7&hl=pt-br)
Organiza os filhos em uma única linha horizontal ou vertical e cria uma barra de rolagem caso o comprimento da janela exceda o comprimento da tela.
Criar listas dinâmicas
Quando o conteúdo do layout é dinâmico ou não predeterminado, é possível
usar
RecyclerView
ou
uma subclasse de
AdapterView
.
RecyclerView
geralmente é a melhor opção, porque usa a memória
de forma mais eficiente do que AdapterView
.
Os layouts comuns possíveis com RecyclerView
e
AdapterView
incluem o seguinte:
O RecyclerView
oferece mais possibilidades e
a opção de
criar um gerenciador de layout
personalizado.
Preencher uma visualização de adaptador com dados
É possível preencher um
AdapterView
como ListView
ou
GridView
vinculando a instância de AdapterView
a um
Adapter
,
que recupera dados de uma fonte externa e cria um View
que representa cada entrada de dados.
O Android oferece várias subclasses de Adapter
que são úteis
para recuperar diferentes tipos de dados e criar visualizações para uma
AdapterView
. Os dois adaptadores mais comuns são:
ArrayAdapter
- Use esse adaptador quando a fonte de dados for uma matriz. Por padrão,
ArrayAdapter
cria uma visualização para cada item da matriz chamandotoString()
em cada item e colocando o conteúdo em umaTextView
.Por exemplo, se você tem uma matriz de strings que quer exibir em um
ListView
, inicialize um novoArrayAdapter
usando um construtor para especificar o layout de cada string e a matriz de strings:Kotlin
val adapter = ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray)
Java
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray);
Os argumentos para esse construtor são os seguintes:
- Seu app
Context
- O layout que contém um
TextView
para cada string na matriz - A matriz de strings
Em seguida, chame
setAdapter()
noListView
:Kotlin
val listView: ListView = findViewById(R.id.listview) listView.adapter = adapter
Java
ListView listView = (ListView) findViewById(R.id.listview); listView.setAdapter(adapter);
Para personalizar a aparência de cada item, é possível modificar o método
toString()
para os objetos na matriz. Ou, para criar uma visualização para cada item que seja diferente de umTextView
(por exemplo, se você quiser umImageView
para cada item da matriz), estenda a classeArrayAdapter
e substituagetView()
para retornar o tipo de visualização que você quer para cada item. - Seu app
SimpleCursorAdapter
- Use esse adaptador quando seus dados vierem de um
Cursor
. Ao usarSimpleCursorAdapter
, especifique um layout a ser usado para cada linha noCursor
e quais colunas noCursor
você quer inserir nas visualizações do layout desejado. Por exemplo, se você quiser criar uma lista de nomes e números de telefone das pessoas, execute uma consulta que retorne umCursor
contendo uma linha para cada pessoa e colunas para os nomes e números. Em seguida, você cria uma matriz de strings especificando quais colunas doCursor
vão estar no layout para cada resultado e uma matriz de números inteiros especificando as visualizações correspondentes que cada coluna precisa ser colocada:Kotlin
val fromColumns = arrayOf(ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER) val toViews = intArrayOf(R.id.display_name, R.id.phone_number)
Java
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER}; int[] toViews = {R.id.display_name, R.id.phone_number};
Ao instanciar o
SimpleCursorAdapter
, transmita o layout a ser usado para cada resultado, oCursor
contendo os resultados e estas duas matrizes:Kotlin
val adapter = SimpleCursorAdapter(this, R.layout.person_name_and_number, cursor, fromColumns, toViews, 0) val listView = getListView() listView.adapter = adapter
Java
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.person_name_and_number, cursor, fromColumns, toViews, 0); ListView listView = getListView(); listView.setAdapter(adapter);
Em seguida, o
SimpleCursorAdapter
cria uma visualização para cada linha noCursor
usando o layout fornecido por meio da inserção de cada item defromColumns
na visualizaçãotoViews
correspondente.
Se você mudar os dados subjacentes que
são lidos pelo adaptador durante a vida útil do app, chame
notifyDataSetChanged()
.
Isso notifica a visualização anexada de que os dados foram alterados e se atualiza.
Processar eventos de clique
Para responder a eventos de clique em cada item em um AdapterView
,
implemente a
interface
AdapterView.OnItemClickListener
. Por exemplo:
Kotlin
listView.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id -> // Do something in response to the click. }
Java
// Create a message handling object as an anonymous class. private OnItemClickListener messageClickedHandler = new OnItemClickListener() { public void onItemClick(AdapterView parent, View v, int position, long id) { // Do something in response to the click. } }; listView.setOnItemClickListener(messageClickedHandler);
Outros recursos
Confira como os layouts são usados no app de demonstração Sunflower (link em inglês) no GitHub.