{"id":32749,"date":"2017-08-07T12:08:55","date_gmt":"2017-08-07T19:08:55","guid":{"rendered":"https:\/\/blog.xamarin.com\/?p=32749"},"modified":"2019-03-25T19:24:59","modified_gmt":"2019-03-26T03:24:59","slug":"exploring-androids-bottom-navigation-view","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/exploring-androids-bottom-navigation-view\/","title":{"rendered":"Exploring Android&#8217;s Bottom Navigation View"},"content":{"rendered":"<p>\t\t\t\tThe debate over whether tabs should go on the top or the bottom of a screen has raged for nearly a decade. Android has always preferred to use tabs as a filtering mechanism on the top of a page, while iOS has used bottom tabs as the main source of navigation. Now, with the addition of the <a href=\"https:\/\/material.io\/guidelines\/components\/bottom-navigation.html\" target=\"_blank\">Bottom Navigation View<\/a> in the Support Design library, Android developers have the choice of where their main navigation comes from in their applications.<\/p>\n<p>Bottom navigation bars make it easy for your users to navigate through your top-level views with a single tap, compared the the navigation drawer that flies out from the side and has been a standard when there are a lot of different sections to an app. Today, I&#8217;ll walk through when it&#8217;s best to use bottom navigation in your app, how to implement it, and how to customize it to your liking. <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/Bottom-Navigation.png\" alt=\"\" width=\"400\" class=\"aligncenter size-full wp-image-32750\" \/><\/p>\n<p>The core experience of bottom navigation is designed for use on mobile phone devices that allows users to swap between pages easily. Some questions for if you should use bottom navigation are: <\/p>\n<ul>\n<li>Does your app have 3&ndash;5 top-level pages?<\/li>\n<li>Do your top-level pages need direct access?<\/li>\n<\/ul>\n<p>If your application has more than five pages, it&#8217;s best to stick with the <a href=\"https:\/\/blog.xamarin.com\/add-beautiful-material-design-with-the-android-support-design-library\/\" target=\"_blank\">navigation drawer<\/a>; if you have less than three, stick with standard top tabs.<\/p>\n<h2>Getting Started with Bottom Navigation View<\/h2>\n<p>To get started with the new Bottom Navigation View, we&#8217;ll want to make sure that we have our Android application updated with an <a href=\"https:\/\/blog.xamarin.com\/android-tips-hello-appcompatactivity-goodbye-actionbaractivity\/\" target=\"_blank\">AppCompat Activity<\/a> and upgraded to the <a href=\"https:\/\/blog.xamarin.com\/mastering-android-support-libraries\/\" target=\"_blank\">latest Support Libraries<\/a>. With that, we can now install the <i><a href=\"https:\/\/www.nuget.org\/packages\/Xamarin.Android.Support.Design\" target=\"_blank\">Xamarin.Android.Support.Design<\/a><\/i> NuGet package (current version 25.3.1) into our Android project at our set up.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/Support-NuGet.png\" alt=\"\" width=\"887\" height=\"190\" class=\"aligncenter size-full wp-image-32755\" \/><\/p>\n<h3>Adding Tab\/Menu Items<\/h3>\n<p>We must define the items that will be displayed before we add the <code>BottomNavigationView<\/code> control. This is controlled similarly to the <code>NavigationDrawer<\/code>, with a menu defined in xml. We can create a new menu folder in the <code>Resources<\/code> directory and add a new xml file. I created <code>bottom_navigation_main.xml<\/code> in <code>Resources\/menu\/<\/code> and downloaded a few tab icons from the <a href=\"https:\/\/romannurik.github.io\/AndroidAssetStudio\/\" target=\"_blank\">Android Asset Studio<\/a>, which are 24dp x 24dp.<\/p>\n<pre class=\"lang:xml decode:true\"><code>&#060;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;\r\n&#060;menu xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\"\r\n    xmlns:app=\"http:\/\/schemas.android.com\/apk\/res-auto\"&gt;\r\n  &#060;item\r\n      android:id=\"@+id\/menu_home\"\r\n      android:enabled=\"true\"\r\n      android:icon=\"@drawable\/ic_action_home\"\r\n      android:title=\"@string\/tab1_title\"\r\n      app:showAsAction=\"ifRoom\" \/&gt;\r\n\r\n  &#060;item\r\n      android:id=\"@+id\/menu_audio\"\r\n      android:enabled=\"true\"\r\n      android:icon=\"@drawable\/ic_action_audiotrack\"\r\n      android:title=\"@string\/tab2_title\"\r\n      app:showAsAction=\"ifRoom\" \/&gt;\r\n\r\n  &#060;item\r\n      android:id=\"@+id\/menu_video\"\r\n      android:enabled=\"true\"\r\n      android:icon=\"@drawable\/ic_action_videocam\"\r\n      android:title=\"@string\/tab3_title\"\r\n      app:showAsAction=\"ifRoom\" \/&gt;\r\n&#060;\/menu&gt;<\/code><\/pre>\n<h3>Adding a Bottom Navigation View<\/h3>\n<p>Bottom navigation works by replacing fragments when one of the items is selected. This means that our Android xml should also have a <code>FrameLayout<\/code> to swap in and out the fragments that will be displayed. Our xml will look something like this in its basic form:<\/p>\n<pre class=\"lang:xml decode:true\"> &#060;RelativeLayout\r\n    xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\"\r\n    xmlns:app=\"http:\/\/schemas.android.com\/apk\/res-auto\"\r\n    android:id=\"@+id\/activity_main\"\r\n    android:layout_width=\"match_parent\"\r\n    android:layout_height=\"match_parent\"&gt;\r\n    &#060;FrameLayout\r\n        android:id=\"@+id\/content_frame\"\r\n        android:layout_width=\"match_parent\"\r\n        android:layout_height=\"match_parent\" \r\n        android:layout_above=\"@+id\/bottom_navigation\"\/&gt;\r\n    &#060;android.support.design.widget.BottomNavigationView\r\n      android:id=\"@+id\/bottom_navigation\"\r\n      android:layout_width=\"match_parent\"\r\n      android:layout_height=\"56dp\"\r\n      android:layout_gravity=\"start\"\r\n      android:layout_alignParentBottom=\"true\"\r\n      android:background=\"@android:color\/white\"\r\n      app:elevation=\"16dp\"\r\n      app:menu=\"@menu\/bottom_navigation_main\" \/&gt;\r\n      &#060;!-- Note: background color is required to get elevation --&gt;\r\n  &#060;\/RelativeLayout&gt;<\/pre>\n<p>We can define an <code>elevation<\/code> so the bottom navigation is lifted off the page with a nice drop shadow, and we define our items in the navigation view with the <code>menu<\/code> property that is referencing the menu we created earlier.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/BottomNavigationInAction.gif\" alt=\"\" width=\"492\" height=\"108\" class=\"aligncenter size-full wp-image-32756\" \/><\/p>\n<p>As we can see, the default will automatically apply our <code>primary<\/code> color and gray out the deselected items.<\/p>\n<h3>Handling Click Events<\/h3>\n<p>Now it&#8217;s time for us to actually handle the click events and set our content. In this example, I have three different fragments that simply load an Android xml file that displays the current index it&#8217;s on. We can create a simple method to replace the current fragment based on the ID that was set in the menu xml in our Main Activity:<\/p>\n<pre class=\"lang:c# decode:true\">void LoadFragment(int id)\r\n{\r\n    Android.Support.V4.App.Fragment fragment = null;\r\n    switch (id)\r\n    {\r\n        case Resource.Id.menu_home:\r\n            fragment = Fragment1.NewInstance();\r\n            break;\r\n        case Resource.Id.menu_audio:\r\n            fragment = Fragment2.NewInstance();\r\n            break;\r\n        case Resource.Id.menu_video:\r\n            fragment = Fragment3.NewInstance();\r\n            break;\r\n    }\r\n\r\n    if (fragment == null)\r\n        return;\r\n\r\n    SupportFragmentManager.BeginTransaction()\r\n        .Replace(Resource.Id.content_frame, fragment)\r\n        .Commit();\r\n}<\/pre>\n<p>Now we can load our xml, find the <code>BottomNavigationView<\/code>, and register for a <code>NavigationItemSelected<\/code> event:<\/p>\n<pre class=\"lang:c# decode:true\">BottomNavigationView bottomNavigation;\r\nprotected override void OnCreate(Bundle bundle)\r\n{\r\n    base.OnCreate(bundle);\r\n    SetContentView(Resource.Layout.main);\r\n    var toolbar = FindViewById&#060;Android.Support.V7.Widget.Toolbar&gt;(Resource.Id.toolbar);\r\n    if (toolbar != null)\r\n    {\r\n        SetSupportActionBar(toolbar);\r\n        SupportActionBar.SetDisplayHomeAsUpEnabled(false);\r\n        SupportActionBar.SetHomeButtonEnabled(false);\r\n    }\r\n\r\n    bottomNavigation = FindViewById&#060;BottomNavigationView&gt;(Resource.Id.bottom_navigation);\r\n\r\n    bottomNavigation.NavigationItemSelected += BottomNavigation_NavigationItemSelected;\r\n\r\n    \/\/ Load the first fragment on creation\r\n    LoadFragment(Resource.Id.menu_home);\r\n}\r\n\r\nprivate void BottomNavigation_NavigationItemSelected(object sender, BottomNavigationView.NavigationItemSelectedEventArgs e)\r\n{\r\n    LoadFragment(e.Item.ItemId);\r\n}<\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/BottomNavigationInActionWithFragments.gif\" alt=\"\" width=\"492\" height=\"760\" class=\"aligncenter size-full wp-image-32757\" \/><\/p>\n<h2>Adding Color<\/h2>\n<p>Google&#8217;s recommendation is to simply use the default white or black background color and primary tint of icons if your app is using default themes and your Toolbar is already tinted. If you wish to set the color of the bottom navigation, then it&#8217;s recommended to make the icon and text of the current action black or white. There are two additional properties, <code>app:itemIconTint<\/code> and <code>app:itemTextColor<\/code>, that can be set to handle this. Setting them directly to a specific color is what you probably think you want to do, but an immediate issue will present itself where it also sets the deselected state to the same color. For instance, if I set these three properties:<\/p>\n<pre class=\"lang:xml decode:true\">android:background=\"@color\/primary\"\r\napp:itemIconTint=\"@android:color\/white\"\r\napp:itemTextColor=\"@android:color\/white\"<\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/ColorIssues.png\" alt=\"\" width=\"492\" height=\"90\" class=\"aligncenter size-full wp-image-32758\" \/><\/p>\n<p>To fix this, we just have to create a selector defined in our <code>drawable<\/code> folder that will set the color based on the state in a new xml file; I called mine <code>nav_item_colors.xml<\/code>:<\/p>\n<pre class=\"lang:xml decode:true\">\r\n&#060;selector xmlns:android=\"http:\/\/schemas.android.com\/apk\/res\/android\"&gt;\r\n  &#060;item android:state_checked=\"true\" android:color=\"@android:color\/white\" \/&gt;\r\n  &#060;item android:color=\"#80FFFFFF\"  \/&gt;\r\n&#060;\/selector&gt;<\/pre>\n<p>Now, back in our <code>BottomNavigationView<\/code>, we can use the new selector colors:<\/p>\n<pre class=\"lang:xml decode:true\">android:background=\"@color\/primary\"\r\napp:itemIconTint=\"@drawable\/nav_item_colors\"\r\napp:itemTextColor=\"@drawable\/nav_item_colors\"<\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/BottomNavigationColor.gif\" alt=\"\" width=\"492\" height=\"92\" class=\"aligncenter size-full wp-image-32759\" \/><\/p>\n<p>Absolutely lovely!<\/p>\n<h2>Learn More<\/h2>\n<p>To learn more about bottom navigation in Android, be sure to read through the <a href=\"https:\/\/material.io\/guidelines\/components\/bottom-navigation.html\" target=\"_blank\">Material Design Guidelines<\/a> for all the &#8220;dos and don&#8217;ts&#8221; of using it. You can also grab a full sample and other samples of navigation from my <a href=\"https:\/\/github.com\/jamesmontemagno\/Xamarin-Templates\/tree\/master\/Xamarin.Android-Templates\/Projects\" target=\"_blank\">GitHub repo<\/a>.\t\t<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The debate over whether tabs should go on the top or the bottom of a screen has raged for nearly a decade. Android has always preferred to use tabs as a filtering mechanism on the top of a page, while iOS has used bottom tabs as the main source of navigation. Now, with the addition of the <a href=\"https:\/\/material.io\/guidelines\/components\/bottom-navigation.html\" target=\"_blank\">Bottom Navigation View<\/a> in the Support Design library, Android developers have the choice of where their main navigation comes from in their applications.<\/p>\n","protected":false},"author":544,"featured_media":41023,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[313,2,556],"tags":[5,784,1063,4],"class_list":["post-32749","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-android","category-developers","category-integrations","tag-android","tag-support-libraries","tag-tabs","tag-xamarin-platform"],"acf":[],"blog_post_summary":"<p>The debate over whether tabs should go on the top or the bottom of a screen has raged for nearly a decade. Android has always preferred to use tabs as a filtering mechanism on the top of a page, while iOS has used bottom tabs as the main source of navigation. Now, with the addition of the <a href=\"https:\/\/material.io\/guidelines\/components\/bottom-navigation.html\" target=\"_blank\">Bottom Navigation View<\/a> in the Support Design library, Android developers have the choice of where their main navigation comes from in their applications.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/32749","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/users\/544"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=32749"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/32749\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media\/41023"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=32749"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=32749"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=32749"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}