# BottomNavigationViewEx: extending Android's BottomNavigationView with shifting, sizing and ViewPager wiring

> BottomNavigationViewEx is a Java widget that subclasses the Android design library's BottomNavigationView and exposes the private item views, animation flags and sizing calls that the stock class hides. It suits teams already committed to the support design library; it does not fit projects on Material 3 or Compose.

**ittianyu/BottomNavigationViewEx** — An android lib for enhancing BottomNavigationView. 一个增强BottomNavigationView的安卓库。

- Repository: https://github.com/ittianyu/BottomNavigationViewEx
- Stars: 3,465 · Forks: 549
- Language: Java
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/ittianyu-bottomnavigationviewex

## The gap BottomNavigationViewEx fills in the stock design library widget

The stock BottomNavigationView in the Android design library gives you a menu, an item icon tint and an item text colour, and not much else. Item views are private. The shifting behaviour that animates a selected item wider than its neighbours is decided internally from the item count, with no public switch. If you want the icon centred with a different top margin, or a large label on the checked item and a small label on the rest, you are left reaching into the view hierarchy with findViewById on generated ids.

BottomNavigationViewEx is a subclass that keeps the same XML tag shape and the same menu attribute, then adds the missing switches. The feature table in the README lists the surface: enableAnimation, enableShiftingMode, enableItemShiftingMode, setIconSize, setIconSizeAt, setIconMarginTop, setIconsMarginTop, setLargeTextSize, setSmallTextSize, setTextSize, setTypeface, setItemBackground, setItemHeight, setIconTintList, setTextTintList, plus getters for the private item views and labels. The audience is an app developer on the support design library who has already hit one of those walls and does not want to fork the widget.

The design choice worth noting is that this is a subclass, not a wrapper and not a reimplementation. That keeps migration cheap, but it also means every getter is coupled to the private field names of the version it was compiled against. A design library release that renames mButton or restructures the item layout breaks the getters rather than failing at compile time.

## How the widget reaches the private item views and what each animation flag actually toggles

The repository layout puts the library in widget/ and a demo app in app/, with the whole widget in a single file: widget/src/main/java/com/ittianyu/bottomnavigationviewex/BottomNavigationViewEx.java. That one file is the mechanism. It extends BottomNavigationView, calls the superclass constructor chain, and then reflects or casts into the internal menu view to obtain the per-item button views that the public API does not expose.

The README describes each item as carrying two labels, one large and one small. The small label is shown when the item is in its normal state and the large one when the item is checked. setLargeTextSize, setSmallTextSize and setTextSize act on those two TextViews separately; setTypeface applies to both. That is the reason the sizing API has three entry points instead of one, and it is also the reason the effect is not visible until an item is selected.

The three animation flags are independent, which the README spells out. enableAnimation controls the click animation, meaning text scale and icon movement in no item shifting mode. enableItemShiftingMode controls whether an individual item animates when it becomes selected; with it off the item text is always shown. enableShiftingMode controls the navigation level, whether items have different widths at all. The README states the default for the latter two is true when the item count is greater than three, and enableAnimation defaults to true. Setting all three to false is the documented way to get a static bar.

## Installing BottomNavigationViewEx from JitPack and wiring a first bar

The library is distributed through JitPack, not Maven Central. The README requires compileSdkVersion 25 or higher. Step one is adding both repositories to the root build.gradle, because the design library itself comes from maven.google.com.

```groovy
allprojects {
	repositories {
		...
		maven { url "https://jitpack.io" }
		maven { url "https://maven.google.com" }
	}
}
```

Step two is the dependency. The README gives three variants. For support library 28 the coordinates are com.github.ittianyu:BottomNavigationViewEx:2.0.4 alongside com.android.support:design:28.0.0. For support library 25 or 26 the older compile line with version 1.2.4 is documented. For AndroidX the README says to use the new version and add two properties to gradle.properties.

```groovy
implementation 'com.github.ittianyu:BottomNavigationViewEx:2.0.4'
implementation "com.android.support:design:28.0.0"
```

```groovy
android.useAndroidX=true
android.enableJetifier=true
```

There is also a manual route: download BottomNavigationViewEx.java from the repository and copy it into your project, which is a real option for a single-file widget and avoids the JitPack round trip.

In XML the tag is the full class name, and the menu attribute works as it does on the stock widget. The README's example sets itemIconTint and itemTextColor to the same selector.

```xml
<com.ittianyu.bottomnavigationviewex.BottomNavigationViewEx
    android:id="@+id/bnve"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:background="@color/colorPrimary"
    app:itemIconTint="@color/selector_item_color"
    app:itemTextColor="@color/selector_item_color"
    app:menu="@menu/menu_navigation_with_view_pager" />
```

In the Activity you cast the findViewById result to BottomNavigationViewEx and call the switches. The README's first recipe disables everything: enableAnimation(false), enableShiftingMode(false), enableItemShiftingMode(false). If the bar still shifts after that, the flag you missed is the one you did not call; they are independent.

## Binding a ViewPager and adding a badge on top of the widget

setupWithViewPager is the method that earns the library a place in a tabbed layout. The README says it links the given ViewPager and the BottomNavigationViewEx so that changes in one are reflected in the other, including scroll state changes and clicks. The order matters: set the adapter on the ViewPager first, then call setupWithViewPager.

```java
adapter = new VpAdapter(getSupportFragmentManager(), fragments);
bind.vp.setAdapter(adapter);

bind.bnve.setupWithViewPager(bind.vp);
```

Badges are not part of the library. The README shows the pattern with a separate dependency, q.rorbin:badgeview:1.1.0, and a helper that calls getBottomNavigationItemView(position) to obtain the target view, then binds a QBadgeView to it with setBadgeNumber, setGravityOffset and bindTarget. This is where the getter earns its keep: without a public handle on the item view, a badge library has nothing to attach to. The README's snippet also wires an OnDragStateChangedListener, which is badge library API, not BottomNavigationViewEx API.

The README documents one visual caveat directly, in a line that reads "Attention: Something wrong on Android 4.x", with a screenshot named with_padding.jpg. The library advertises API 9+ in its badge, and the demo images cover padding, centred icons, smaller text, bigger icons, custom typeface, icon selectors, icon margin top and an unchecked-first-time state. Treat that Android 4.x note as the boundary the author chose to document rather than fix.

## Where BottomNavigationViewEx is the wrong tool

The strongest limitation is structural. This library enhances BottomNavigationView from com.android.support:design. That widget's shifting mode, where the selected item widens and unselected labels hide, is the behaviour the library's flags exist to control. Material 3's navigation bar removed shifting and made labels and icons uniform by default. If your app has moved to Material 3 or to Jetpack Compose, most of the flag surface here has nothing to switch off, and the sizing calls duplicate what a theme or a custom item layout would do.

The second limitation is version coupling. The getters reach into private fields of the design library. The README's feature table names them generically (getBottomNavigationItemView, getBottomNavigationItemViews, getLargeLabelAt, getSmallLabelAt, getMenuItemPosition, getOnNavigationItemSelectedListener), but a getter that returns a private field is only as stable as that field's name. Nothing in the repository pins a maximum design library version, and the README does not document a fallback when a getter returns null.

The third is the release rhythm. The most recent release listed is 2.0.4, published on 2019-04-05. The repository's last push was on 2026-04-24, so the code is being touched, but the published artifact has not moved in years. If you need a fix that landed after 2.0.4, you are building from source or copying the file, not pulling from JitPack. The README also does not document rollback or a compatibility matrix, so pinning the design library version next to the widget version is on you.

## What a Material Components or Compose migration changes about the comparison

The realistic alternative is not a competing third-party bar. It is the current first-party widget. Material Components for Android ships NavigationBar, and Compose ships a navigation bar composable. The difference in approach is not cosmetic. BottomNavigationViewEx subclasses an existing view and reaches inward to private fields to expose sizing and animation; Material 3 and Compose expose the same visual outcomes through public theming and layout APIs, so there is no private field to break.

The trade-off runs the other way too. A subclass keeps your XML, your menu resource and your existing Activity code. Moving to NavigationBar means adopting the Material Components theme and reworking the bar's attributes, and moving to Compose means rewriting the screen. For an app already on support library 28 that needs one thing, a per-item icon size or a separate large and small label size, subclassing is the cheaper change. For an app starting today, the private-field coupling is a liability you would be taking on deliberately.

If you want a bar with a different visual model entirely, the related searches around this project point at roughike's bottom-bar, BubbleNavigation and similar libraries. Those are separate projects with their own layouts and their own dependencies; the README here does not compare itself to any of them, and the comparison is not one this repository makes.

## Licence, upgrade cost and what to check before you pin a version

The repository is MIT licensed, with LICENSE.txt at the top level. MIT permits use in closed-source applications and requires the copyright notice and permission notice to be included. That is the extent of what the repository states; it is not legal advice, and if your organisation has a policy on attribution for vendored source, the manual-copy install path is the case where it applies most directly, because you are shipping the file inside your own tree.

The upgrade cost has two axes. The widget version is one: 2.0.4 is the last published artifact, and the README's AndroidX instructions (android.useAndroidX=true, android.enableJetifier=true) are the migration path from the support library coordinates. The design library version is the other, and it is the one that bites. BottomNavigationViewEx is compiled against a specific design library, and its getters read private members of that library's item views. Upgrading com.android.support:design without checking the widget is the failure mode to plan for.

Concretely, before pinning, read widget/src/main/java/com/ittianyu/bottomnavigationviewex/BottomNavigationViewEx.java and note which private fields each getter touches. Then decide whether you are comfortable calling those getters from production code, or whether you only need the setter side (icon size, text size, typeface, background, height), which is less exposed. The demo app in app/ is the place to reproduce a layout before committing to the dependency in a shipping module.

## Conclusion

Adopt BottomNavigationViewEx if your app is already built on com.android.support:design:28.0.0 or the AndroidX equivalent and you need per-item icon sizing, separate large and small label text sizes, or a one-line ViewPager binding. Do not adopt it for a new Compose or Material 3 project: the library wraps the old BottomNavigationView and the README's own feature table is built around shifting mode, which Material 3 removed. Before committing, open widget/src/main/java/com/ittianyu/bottomnavigationviewex/BottomNavigationViewEx.java and check which private fields each getter reads, because those are the fields a future design library release can rename.

## FAQ

### How do I install BottomNavigationViewEx in an Android project?

Add the JitPack and Google Maven repositories to the root build.gradle, then add the dependency com.github.ittianyu:BottomNavigationViewEx:2.0.4 with com.android.support:design:28.0.0. The README also documents copying BottomNavigationViewEx.java into your project manually.

### Does BottomNavigationViewEx work with AndroidX?

The README says to use the new version of the library and to add android.useAndroidX=true and android.enableJetifier=true to gradle.properties. It does not document a separate AndroidX artifact.

### How do I disable the shifting animation in BottomNavigationViewEx?

Call enableAnimation(false), enableShiftingMode(false) and enableItemShiftingMode(false) on the widget. The README notes these are independent flags, and that shifting mode defaults to true when the item count is greater than three.

### How does BottomNavigationViewEx bind to a ViewPager?

Set the adapter on the ViewPager first, then call setupWithViewPager on the widget. The README states this links the two so that scroll state changes and clicks are reflected in both directions.

## Sources

- [Issues](https://github.com/ittianyu/BottomNavigationViewEx/issues)
- [ittianyu/BottomNavigationViewEx on GitHub](https://github.com/ittianyu/BottomNavigationViewEx)
- [License: MIT](https://github.com/ittianyu/BottomNavigationViewEx/blob/master/LICENSE)
- [README](https://github.com/ittianyu/BottomNavigationViewEx/blob/master/README.md)
- [Releases](https://github.com/ittianyu/BottomNavigationViewEx/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ittianyu-bottomnavigationviewex
