5

I am trying to check the visibility of the navigation bar. On the Samsung Galaxy S8 I can toggle the navigation bar visibility.

I have tried a lot of different ways to check the visibility, but none of them work on the Galaxy S8.

Some examples: (They will always return the same value, no matter it is shown or hidden)

ViewConfiguration.get(getBaseContext()).hasPermanentMenuKey() always returns false KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK) always returns false KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_HOME) always returns true

Even by figuring out the navigation bar height (How do I get the height and width of the Android Navigation Bar programmatically?), it will not work.

Mehraj Khan
  • 867
  • 6
  • 16
Joery
  • 529
  • 2
  • 11
  • 28

2 Answers2

1

Maybe this will be useful for someone. The user can hide the navigation bar, so the best way to detect visibility is to subscribe to this event. It works.

 object NavigationBarUtils {
    // Location of navigation bar
    const val LOCATION_BOTTOM = 0
    const val LOCATION_RIGHT = 1
    const val LOCATION_LEFT = 2
    const val LOCATION_NONE = 3

    fun addLocationListener(activity: Activity, listener: (location: Int) -> Unit) {
        ViewCompat.setOnApplyWindowInsetsListener(activity.window.decorView) { view, insets ->
            val location = when {
                insets.systemWindowInsetBottom != 0 -> LOCATION_BOTTOM
                insets.systemWindowInsetRight != 0 -> LOCATION_RIGHT
                insets.systemWindowInsetLeft != 0 -> LOCATION_LEFT
                else -> LOCATION_NONE
            }
            listener(location)
            ViewCompat.onApplyWindowInsets(view, insets)
        }
    }
}
Abandoned Cart
  • 3,230
  • 29
  • 32
Andrey Tuzov
  • 81
  • 1
  • 4
0

Since the only answer at the time of writing is Kotlin, here is a Java alternative:

import android.content.res.Resources;
import android.support.v4.view.OnApplyWindowInsetsListener;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.WindowInsetsCompat;
import android.view.View;

public class NavigationBar {

    final int BOTTOM = 0;
    final int RIGHT = 1;
    final int LEFT = 2;
    final int NONE = 3;
    private int LOCATION = NONE;

    private View view;

    NavigationBar(View view) {
        this.view = view;
    }

    int getNavBarLocation() {
        ViewCompat.setOnApplyWindowInsetsListener(view, new OnApplyWindowInsetsListener() {
            public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
                if (insets.getSystemWindowInsetBottom() != 0)
                    LOCATION = BOTTOM;
                else if (insets.getSystemWindowInsetRight() != 0)
                    LOCATION = RIGHT;
                else if (insets.getSystemWindowInsetLeft() != 0)
                    LOCATION = LEFT;
                else
                    LOCATION = NONE;
                return insets;
            }
        });
        return LOCATION;
    }

    int getNavBarHeight() {
        Resources resources = view.getResources();
        int resourceId = resources.getIdentifier(
                "navigation_bar_height", "dimen", "android");
        if (resourceId > 0)
            return resources.getDimensionPixelSize(resourceId);
        return 0;
    }
}

I have also included how to get the height, since that will often be the next step.

In your activity, you would then call the methods using a view-based reference:

    NavigationBar navigationBar = new NavigationBar(snackbarLayout);
    if (navigationBar.getNavBarLocation() == navigationBar.BOTTOM) {
        FrameLayout.LayoutParams parentParams =
                (FrameLayout.LayoutParams) snackbarLayout.getLayoutParams();
        parentParams.setMargins(0, 0, 0, 0 - navigationBar.getNavBarHeight());
        snackbarLayout.setLayoutParams(parentParams);
    }

(This example is based on a common issue with inconsistent SnackBar margins)

Abandoned Cart
  • 3,230
  • 29
  • 32