26

I'm using an AppCompatDialogFragment to show a BottomSheetDialog. Clicking the back button on the Navigation Bar closes the BottomSheetDialog.

I want to change the icon on the Navigation Bar from the back button to the 'arrow-down' icon. This is by default done when the keyboard is shown and I want to replicate it for the Bottom Sheet.

To be clear, here what I have:

Current

And here is what I need:

This is what I want

Note that the back button is an "arrow-down".

The navigation-bar is a system-ui component and I don't see the way to change it's appearance to look like the navigation-bar displayed when the keyboard is visible.

ben75
  • 29,217
  • 10
  • 88
  • 134
Vlad
  • 988
  • 12
  • 18
  • An arrow-down would be shown only when keyboard is opened. I am curious what use-case do you have? Because if it is just a desire, than you can also say *"i want an octagon instead of home button"*. You want to be a bad boy and break the rules, meaning that user certainly knows in what case that arrow becomes arrow-down, and you want to introduce radical changes there, which obviously Google won't allow to do, because UX should be consistent throughout the platform. – azizbekian Aug 25 '17 at 14:10
  • 3
    @azizbekian I want to show the arrow-down when I display a `BottomDialog`. When clicking the back button, the `BottomDialog` is dismissed by sliding down and it would make sense to show an arrow-down instead of the classic back button. – Vlad Aug 25 '17 at 14:18
  • @azizbekian the API allow you to change the behavior of the back button, so it make sense to allow you to change the associated icon. – ben75 Aug 25 '17 at 17:42
  • You could probably wrap your BottomDialog in a custom keyboard layout, but are you sure, you want that pain in the ... just for an arrow? – artkoenig Aug 29 '17 at 14:20
  • Set your activity as [full screen](https://stackoverflow.com/questions/2868047/fullscreen-activity-in-android), and layout the hardware buttons the way you want. You can even reconstruct the status bar. – RonTLV Aug 29 '17 at 17:45

2 Answers2

9

In android O the concept of changing the icon is introduced but it is still through the 3rd party app. Custom Navigation Bar that uses WRITE_SECURE_SETTINGS to change the icons. In Android O you can change the display of the bar i.e Light or Dark theme.

Solution 2 can be more of a help to you. You can create a popup window on navigation Bar with the desired layout i.e 3 buttons back, Recent Apps and home button. In this way you can change the back button icon accordingly. Make sure the pop up window is of same height as the navigation Bar and you can then make your own functions for home and recent apps and in back function you can close your BottomSheetDialog and remove that popup window.

The below is the code for home key as well as recent Apps. For back button do accordingly what you want to achieve with your own icon.

For Home Button.

Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);

For Recent Apps.

Class serviceManagerClass = Class.forName("android.os.ServiceManager");
Method getService = serviceManagerClass.getMethod("getService", String.class);
IBinder retbinder = (IBinder) getService.invoke(serviceManagerClass, "statusbar");
Class statusBarClass = Class.forName(retbinder.getInterfaceDescriptor());
Object statusBarObject = statusBarClass.getClasses()[0].getMethod("asInterface", IBinder.class).invoke(null, new Object[] { retbinder });
Method clearAll = statusBarClass.getMethod("toggleRecentApps");
clearAll.setAccessible(true);
clearAll.invoke(statusBarObject);

For Back Button // use your icon and function of closing the BottomSheetDialog.

For calculating the height of the navigationBar

public static int getSoftButtonsBarSizePort(Activity activity) {
    // getRealMetrics is only available with API 17 and +
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        DisplayMetrics metrics = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
        int usableHeight = metrics.heightPixels;
        activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
        int realHeight = metrics.heightPixels;
        if (realHeight > usableHeight)
            return realHeight - usableHeight;
        else
            return 0;
    }
    return 0;
}

you can also do it by adb commands but make sure it can mess up your navigationBar and you cannot get back your original navigationBar.

I hope it helps.

Sahil
  • 1,399
  • 9
  • 11
  • How can I position the `popup window` on top of the `Navigation Bar`? Do I have to set my app to immersive mode? – Vlad Aug 31 '17 at 19:14
  • https://stackoverflow.com/a/34595261/6761707 Check this and you will know how to exactly make it @Vlad Instead of Gravity.TOP use gravity.BOTTOM and Instead of transparent Your own color. and in the end ...when having your customViewGroup add these buttons and on click event on it. Thanks I hope it Helps and do upVote if it works for you – Sahil Aug 31 '17 at 19:53
  • You can also Use your BottomNavigationView and make sure it is added on the NavgationBar using above comment answer. Thanks again – Sahil Aug 31 '17 at 19:58
4

As already answered, it will be introduced in Android O.

For prior versions it's only possible for Android 3.x, or 4.4+ using flags as SYSTEM_UI_FLAG_IMMERSIVE, SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, SYSTEM_UI_FLAG_HIDE_NAVIGATION, etc. But still very limited, putting a lot of effort you get a result not very friendly or even glitchy.

The reason because it isn't possible, it because is a security issue. Apps could prevent to users to exit of the app.

Look at these links :

crgarridos
  • 8,758
  • 3
  • 49
  • 61