Creation of the Bottom Navigation Bar on Kotlin using Anko

Starting a new project, I decided to try to completely abandon the XML files, on the basis of which layouts are formed, and create screens using the Anko library. Having little experience in developing for Android (about 2 years) and even less experience writing code in Kotlin (a little over six months), I immediately faced the problem of including the Navigation Architecture Component in the application, or rather rendering the Bottom Navigation Bar created by BottomNavigationView .


First of all, I turned to the Internet to find a possible solution. But all the articles I found with varying degrees of clarity told about how to work with navigation components and none (of those whose articles I studied) did it on Anko. Having solved the task, I offer the community my option to create a Bottom Navigation Bar.


The complete code can be viewed here.
I skip the stage of creating a new project in Android Studio, I just note the following dependencies for working with Anko and Navigation Architecture Component in build.gradle at the module level:


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'

The next step is to create the structure of the future application. To draw the main activity, instead of the xml-file, create the MainActivityUI class inherited from the AnkoComponent interface:


class MainActivityUI: AnkoComponent {
    override fun createView(ui: AnkoContext): View = with(ui) {
        constraintLayout {  }
    }
}

In the MainActivity class, setContentView (R.layout.activity_main) is replaced by MainActivityUI (). SetContentView (this).


Then we create package fragments in which our fragments and package ui will lie to place the classes responsible for rendering screens of the corresponding fragments. This is the structure of the project:


fragments
        ui
            HomeUI
            UsersUI
            DetailsUI
            MoreUI
        HomeFragment
        UsersFragment
        DetailsFragment
        MoreFragment

Now we’ll deal directly with the navigation and the creation of the Bottom Navigation Bar.
A detailed description of the inclusion of new navigation components and a description of the work in the Navigation Editor can be found on the documentation page here . To create a file (graph) for navigation between application screens, you need to add another folder to the res folder, namely navigation, and add navigation_graph.xml file to it already. For this project, it will be like this:



To display the Bar itself, you need to create another resource folder, namely menu. It contains the file responsible for the visible part of the bar. This is how it looks in this project:



It is time to put everything together and see how it works.


Add a container for fragments in MainActivityUI, and also define a container for the navigation bar.



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
            )
        }
    }
}

It should be specially noted that bottomNavigation in this example is an extantion function, which has the following form:


inline fun ViewManager.bottomNavigation(init: BottomNavigationView.() -> Unit = {}) =
        ankoView({ BottomNavigationView(it) }, theme = 0, init = init)

Now in MainActivity you need to define the NavHostFragment object (see the dock):


private val host by lazy { NavHostFragment.create(R.navigation.navigation_graph) }

And in the onCreate () method, define:


supportFragmentManager.beginTransaction()
    .replace(R.id.fragment_container, host)
    .setPrimaryNavigationFragment(host)
    .commit()

The final touch - add to the onStart () MainActivity an object of the NavController class, which allows you to transition between fragments by choosing one or another navigation bar object:


override fun onStart() {
    super.onStart()
    val navController = host.findNavController()
    findViewById(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")
    }
}

Launch the application and vois là ...


Screenshot


Also popular now: