In Mar 2016, Google has released a new component in Material Design Technology called Bottom Navigation Bar - providing guidance for a pattern that had already seen success on iOS. Bottom bar/tabs are understandably controversial: Android design always recommended having tabs at the top of the screen, and usage of tabs at the bottom was looked at as lazy mimicking of iOS design. Yet Google themselves began using the pattern last year with Google+, and then followed it up with Google Photos earlier this year.
However, Bottom Navigation Bar also has excellent specific usage, like we can see at Google+ and Google Photo apps. But, in Android SDK, there is none official widget or of document to show us a solution to make this design! So, up to now, the best way is using a third-party library to create it.
Through this post, I would like to present a simple/popular library called Bottom-Bar (developed by Iiro Krankka) which be able to creating this component after a few step.
DEMO VIDEO:
The simplest way to use this library is adding it's dependency to your application level
The object to building the Bottom Navigation bar is
Some important method:
By using
As you can see outputs above, the bottom navigation bar overlaps the main view content, so in order to avoid this inconvenience, we should hide it when scrolling screen. Similar with another scrolling trick in Material Design tech, we must use
More over, you can easily add badges for showing an unread message count or new items/ /whatever you like. Read Badge guide of this library to learn the way to make this output:
What do you think about bottom navigation? An improvement over tabs or change for change’s sake? This component is controversial in Android design but we can not deny its usefulness. Beside that, there are 2 widget that similar with it called Bottom Sheet and Modal Bottom Sheet, I had 2 posts about them (following links), you should take a glance. After all, this is an emerging pattern (or re-emerging, depending on who you ask) on Android, so the nuances of how the bar should be used aren't set in stone. As always, developers and designers should weigh what makes sense in their own context for their own product, using the guidelines as general best practices for any patterns they find to be necessary.
Finally, Google developers released Design Support Library version 25.0.0 and providing a new widget named
References:
However, Bottom Navigation Bar also has excellent specific usage, like we can see at Google+ and Google Photo apps. But, in Android SDK, there is none official widget or of document to show us a solution to make this design! So, up to now, the best way is using a third-party library to create it.
Through this post, I would like to present a simple/popular library called Bottom-Bar (developed by Iiro Krankka) which be able to creating this component after a few step.
DEMO VIDEO:
Importing library
build.gradle:
compile 'com.roughike:bottom-bar:1.4.0.1'
Now, I will make a demo project about using it to create the Bottom Navigation Bar, it's source code now available on Github.
Simple Bottom Bar with custom tabs color and background
BottomBar. It's not a UI widget, so we don't put it in a xml file, it will be created in Java code.Some important method:
attach(): Bind theBottomBarto the specified View's parent, and inflate your layout there. Useful when theBottomBaroverlaps some content that shouldn't be overlapped.setItems(menu_file_id): Set items (tabs) for thisBottomBarfrom menu file.- Handling any tab selected/reselected by called
setOnMenuTabClickListener(). The parameter here isOnMenuTabClickListenerinterface and there are 2 methods that you must override: onMenuTabSelected(): called whenBottomBarTabfirst selected.onMenuTabReSelected(): called whenBottomBarTabreselected.
bottom_bar_menu.xml
This is a full code for an activity to creating a Bottom Navigation Bar with custom background and the tabs color will be changed when it's selected:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/like"
android:icon="@drawable/like"
android:title="Like" />
<item
android:id="@+id/love"
android:icon="@drawable/love"
android:title="Love" />
<item
android:id="@+id/sad"
android:icon="@drawable/sad"
android:title="Sad" />
<item
android:id="@+id/angry"
android:icon="@drawable/angry"
android:title="Angry" />
</menu>
SimpleActivity.java
Running this activity, we'l have this output:
package info.devexchanges.bottomnavigation;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;
import com.roughike.bottombar.BottomBar;
import com.roughike.bottombar.OnMenuTabClickListener;
public class SimpleActivity extends AppCompatActivity {
private BottomBar mBottomBar;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple);
// Customize the colors here
mBottomBar = BottomBar.attach(this, savedInstanceState,
Color.parseColor("#f2f2f2"), // Background Color
ContextCompat.getColor(this, R.color.colorAccent), // Tab Item Color
0.25f); // Tab Item Alpha
mBottomBar.setItems(R.menu.bottom_bar_menu);
mBottomBar.setOnMenuTabClickListener(new OnMenuTabClickListener() {
@Override
public void onMenuTabSelected(@IdRes int menuItemId) {
showToast(menuItemId, false);
}
@Override
public void onMenuTabReSelected(@IdRes int menuItemId) {
showToast(menuItemId, true);
}
});
}
private void showToast(int menuId, boolean isReselected) {
if (menuId == R.id.like) {
if (isReselected) {
show("Tab Like Reselected!");
} else {
show("You like this!");
}
} else if (menuId == R.id.love) {
if (isReselected) {
show("Tab Love Reselected!");
} else show("You love this!");
} else if (menuId == R.id.sad) {
if (isReselected) {
show("Tab Sad Reselected");
} else show("You felt sad when reading this content!");
} else if (isReselected) {
show("Tab Angry Reselected!");
} else show("You felt angry when reading this!");
}
private void show(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// Necessary to restore the BottomBar's state, otherwise we would
// lose the current tab on orientation change.
mBottomBar.onSaveInstanceState(outState);
}
}
| "Love" tab first selected |
| "Love" tab selected |
Changing Bottom Bar background when tab selected
mapColorForTab() method, your BottomBar background when each tab selected. See this activity code:
ChangeBackgroundActivity.java
Running this activity, we'll have this output:
package info.devexchanges.bottomnavigation;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import com.roughike.bottombar.BottomBar;
import com.roughike.bottombar.OnMenuTabClickListener;
public class ChangeBackgroundActivity extends AppCompatActivity {
private BottomBar bottomBar;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple);
bottomBar = BottomBar.attach(this, savedInstanceState);
bottomBar.setItems(R.menu.bottom_bar_menu);
bottomBar.setOnMenuTabClickListener(new OnMenuTabClickListener() {
@Override
public void onMenuTabSelected(@IdRes int menuItemId) {
}
@Override
public void onMenuTabReSelected(@IdRes int menuItemId) {
}
});
// Setting colors for different tabs when there's more than three of them.
// You can set colors for tabs in three different ways as shown below.
bottomBar.mapColorForTab(0, ContextCompat.getColor(this, R.color.colorAccent));
bottomBar.mapColorForTab(1, 0xFF5D4037);
bottomBar.mapColorForTab(2, "#7B1FA2");
bottomBar.mapColorForTab(3, "#FF5252");
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
bottomBar.onSaveInstanceState(outState);
}
}
Customizing Navigation Bar behavior
CoordinatorLayout as the root container in the activity layout (xml file) like this:
activity_behavior.xml
Change from <?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/myCoordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.v4.widget.NestedScrollView
android:id="@+id/myScrollingContent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="@string/long_text" />
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
BottomBar.attach() to BottomBar.attachShy() in activity Java code:
BehaviorActivity.java
We'll have this output:
package info.devexchanges.bottomnavigation;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.Nullable;
import android.support.design.widget.CoordinatorLayout;
import android.support.v7.app.AppCompatActivity;
import com.roughike.bottombar.BottomBar;
import com.roughike.bottombar.OnMenuTabClickListener;
public class BehaviorActivity extends AppCompatActivity {
private BottomBar bottomBar;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_behavior);
bottomBar = BottomBar.attachShy((CoordinatorLayout) findViewById(R.id.myCoordinator),
findViewById(R.id.myScrollingContent), savedInstanceState);
bottomBar.setItems(R.menu.bottom_bar_menu);
bottomBar.setOnMenuTabClickListener(new OnMenuTabClickListener() {
@Override
public void onMenuTabSelected(@IdRes int menuItemId) {
}
@Override
public void onMenuTabReSelected(@IdRes int menuItemId) {
}
});
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
bottomBar.onSaveInstanceState(outState);
}
}
More over, you can easily add badges for showing an unread message count or new items/ /whatever you like. Read Badge guide of this library to learn the way to make this output:
Conclusions
Update: Bottom Navigation View in Android SDK
BottomNavigationView. With this, we now have an official way to build a bottom navigation view which not depend on a third-party library. Please read my UPDATE POST to learning this new solution.References:
- Navigation Bottom View in Google Design
- Official library page on Github
- About this component on AndroidPolice
- Bottom Sheet tutorial
- Modal Bottom Sheet tutorial