A barra de apps superior proporciona um lugar consistente na parte superior da janela do app para exibir informações e ações da tela atual.
A propriedade da barra de apps varia de acordo com as necessidades do seu app. Ao
usar fragmentos, a barra de apps pode ser implementada como uma
ActionBar
que pertence
à atividade do host ou a uma barra de ferramentas no layout do fragmento.
Se todas as suas telas usam a mesma barra de apps que está sempre na parte de cima e se estende pela largura da tela, use uma barra de ações fornecida pelo tema e hospedada pela atividade. O uso de barras de apps com temas ajuda a manter uma aparência consistente e oferece um local para hospedar menus de opção e um botão "para cima".
Use uma barra de ferramentas hospedada pelo fragmento se você quiser ter mais controle sobre o tamanho, a posição e a animação da barra de apps em várias telas. Por exemplo, talvez você precise de uma barra de apps recolhível ou de uma que se estenda apenas até a metade da tela e seja centralizada verticalmente.
Diferentes situações exigem diferentes abordagens para aspectos como inflação de menus e resposta à interação do usuário. Entender as diferentes abordagens e usar a melhor para o app poupa tempo e ajuda a garantir que o app funcione corretamente.
Os exemplos neste tópico se referem a um ExampleFragment
que contém
um perfil editável. O fragmento infla o
menu definido por XML abaixo na barra de apps:
<!-- sample_menu.xml -->
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_settings"
android:icon="@drawable/ic_settings"
android:title="@string/settings"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/action_done"
android:icon="@drawable/ic_done"
android:title="@string/done"
app:showAsAction="ifRoom|withText"/>
</menu>
O menu contém duas opções: uma para navegar até uma tela de perfil e outra para salvar as mudanças feitas no perfil.
Barra de apps da atividade
A barra de apps geralmente é de propriedade da atividade do host. Quando a barra de apps pertence a uma atividade, os fragmentos podem interagir com ela substituindo os métodos de framework que são chamados durante a criação de fragmentos.
Registrar com atividades
Informe ao sistema que o fragmento da barra de apps está participando
do preenchimento do menu de opções. Para fazer isso, chame
setHasOptionsMenu(true)
no método onCreate(Bundle)
do fragmento, conforme mostrado no exemplo
a seguir:
Kotlin
class ExampleFragment : Fragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) } }
Java
public class ExampleFragment extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); } }
setHasOptionsMenu(true)
informa ao sistema que seu fragmento
quer receber callbacks relacionados ao menu. Quando ocorre um evento
relacionado a um menu, como um clique, o método de processamento de eventos é
chamado primeiro na atividade antes de ser chamado no fragmento.
No entanto, não confie nessa ordem na lógica do aplicativo. Se a mesma atividade hospeda vários fragmentos, cada fragmento pode fornecer opções de menu. Nesse caso, a ordem dos callbacks depende da ordem em que os fragmentos são adicionados.
Inflar o menu
Para mesclar seu menu ao menu de opções da barra de apps, substitua
onCreateOptionsMenu()
no seu fragmento. Esse método recebe o menu da barra de apps atual e um
MenuInflater
como parâmetros. Use
o inflador de menu para criar uma instância do menu do fragmento e
mescle-a no menu atual, como mostrado no exemplo a seguir:
Kotlin
class ExampleFragment : Fragment() { ... override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { inflater.inflate(R.menu.sample_menu, menu) } }
Java
public class ExampleFragment extends Fragment { ... @Override public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { inflater.inflate(R.menu.sample_menu, menu); } }
A Figura 2 mostra o menu atualizado.
Processar eventos de clique
Todas as atividades e fragmentos que participam do menu de opções podem
responder aos toques. O
onOptionsItemSelected()
do fragmento recebe o item de menu selecionado como um parâmetro e retorna um booleano
para indicar se o toque foi consumido. Quando uma
atividade ou um fragmento retorna true
de onOptionsItemSelected()
, nenhum
outro fragmento participante recebe o callback.
Na sua implementação de onOptionsItemSelected()
, use uma instrução
switch
no itemId
do item do menu. Se o item selecionado
for seu, processe o toque de maneira adequada e retorne true
para indicar
que o evento de clique foi processado. Se o item selecionado não for
seu, chame a implementação de super
. Por padrão, a implementação de super
retorna false
para permitir que o processamento do menu continue.
Kotlin
class ExampleFragment : Fragment() { ... override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { R.id.action_settings -> { // Navigate to settings screen. true } R.id.action_done -> { // Save profile changes. true } else -> super.onOptionsItemSelected(item) } } }
Java
public class ExampleFragment extends Fragment { ... @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.action_settings: { // Navigate to settings screen. return true; } case R.id.action_done: { // Save profile changes. return true; } default: return super.onOptionsItemSelected(item); } } }
Modificar o menu de forma dinâmica
Coloque a lógica para ocultar ou mostrar um botão ou mudar o ícone em
onPrepareOptionsMenu()
.
Esse método é chamado logo antes de mostrar o menu.
Continuando com o exemplo anterior, o botão Salvar ficará
invisível até que o usuário inicie a edição e desaparecerá depois que
o usuário salvar. A adição dessa lógica a onPrepareOptionsMenu()
garante
que o menu seja apresentado corretamente:
Kotlin
class ExampleFragment : Fragment() { ... override fun onPrepareOptionsMenu(menu: Menu){ super.onPrepareOptionsMenu(menu) val item = menu.findItem(R.id.action_done) item.isVisible = isEditing } }
Java
public class ExampleFragment extends Fragment { ... @Override public void onPrepareOptionsMenu(@NonNull Menu menu) { super.onPrepareOptionsMenu(menu); MenuItem item = menu.findItem(R.id.action_done); item.setVisible(isEditing); } }
Quando você precisar atualizar o menu, como quando um usuário pressiona o
botão Editar para editar as informações do perfil, chame
invalidateOptionsMenu()
na atividade do host para solicitar que o sistema chame onCreateOptionsMenu()
.
Após a invalidação, é possível fazer as atualizações em onCreateOptionsMenu()
. Depois que
o menu é inflado, o sistema chama onPrepareOptionsMenu()
e atualiza
o menu para refletir o estado atual do fragmento.
Kotlin
class ExampleFragment : Fragment() { ... fun updateOptionsMenu() { isEditing = !isEditing requireActivity().invalidateOptionsMenu() } }
Java
public class ExampleFragment extends Fragment { ... public void updateOptionsMenu() { isEditing = !isEditing; requireActivity().invalidateOptionsMenu(); } }
Barra de apps do fragmento
Se a maioria das telas do seu app não precisar de uma barra de apps ou se uma
tela precisar de uma barra diferente das outras, adicione uma
Toolbar
ao
layout do fragmento. Embora você possa adicionar uma Toolbar
em qualquer lugar dentro da
hierarquia de visualização do fragmento, ela geralmente é mantida na parte de cima
da tela. Para usar a Toolbar
no seu fragmento, forneça um ID e
extraia uma referência a ele no fragmento, da mesma forma que você faria com qualquer outra
visualização. Você também pode animar a barra de ferramentas usando
comportamentos
CoordinatorLayout
.
<androidx.appcompat.widget.Toolbar
android:id="@+id/myToolbar"
... />
Ao usar uma barra de apps de um fragmento, o Google recomenda usar as
APIs Toolbar
diretamente. Não use
setSupportActionBar()
e as APIs de menu do Fragment
, que são adequadas apenas para barras de apps de atividades.
Inflar o menu
O método de conveniência inflateMenu(int)
da Toolbar
usa o ID de um
recurso de menu como parâmetro. Para inflar um recurso de menu XML na
barra de ferramentas, transmita o resId
para esse método, conforme mostrado no exemplo
a seguir:
Kotlin
class ExampleFragment : Fragment() { ... override fun onViewCreated(view: View, savedInstanceState: Bundle?) { ... viewBinding.myToolbar.inflateMenu(R.menu.sample_menu) } }
Java
public class ExampleFragment extends Fragment { ... @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { ... viewBinding.myToolbar.inflateMenu(R.menu.sample_menu); } }
Para inflar outro recurso de menu XML, chame o método novamente com o
resId
do novo menu. Os novos itens são adicionados ao menu, e os
itens existentes não são modificados nem removidos.
Se você quiser substituir o conjunto de menus existente, limpe o menu antes de
chamar inflateMenu(int)
com o novo ID do menu, como mostrado no exemplo
abaixo:
Kotlin
class ExampleFragment : Fragment() { ... fun clearToolbarMenu() { viewBinding.myToolbar.menu.clear() } }
Java
public class ExampleFragment extends Fragment { ... public void clearToolbarMenu() { viewBinding.myToolbar.getMenu().clear() } }
Processar eventos de clique
Você pode transmitir um
OnMenuItemClickListener
diretamente à barra de ferramentas usando o
método
setOnMenuItemClickListener()
. Esse listener é invocado quando o usuário seleciona um item de menu
nos botões de ação apresentados no final da barra de ferramentas ou no
overflow associado. O MenuItem
selecionado
é transmitido ao método
onMenuItemClick()
do listener e pode ser usado para consumir a ação, conforme mostrado no exemplo
abaixo:
Kotlin
class ExampleFragment : Fragment() { ... override fun onViewCreated(view: View, savedInstanceState: Bundle?) { ... viewBinding.myToolbar.setOnMenuItemClickListener { when (it.itemId) { R.id.action_settings -> { // Navigate to settings screen. true } R.id.action_done -> { // Save profile changes. true } else -> false } } } }
Java
public class ExampleFragment extends Fragment { ... @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { ... viewBinding.myToolbar.setOnMenuItemClickListener(item -> { switch (item.getItemId()) { case R.id.action_settings: // Navigate to settings screen. return true; case R.id.action_done: // Save profile changes. return true; default: return false; } }); } }
Modificar o menu de forma dinâmica
Quando o fragmento pertence à barra de apps, é possível modificar o Toolbar
durante
a execução como qualquer outra visualização.
Continuando com o exemplo anterior, a opção de menu Salvar ficará invisível até o usuário iniciar a edição, desaparecendo novamente depois que for tocada:
Kotlin
class ExampleFragment : Fragment() { ... fun updateToolbar() { isEditing = !isEditing val saveItem = viewBinding.myToolbar.menu.findItem(R.id.action_done) saveItem.isVisible = isEditing } }
Java
public class ExampleFragment extends Fragment { ... public void updateToolbar() { isEditing = !isEditing; MenuItem saveItem = viewBinding.myToolbar.getMenu().findItem(R.id.action_done); saveItem.setVisible(isEditing); } }
Adicionar um ícone de navegação
Se estiver presente, o botão de navegação aparecerá no início da barra de ferramentas.
Quando você define um ícone de navegação na barra de ferramentas, ela fica visível. Você também pode
definir um onClickListener()
específico de navegação, que será chamado sempre
que o usuário clicar no botão de navegação, conforme mostrado no exemplo
a seguir:
Kotlin
class ExampleFragment : Fragment() { ... override fun onViewCreated(view: View, savedInstanceState: Bundle?) { ... myToolbar.setNavigationIcon(R.drawable.ic_back) myToolbar.setNavigationOnClickListener { view -> // Navigate somewhere. } } }
Java
public class ExampleFragment extends Fragment { ... @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { ... viewBinding.myToolbar.setNavigationIcon(R.drawable.ic_back); viewBinding.myToolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // Navigate somewhere. } }); } }