Layouts em visualizações
Um layout define a estrutura de uma interface do usuário no app, como em uma
atividade. Todos os elementos do
layout são criados usando uma hierarquia de
objetos View e
ViewGroup. Uma View geralmente mostra 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.
Os 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 muitos tipos que fornecem uma estrutura de layout diferente, como
LinearLayout
ou
ConstraintLayout.
Um layout pode ser declarado de duas maneiras:
- Declare elementos da interface em XML. O Android fornece um vocabulário XML
direto que corresponde às classes e subclasses
View, como as de widgets e layouts. Também é possível 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. O app pode criar objetos
VieweViewGroupe manipular as propriedades deles de forma programática.
Ao declarar a interface no XML, é possível separar a apresentação do app do código que controla o comportamento dele. O uso de arquivos XML também facilita fornecer layouts diferentes para diferentes tamanhos de tela e orientações. Isso é discutido mais adiante em Suporte a diferentes tamanhos de tela.
O framework do Android oferece flexibilidade para usar um ou ambos os métodos para criar a interface do usuário do seu app. Por exemplo, é possível declarar os layouts padrão do aplicativo em XML e, em seguida, modificar o layout no momento da execução.
Programação do XML
Usando o vocabulário XML do Android, é possível projetar rapidamente layouts de IU e os elementos de tela intrínsecos, do mesmo modo que se 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 deve ser um objeto
View ou ViewGroup. Depois de definir o elemento raiz, é possível adicionar outros objetos ou widgets de layout como elementos filhos para construir gradualmente uma hierarquia de View que define o layout. Por exemplo, veja um layout XML que usa um LinearLayout vertical para
conter 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 mais informações 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(),
passando a referência para o recurso de layout na forma:
R.layout.layout_file_name. Por exemplo, se o layout XML
for salvo como main_layout.xml, carregue-o para seu
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 ele é iniciado.Activity Para mais
informações sobre ciclos de vida de atividades, consulte
Introdução às
atividades.
Atributos
Cada objeto View e ViewGroup aceita uma variedade própria de atributos XML. Alguns atributos são específicos de um objeto View. Por exemplo, o 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 ViewGroup pai.
ID
Qualquer objeto View pode ter um ID de número inteiro associado para
identificar exclusivamente o View na árvore. Quando o app é
compilado, esse ID é referenciado como um número inteiro, mas normalmente é atribuído
no arquivo XML do layout como uma string no atributo id. É um atributo XML comum a todos os objetos View e é definido pela classe View. Você 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 arroba (@) 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 é 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, não é necessário ter o símbolo de adição, mas é preciso 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, em vez da classe de recursos
local.
Para criar visualizações e referenciá-las no seu app, use um padrão comum da seguinte maneira:
- Defina uma visualização no arquivo de layout e atribua um ID exclusivo a ela, 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 do 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, visualizações irmãs podem definir o layout relativo para outra visualização irmã, referenciada pelo ID exclusivo.
Um ID não precisa ser exclusivo por toda a árvore, mas deve ser exclusivo dentro da parte da árvore em que você pesquisa. Muitas vezes, pode ser toda a árvore, então é melhor torná-lo exclusivo sempre que possível.
Parâmetros de layout
Os atributos do layout XML chamados layout_something definem
parâmetros de layout para o View apropriados para o
ViewGroup em que ele 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 pai define parâmetros de layout para cada visualização filha, incluindo o grupo de visualizações filhas.
Cada subclasse LayoutParams tem a própria sintaxe para definir
valores. Cada elemento filho precisa definir um LayoutParams adequado 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 é obrigatória para defini-las. Muitos
LayoutParams incluem margens e bordas opcionais.
É possível especificar largura e altura com medidas exatas, mas não é recomendável na maioria dos casos. Em geral, usa-se uma destas constantes para definir a largura e a altura:
wrap_content: instrui a exibição a redimensionar de acordo com as dimensões exigidas pelo conteúdo.match_parent: instrui sua visualização a assumir o maior tamanho permitido pelo grupo de visualizações parental.
Em geral, não recomendamos especificar largura e altura de um layout usando
unidades absolutas, como pixels. Uma abordagem melhor é usar medidas relativas, como unidades de pixel de densidade independente (dp), 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. Ela tem uma localização, expressa 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.
É possível recuperar a localização de uma visualização chamando 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 ao
elemento pai. Por exemplo, quando getLeft() retorna 20, isso significa que a
visualização está localizada 20 pixels à direita da borda esquerda do elemento
pai direto.
Além disso, há métodos de conveniência para evitar cálculos desnecessários:
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, padding 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 terá
dentro do elemento pai. Você pode conseguir as dimensões medidas chamando
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, na hora do desenho e após o layout. Esses valores podem diferir da largura e da altura medidas. Você
pode conseguir 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 a esquerda, a direita e as partes superior e inferior da visualização.
É possível usar o padding para compensar o conteúdo da visualização por um número específico
de pixels. Por exemplo, um padding à esquerda 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 oferecem suporte a 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, você também pode fazer isso 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 aplicação de margem e padding. O
TextView tem margens e padding uniformes aplicados em toda a volta, e
o Button mostra como você pode aplicá-los de forma independente a diferentes
bordas.
Layouts comuns
Cada subclasse da classe ViewGroup oferece uma maneira exclusiva de
mostrar as visualizações aninhadas dentro dela. O tipo de layout mais flexível e que oferece as melhores ferramentas para manter a hierarquia de layout simples é ConstraintLayout.
Confira abaixo alguns dos tipos de layout comuns criados na plataforma Android.
Organiza os filhos em uma única linha horizontal ou vertical e cria uma barra de rolagem se o comprimento da janela exceder 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.
Em geral, RecyclerView é a melhor opção porque usa a memória de maneira mais eficiente do que AdapterView.
Layouts comuns possíveis com RecyclerView e
AdapterView incluem:
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 diversas subclasses de Adapter que são úteis
para recuperar diferentes tipos de dados e criar visualizações de um
AdapterView. Os dois adaptadores mais comuns são:
ArrayAdapter- Use esse adaptador quando a fonte de dados for uma matriz. Por padrão,
ArrayAdaptercria uma visualização para cada item de matriz chamandotoString()em cada item e posicionando o conteúdo em umTextView.Por exemplo, se você tiver uma matriz de strings que quer exibir em um
ListView, inicialize um novoArrayAdapterusando 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 desse construtor são os seguintes:
- Seu app
Context - O layout que contém um
TextViewpara cada string na matriz - A matriz de strings
Em seguida, chame
setAdapter()no seuListView: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 substituir o método
toString()para os objetos na matriz. Ou, para criar uma visualização para cada item diferente de umTextView—por exemplo, se você quiser umImageViewpara cada item da matriz—estenda a classeArrayAdaptere substituagetView()para retornar o tipo de visualização que quer para cada item. - Seu app
SimpleCursorAdapter- Use esse adaptador quando os dados vierem de um
Cursor. Ao usarSimpleCursorAdapter, especifique um layout para usar em cada linha doCursore quais colunas doCursorvocê quer inserir nas visualizações do layout. Por exemplo, se quiser criar uma lista de nomes e números de telefone de pessoas, execute uma consulta que retorne umCursorcom uma linha para cada pessoa e colunas para os nomes e números. Em seguida, crie uma matriz de strings que especifique quais colunas doCursorestarão no layout para cada resultado e uma matriz de números inteiros que especifique as visualizações correspondentes em 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, oCursorcontendo 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
SimpleCursorAdaptercria uma visualização de cada linha noCursorusando o layout fornecido por meio da inserção de cada item defromColumnsna visualizaçãotoViewscorrespondente.
Se você mudar os dados subjacentes lidos pelo adaptador durante a vida útil do app, chame
notifyDataSetChanged().
Isso notifica a visualização anexada de que os dados foram mudados e ela se atualiza
automaticamente.
Processar eventos de clique
Para responder a eventos de clique em cada item em um AdapterView,
implemente a interface
AdapterView.OnItemClickListener. 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 no GitHub.


