(Deprecated) A custom view component that mimics the new Material Design Bottom Navigation pattern.
I don’t have time to maintain this anymore. I basically wrote the whole library in a rush, without tests, while being a serious expert beginner at the time. As a result, there’s a lot of unpredictable moving parts and the tests probably aren’t that great either. Don’t really know, since I haven’t touched this in ages.
I’d recommend you to use the official BottomNavigationView from Google and urge them to implement the features you need. Or use another 3rd party library.
The latest version before that can be found in the v1 branch
A custom view component that mimics the new Material Design Bottom Navigation pattern.
Nope. The minSDK version is API level 11 (Honeycomb).
compile 'com.roughike:bottom-bar:2.3.1'
Maven:
<dependency>
<groupId>com.roughike</groupId>
<artifactId>bottom-bar</artifactId>
<version>2.3.1</version>
<type>pom</type>
</dependency>
You can add items by writing a XML resource file.
The icons must be fully opaque, solid black color, 24dp and with no padding. For example, with Android Asset Studio Generic Icon generator, select “TRIM” and make sure the padding is 0dp. Here’s what your icons should look like:
Define your tabs in an XML resource file.
res/xml/bottombar_tabs.xml:
<tabs>
<tab
id="@+id/tab_favorites"
icon="@drawable/ic_favorites"
title="Favorites" />
<tab
id="@+id/tab_nearby"
icon="@drawable/ic_nearby"
title="Nearby" />
<tab
id="@+id/tab_friends"
icon="@drawable/ic_friends"
title="Friends" />
</tabs>
Then, add the BottomBar to your layout and give it a resource id for your tabs xml file.
layout/activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- This could be your fragment container, or something -->
<FrameLayout
android:id="@+id/contentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/bottomBar" />
<com.roughike.bottombar.BottomBar
android:id="@+id/bottomBar"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
app:bb_tabXmlResource="@xml/bottombar_tabs" />
</RelativeLayout>
By default, the tabs don’t do anything unless you listen for selection events and do something when the tabs are selected.
MainActivity.java:
public class MainActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomBar bottomBar = (BottomBar) findViewById(R.id.bottomBar);
bottomBar.setOnTabSelectListener(new OnTabSelectListener() {
@Override
public void onTabSelected(@IdRes int tabId) {
if (tabId == R.id.tab_favorites) {
// The tab with id R.id.tab_favorites was selected,
// change your content accordingly.
}
}
});
}
}
If you want to listen for reselection events, here’s how you do it:
bottomBar.setOnTabReselectListener(new OnTabReselectListener() {
@Override
public void onTabReSelected(@IdRes int tabId) {
if (tabId == R.id.tab_favorites) {
// The tab with id R.id.tab_favorites was reselected,
// change your content accordingly.
}
}
});
If you want to conditionally cancel selection of any tab, you absolutely can. Just assign a TabSelectionInterceptor
to the BottomBar, and return true from the shouldInterceptTabSelection()
method.
bottomBar.setTabSelectionInterceptor(new TabSelectionInterceptor() {
@Override
public boolean shouldInterceptTabSelection(@IdRes int oldTabId, @IdRes int newTabId) {
if (newTabId == R.id.tab_pro_feature && !userHasProVersion()) {
startProVersionPurchaseFlow();
return true;
}
return false;
}
});
If you want to have different icon when a specific tab is selected, just use state list drawables.
res/drawable/my_tab_icon.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_myicon_selected" android:state_selected="true" />
<item android:drawable="@drawable/ic_myicon_default" android:state_selected="false" />
</selector>
res/xml/bottombar_tabs.xml
...
<tab
id="@+id/tab_favorites"
icon="@drawable/my_tab_icon"
title="Favorites" />
<!-- You can use @color resources too! -->
...
Just add barColorWhenSelected
to each tab. When that tab is selected, the whole BottomBar background color is changed with a nice animation.
res/xml/bottombar_tabs.xml
<tabs>
<tab
id="@+id/tab_favorites"
icon="@drawable/ic_favorites"
title="Favorites"
barColorWhenSelected="#5D4037" />
<!-- You can use @color resources too! -->
</tabs>
First, define a style that is a child of your main application theme:
res/values-v21/styles.xml
<style name="AppTheme.TransNav" parent="AppTheme">
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
</style>
You’ll also have to make a stub version of the same theme to avoid crashes in previous API levels than Lollipop:
res/values/styles.xml
<style name="AppTheme.TransNav" parent="AppTheme" />
Also include the same stub in your values-land-v21.xml
to avoid transparent navbar and weird behavior on landscape.
res/values-land-v21.xml:
<style name="AppTheme.TransNav" parent="AppTheme" />
Apply the theme in AndroidManifest.xml
for your Activity.
AndroidManifest.xml:
<activity android:name=".MyAwesomeActivity" android:theme="@style/AppTheme.TransNav" />
Finally, set bb_behavior
to include the underNavbar
flag and you’re good to go!
activity_my_awesome.xml:
<com.roughike.bottombar.BottomBar
android:id="@+id/bottomBar"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_alignParentBottom="true"
app:bb_tabXmlResource="@xml/my_awesome_bottombar_tabs"
app:bb_behavior="underNavbar" />
Specify a different layout for your activity in res/layout-sw600dp
folder and set bb_tabletMode
to true.
res/layout-sw600dp/activity_main.xml:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.roughike.bottombar.BottomBar
android:id="@+id/bottomBar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
app:bb_tabXmlResource="@xml/bottombar_tabs_three"
app:bb_tabletMode="true" />
<!-- This could be your fragment container, or something -->
<FrameLayout
android:id="@+id/contentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="@+id/bottomBar" />
</RelativeLayout>
Easy-peasy!
activity_main.xml:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.NestedScrollView
android:id="@+id/myScrollingContent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Your loooooong scrolling content here. -->
</android.support.v4.widget.NestedScrollView>
<com.roughike.bottombar.BottomBar
android:id="@+id/bottomBar"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_gravity="bottom"
app:bb_tabXmlResource="@xml/bottombar_tabs_three"
app:bb_behavior="shy"/>
</android.support.design.widget.CoordinatorLayout>
You can easily add badges for showing an unread message count or new items / whatever you like.
BottomBarTab nearby = bottomBar.getTabWithId(R.id.tab_nearby);
nearby.setBadgeCount(5);
// Remove the badge when you're done with it.
nearby.removeBadge/();
<com.roughike.bottombar.BottomBar
android:id="@+id/bottomBar"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
app:bb_tabXmlResource="@xml/bottombar_tabs_three"
app:bb_tabletMode="true"
app:bb_behavior="shifting|shy|underNavbar"
app:bb_inActiveTabAlpha="0.6"
app:bb_activeTabAlpha="1"
app:bb_inActiveTabColor="#222222"
app:bb_activeTabColor="@color/colorPrimary"
app:bb_badgesHideWhenActive="true"
app:bb_titleTextAppearance="@style/MyTextAppearance"
app:bb_titleTypeFace="fonts/MySuperDuperFont.ttf"
app:bb_showShadow="true" />
values/xml/
shifting
: the selected tab is wider than the rest. shy
: put the BottomBar inside a CoordinatorLayout and it'll automatically hide on scroll! underNavbar
: draw the BottomBar under the navBar!fonts/MySuperDuperFont.ttf
. In that case your font path would look like src/main/assets/fonts/MySuperDuperFont.ttf
, but you only need to provide fonts/MySuperDuperFont.ttf
, as the asset folder will be auto-filled for you.<tab
id="@+id/tab_recents"
title="Recents"
icon="@drawable/empty_icon"
inActiveColor="#00FF00"
activeColor="#FF0000"
barColorWhenSelected="#FF0000"
badgeBackgroundColor="#FF0000"
badgeHidesWhenActive="true" />
Send me a pull request with modified README.md to get a shoutout!
Feel free to create issues and pull requests.
When creating pull requests, more is more: I’d like to see ten small pull requests separated by feature rather than all those combined into a huge one.
BottomBar library for Android
Copyright (c) 2016 Iiro Krankka (http://github.com/roughike).
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.