Implementing an Immersive Status Bar with the Android SlidingMenu Library
Import the SlidingMenu library iether as a libray module referenced by your app module or by copying the library’s source into your project. After adding the dependency, initialize and attach SlidingMenu to an Activity and configure left-edge sliding, shadow, and fade.
Java: create a small initializer
import android.app.Activity;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;
public final class SlideMenuController {
private final Activity host;
private SlidingMenu slidingMenu;
public SlideMenuController(Activity host) {
this.host = host;
}
public SlidingMenu setup() {
slidingMenu = new SlidingMenu(host);
slidingMenu.setMode(SlidingMenu.LEFT);
slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
slidingMenu.setShadowWidthRes(R.dimen.shadow_width);
slidingMenu.setShadowDrawable(R.drawable.shadow);
slidingMenu.setBehindOffsetRes(R.dimen.slidingmenu_offset);
slidingMenu.setFadeDegree(0.35f);
slidingMenu.attachToActivity(host, SlidingMenu.SLIDING_WINDOW);
slidingMenu.setMenu(R.layout.left_drawer_fragment);
slidingMenu.setOnOpenedListener(new SlidingMenu.OnOpenedListener() {
@Override public void onOpened() { /* no-op */ }
});
slidingMenu.setOnClosedListener(new SlidingMenu.OnClosedListener() {
@Override public void onClosed() { /* no-op */ }
});
return slidingMenu;
}
}
Use it in an Activity
public class MainActivity extends Activity {
private SlidingMenu sm;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sm = new SlideMenuController(this).setup();
}
}
Enable an immersive status bar on Android 4.4+
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
To ensure layout content adjusts for system windows, set attributes on a container that participates in layout.
XML: common container attributes
android:clipToPadding="true"
android:fitsSystemWindows="true"
Why SlidingMenu may not appear immersive by default
SlidingMenu internally hosts two views in a ViewGroup: the "above" content (your main screen) and the "behind" content (the drawer). Translucent system bars require a container that correctly handles window insets. Not every view respects fitsSystemWindows as expected, and if the first child is an ImageView, inset handling often fails, making the UI appear to sit below the status bar even though the bar is translucent.
Two approaches
- Modify the library internals
- Insert a top spacer view (e.g., a status bar inset view) at the top of the "above" and/or "behind" containers so they measure and layout with the status bar height.
- Wrap SlidingMenu and manually apply insets (no library changes)
- Place SlidingMenu inside a vertical container and add a top spacer view. Then programmatically set the spacer’s height to the status bar height and adjust headers/padding in your layouts.
XML: wrapping SlidingMenu with a spacer
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:sliding="http://schemas.android.com/apk/res-auto"
android:id="@+id/root_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/inset_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:fitsSystemWindows="true"
android:clipToPadding="true">
<!-- Spacer updated at runtime to the status bar height -->
<View
android:id="@+id/status_inset"
android:layout_width="match_parent"
android:layout_height="1dp"
android:visibility="gone" />
<com.jeremyfeinstein.slidingmenu.lib.SlidingMenu
android:id="@+id/sliding_menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
sliding:behindOffset="0dp"
sliding:behindScrollScale="1"
sliding:fadeEnabled="true"
sliding:fadeDegree="0.7"
sliding:touchModeAbove="margin"
sliding:viewAbove="@layout/activity_base" />
</LinearLayout>
</RelativeLayout>
Programmatic inset handling
- Make system bars translucent on KitKat and up.
- Compute the status bar height.
- Expand header areas and add top padding so content is visually below the translucent bar.
- Optionally, apply padding to key rows in the menu.
Java: apply insets and adjust header/menu
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
final int topInset = getStatusBarHeight(this);
// Reveal and size the spacer
View spacer = findViewById(R.id.status_inset);
if (spacer != null) {
ViewGroup.LayoutParams p = spacer.getLayoutParams();
p.height = topInset;
spacer.setLayoutParams(p);
spacer.setVisibility(View.VISIBLE);
}
// Access SlidingMenu and adjust key views
SlidingMenu slidingMenu = findViewById(R.id.sliding_menu);
// Example: adjust a header view in the content (above)
View header = slidingMenu.getContent().findViewById(R.id.header_container);
if (header != null) {
header.post(() -> {
int h = header.getHeight();
ViewGroup.LayoutParams lp = header.getLayoutParams();
if (lp.height > 0) {
lp.height = lp.height + topInset;
header.setLayoutParams(lp);
} else {
header.setPadding(
header.getPaddingLeft(),
header.getPaddingTop() + topInset,
header.getPaddingRight(),
header.getPaddingBottom()
);
}
});
}
// Example: adjust a top row in the left menu (behind)
View menuTopRow = slidingMenu.getMenu().findViewById(R.id.logout_layout);
if (menuTopRow != null) {
menuTopRow.setPadding(
menuTopRow.getPaddingLeft(),
menuTopRow.getPaddingTop() + topInset,
menuTopRow.getPaddingRight(),
menuTopRow.getPaddingBottom()
);
}
}
Helper: status bar height
public static int getStatusBarHeight(Context context) {
int result = 0;
int resId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resId > 0) {
result = context.getResources().getDimensionPixelSize(resId);
}
return result;
}
Notes
- Ensure fitsSystemWindows is applied to a layout that actually performs measurement and layout (e.g., LinearLayout/RelativeLayout). Avoid placing it only on a Gone child; programmatic padding is more reliable.
- If the first child of a container is an ImageView that draws under the status bar, insert a spacer or apply top padding equal to the status bar height.
- When using attachToActivity with SLIDING_CONTENT, verify that your Activity’s content root also participates in inset handling, or the immersive affect may look offset.