Iniciando um novo projeto, decidi tentar abandonar completamente os arquivos XML, com base nos layouts formados, e criar telas usando a biblioteca Anko. Tendo pouca experiência em desenvolvimento para Android (cerca de 2 anos) e ainda menos experiência em escrever código no Kotlin (pouco mais de seis meses), imediatamente enfrentei o problema de incluir a barra de navegação inferior criada por BottomNavigationView no aplicativo Componente de Arquitetura de Navegação.
Antes de tudo, voltei-me à Internet para encontrar uma solução possível. Mas todos os artigos que encontrei com diferentes graus de clareza informaram sobre como trabalhar com componentes de navegação e nenhum (daqueles cujos artigos eu estudei) fez no Anko. Tendo resolvido a tarefa, ofereço à comunidade minha opção de criar uma barra de navegação inferior.
Todo o código pode ser visto aqui.
Eu pulo o estágio de criação de um novo projeto no Android Studio, apenas observe as seguintes dependências para trabalhar com o Anko e o Navigation Architecture Component no build.gradle no nível do módulo:
implementation "org.jetbrains.anko:anko:$anko_version" implementation "org.jetbrains.anko:anko-constraint-layout:$anko_version" implementation "com.android.support.constraint:constraint-layout:2.0.0-alpha3" implementation 'android.arch.navigation:navigation-fragment:1.0.0-beta02' implementation 'android.arch.navigation:navigation-fragment-ktx:1.0.0-beta02' implementation 'android.arch.navigation:navigation-ui-ktx:1.0.0-beta02' implementation 'com.google.android.material:material:1.0.0'
O próximo passo é criar a estrutura do aplicativo futuro. Para desenhar a atividade principal, em vez do arquivo xml, crie a classe MainActivityUI herdada da interface AnkoComponent:
class MainActivityUI: AnkoComponent<MainActivity> { override fun createView(ui: AnkoContext<MainActivity>): View = with(ui) { constraintLayout { } } }
Na classe MainActivity, setContentView (R.layout.activity_main) é substituído por MainActivityUI (). SetContentView (this).
Em seguida, criamos fragmentos de pacote nos quais nossos fragmentos e interface do usuário estarão para colocar as classes responsáveis por renderizar telas dos fragmentos correspondentes. Esta é a estrutura do projeto:
fragments ui HomeUI UsersUI DetailsUI MoreUI HomeFragment UsersFragment DetailsFragment MoreFragment
Agora, lidaremos diretamente com a navegação e a criação da barra de navegação inferior.
Uma descrição detalhada da inclusão de novos componentes de navegação e uma descrição do trabalho no Editor de Navegação podem ser encontradas na página de documentação aqui . Para criar um arquivo (gráfico) para navegação entre as telas do aplicativo, você precisa adicionar outra pasta à pasta res, a saber navegação, e adicionar o arquivo navigation_graph.xml a ela. Para este projeto, será assim:
<navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/navigation_graph" app:startDestination="@id/homeFragment"> <fragment android:id="@+id/homeFragment" android:name="com.arsinde.ankobottomnavbar.fragments.HomeFragment" android:label="HomeFragment"> <action android:id="@+id/action_homeFragment_to_detailsFragment" app:destination="@id/detailsFragment"/> </fragment> <fragment android:id="@+id/detailsFragment" android:name="com.arsinde.ankobottomnavbar.fragments.DetailsFragment" android:label="DetailsFragment"> <action android:id="@+id/action_detailsFragment_to_usersFragment" app:destination="@id/usersFragment"/> </fragment> <fragment android:id="@+id/usersFragment" android:name="com.arsinde.ankobottomnavbar.fragments.UsersFragment" android:label="UsersFragment"> <action android:id="@+id/action_usersFragment_to_moreFragment" app:destination="@id/moreFragment"/> </fragment> <fragment android:id="@+id/moreFragment" android:name="com.arsinde.ankobottomnavbar.fragments.MoreFragment" android:label="MoreFragment"/> </navigation>
Para exibir a própria barra, você precisa criar outra pasta de recursos, o menu. Ele contém o arquivo responsável pela parte visível da barra. É assim que parece neste projeto:
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@id/homeFragment" android:icon="@drawable/ic_home" android:title="@string/menu_title_home"/> <item android:id="@id/usersFragment" android:icon="@drawable/ic_users" android:title="@string/menu_title_users"/> <item android:id="@id/detailsFragment" android:icon="@drawable/ic_info" android:title="@string/menu_title_details"/> <item android:id="@id/moreFragment" android:icon="@drawable/ic_more" android:title="@string/menu_title_more"/> </menu>
É hora de juntar tudo e ver como funciona.
Adicione um contêiner para fragmentos no MainActivityUI e também defina um contêiner para a barra de navegação.
constraintLayout { val fragmentContainer = frameLayout { id = R.id.fragment_container }.lparams { width = matchParent height = matchConstraint } val bottomNavigation = bottomNavigation { id = R.id.bottom_nav_view inflateMenu(R.menu.bottom_navigation_menu) } applyConstraintSet { fragmentContainer { connect( START to START of PARENT_ID, END to END of PARENT_ID, TOP to TOP of PARENT_ID, BOTTOM to TOP of R.id.bottom_nav_view ) } bottomNavigation { connect( START to START of PARENT_ID, END to END of PARENT_ID, TOP to BOTTOM of R.id.fragment_container, BOTTOM to BOTTOM of PARENT_ID ) } } }
Deve-se notar especialmente que bottomNavigation neste exemplo é uma função de extinção, que tem o seguinte formato:
inline fun ViewManager.bottomNavigation(init: BottomNavigationView.() -> Unit = {}) = ankoView({ BottomNavigationView(it) }, theme = 0, init = init)
Agora em MainActivity, você precisa definir o objeto NavHostFragment (consulte o dock):
private val host by lazy { NavHostFragment.create(R.navigation.navigation_graph) }
E no método onCreate (), defina:
supportFragmentManager.beginTransaction() .replace(R.id.fragment_container, host) .setPrimaryNavigationFragment(host) .commit()
O toque final - adicione à onStart () MainActivity um objeto da classe NavController, que permite a transição entre fragmentos, escolhendo um ou outro objeto da barra de navegação:
override fun onStart() { super.onStart() val navController = host.findNavController() findViewById<BottomNavigationView>(R.id.bottom_nav_view)?.setupWithNavController(navController) navController.addOnDestinationChangedListener{_, destination, _ -> val dest: String = try { resources.getResourceName(destination.id) } catch (e: Resources.NotFoundException) { Integer.toString(destination.id) } Log.d("NavigationActivity", "Navigated to $dest") } }
Inicie o aplicativo e veja mais ...