# ImmersionBar: an Android library that still thinks system bars are per-vendor problem

> Six modules, three releases in a fortnight, and a long chainable API for status bar colour, navigation bar tint, dark icons and keyboard conflicts. The manifest advice in the docs has aged better than the API has.

**gyf-dev/ImmersionBar** — Immersive status bar and navigation bar management for Android 4.4+, handling screen rotation, notch screens, soft keyboard pop-ups and more. Lets you change status bar text color and navigation bar icon color, with support for devices that don't allow font color changes. Works with Activity, Fragment, DialogFragment, Dialog and PopupWindow via a single line of code.

- Repository: https://github.com/gyf-dev/ImmersionBar
- Stars: 11,487 · Forks: 1,913
- Language: Java
- License: Apache-2.0
- Published: 2026-10-06 · Updated: 2026-10-06 · Language: en
- Canonical page: https://hysenlabs.com/projects/gyf-dev-immersionbar

## What the library actually wraps

ImmersionBar exists to make an Android activity draw under the status bar and the navigation bar, and to let you control what those two system surfaces look like while you do it. Both behaviours are platform features available since Android 4.4, which is the minimum the project targets, but the platform leaves enough per-vendor variation that a shared implementation saves real time.

The API shape is a builder that you terminate with `init()`:

```java
ImmersionBar.with(this).init();
```

That one line is the whole basic case. Everything beyond it is optional configuration on the same chain, and the project documents roughly forty of them in a single annotated block. Colour and transparency come first: `transparentStatusBar()`, `transparentNavigationBar()`, `transparentBar()`, then `statusBarColor()`, `navigationBarColor()`, and `barColor()` as the combined form. Alpha has its own trio. Icons get their own switches, `statusBarDarkFont(true)` for dark text on a light bar and `navigationBarDarkIcon(true)` for the equivalent on the navigation bar.

The library also treats the two bars as independent objects with their own listeners and their own measured heights, which is the detail that matters once you move past a single fixed status bar colour.

## Three modules, one of them already on the way out

The Gradle coordinates are the first thing to get right, and the documentation contains a migration note that trips people up. The group id changed: anything older than 3.1.1 used `com.gyf`, and current versions use `com.geyifeng`. The old 3.0.0 line also lived on jcenter, which no longer resolves for most builds.

```groovy
implementation 'com.geyifeng.immersionbar:immersionbar:3.3.3'
implementation 'com.geyifeng.immersionbar:immersionbar-ktx:3.3.3'
implementation 'com.geyifeng.immersionbar:immersionbar-components:3.3.3'
```

The base artifact is the only one required. `immersionbar-ktx` adds a Kotlin extension so you can write the configuration as a block with a receiver scope rather than a method chain. `immersionbar-components` provided base classes called `SimpleImmersionFragment` and `ImmersionFragment` for fragment based screens, and its own annotation in the dependency list marks it as deprecated.

The repository tree confirms the shape of the project: a root `immersionbar/` module, the two optional modules beside it, an `immersionbar-sample/` app, a `buildSrc/` directory and a checked in `jar/`. There are also two archived readme files, `README_1.x.md` and `README_2.x.md`, sitting next to the current one. That is a project that has been public through several platform generations and kept its history in the tree rather than in tags.

For Kotlin users the extension reads like this:

```kotlin
immersionBar {
    statusBarColor(R.color.colorPrimary)
    navigationBarColor(R.color.colorPrimary)
}
```

The deprecated fragment classes were replaced by guidance rather than by a new abstraction: call the setup from `onResume` when you use `viewpager2` with the resume-only-current behaviour, and from `onResume` plus `onHiddenChanged` when you toggle fragments with `show()` and `hide()`.

## Manifest configuration for full screen and notches

Before any of the API matters, the activity has to be allowed to draw edge to edge, and that is partly a manifest decision. The documentation lists four options and calls them alternatives you may combine.

The first is simply targeting SDK 25 or above, which the docs then note makes the remaining three unnecessary on anything current. The second is `android:resizeableActivity="true"` on the application node. The third is `android:maxAspectRatio="2.4"`, and the fourth is the older metadata form:

```xml
<meta-data
 android:name="android.max_aspect"
 android:value="2.4" />
```

Cutouts need their own metadata, and this is where the vendor fragmentation shows through most clearly. Huawei and Xiaomi have documented keys:

```xml
<meta-data
  android:name="android.notch_support"
  android:value="true"/>
<meta-data
  android:name="notch.config"
  android:value="portrait|landscape" />
```

For Vivo and Oppo the documentation says plainly that no configuration information was found. So the honest reading of this section is that the library smooths over the cases the vendors documented and does nothing special for the ones they did not. If you ship to those two, expect to handle inset padding yourself, using the measured bar heights the library exposes rather than a magic number.

## Dark mode, keyboards, and the vendor switches

Two feature clusters in the API are worth pulling out because they are where the platform fights back.

The first is automatic dark icon switching. `autoDarkModeEnable(true)` turns on both automatic variants at once, while `autoStatusBarDarkModeEnable(boolean, float)` and `autoNavigationBarDarkModeEnable(boolean, float)` do one bar each and accept a luminance threshold. Both have a documented precondition: you must set an explicit bar colour, because the decision is made by comparing your colour against the light and dark icon choices. There is also a transform trio, `statusBarColorTransform()`, `navigationBarColorTransform()`, and `barColorTransform()`, which lets you specify the colour the bar becomes once the automatic switch has fired. Flyme gets its own method, `flymeOSStatusBarFontColor()`, which is a fair signal of how much of this API is per-vendor patching.

The second is the soft keyboard. `keyboardEnable(true)` opts into adjusting the window so an input field near the bottom is not covered, and `keyboardMode(...)` sets the layout flag directly. Once enabled, `setOnKeyboardListener()` reports whether the keyboard is up and how tall it is. The 3.3.3 release notes mark that method deprecated in favour of `addOnKeyboardChangedListener()` and `removeOnKeyboardChangedListener()`.

The older vendor toggles are still there and still default to true: `navigationBarWithKitkatEnable(true)` for Android 4.4 and EMUI 3.x, `navigationBarWithEMUI3Enable(true)` for EMUI 3.x specifically, and `navigationBarEnable(true)` to turn navigation bar control off entirely. These exist because that code path cannot be removed without breaking devices still in use.

## Two releases that show what maintenance looks like here

The 3.3.2 and 3.3.3 releases, published a little over a week apart in July and August 2026, are more informative than a long feature list because they describe the failure modes the maintainer actually hits.

Version 3.3.2 deprecated the `setOn...` listener family in favour of `addOn...`, added dedicated status bar and navigation bar objects, added foldable screen support, and handled status bar and navigation bar height changes on rotation. Renaming a public API in a stable library is a deliberate cost, and the reason is visible in the same release: the new objects carry visibility, height, width, and navigation mode, which the old callbacks did not expose.

Version 3.3.3 then fixed two Android 15 problems. The first is the keyboard popping up and a navigation bar or black strip appearing along the bottom edge. The second is page content overlapping the system bars in some scenarios. Both are the kind of bug that appears when the platform changes its own behaviour, and they are exactly what a shared library exists to absorb. The same release optimised the height and state callbacks after navigation bar show, hide, and mode switches, fixed navigation bar state detection on older systems and EMUI 3.x, and made the navigation bar style follow the light and dark theme by default on Android 8.0 and above.

That last change is quietly the most consequential one for existing apps, because it alters appearance without any code change on your side.

## When to reach for it and when to skip it

The case for using this library is a themed app that draws behind the system bars and wants dark icons, a tint, or consistent behaviour across OEM skins. Doing that correctly means handling EMUI, Flyme, MIUI, gesture navigation, cutouts, and the keyboard, and no application team wants to own that list. Apache 2.0 licensing, a version that has reached 3.3.3, a public sample app, and 11478 stars are all reasonable signals that the edge cases get attention.

The case against is that a large part of what the library does, drawing under the bars and tinting them, is now the platform default. Targeting modern SDK levels with the standard window insets APIs covers the common case in a handful of lines. What the platform does not give you is the per-vendor keyboard and EMUI handling, and that is the part worth paying a dependency for if you actually ship to those devices.

Two practical warnings. The API is large enough that it is easy to configure a dozen options and end up fighting your own theme, so start with the one-line form and add what you need. And check which listener methods you are calling: the `setOnStatusBarListener`, `setOnNavigationBarListener`, and `setOnKeyboardListener` trio are all marked deprecated as of 3.3.3, and every tutorial written before that release will use them.

The 130 open issues in the repository are also worth a glance before you commit. For a library whose entire job is tracking OEM behaviour, that backlog is the most honest indicator of what using it will feel like day to day.

## Conclusion

ImmersionBar earns its 11478 stars because it solved a genuinely tedious problem once, at a scale no single app team wants to own, and the code is Apache 2.0 with a sample module you can read top to bottom. Two things give a newcomer pause in 2026. The `immersionbar-components` module is marked deprecated in the dependency snippet itself, and the 3.3.2 release renamed the whole listener API from `setOn...` to `addOn...`, so any code you find from an older tutorial will need those call sites changed. The manifest instructions are also worth reading sceptically: the four options for full screen are presented as alternatives, and the documentation itself notes that option one, targeting SDK 25 or above, has made the other three unnecessary on current devices. Start with `ImmersionBar.with(this).init()`, add only the options you actually need, and check `build.gradle` for the current version rather than copying a coordinate from a blog post.

## FAQ

### How do I add ImmersionBar to an Android project?

Add the base dependency with the current group id, com.geyifeng.immersionbar. Versions from 3.1.1 onwards moved off the old com.gyf prefix and onto mavenCentral, so older coordinates from tutorials will not resolve.

### What is the difference between the three ImmersionBar modules?

The base immersionbar artifact is required. immersionbar-ktx adds a Kotlin extension for configuration blocks, and immersionbar-components supplied fragment base classes but is marked deprecated in the dependency list.

### How do I handle notch displays with ImmersionBar?

Manifest metadata is required, and it differs per vendor. The documentation gives keys for Huawei and Xiaomi and states that no configuration information was found for Vivo and Oppo, so those need manual inset handling.

### Which ImmersionBar APIs are deprecated?

As of 3.3.3, setOnKeyboardListener, setOnStatusBarListener, and setOnNavigationBarListener are deprecated in favour of the addOn and removeOn equivalents. Version 3.3.2 made the same change for the bar property listener.

### Does ImmersionBar fix the keyboard covering input fields?

It can. keyboardEnable opts into window adjustment so a bottom input field is not covered, and keyboardMode sets the layout flag directly. Version 3.3.3 fixed an Android 15 issue where a navigation bar or black strip appeared when the keyboard opened.

## Sources

- [gyf-dev/ImmersionBar on GitHub](https://github.com/gyf-dev/ImmersionBar)
- [Issues](https://github.com/gyf-dev/ImmersionBar/issues)
- [License: Apache-2.0](https://github.com/gyf-dev/ImmersionBar/blob/master/LICENSE)
- [README](https://github.com/gyf-dev/ImmersionBar/blob/master/README.md)
- [Releases](https://github.com/gyf-dev/ImmersionBar/releases)

---

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