web-dev-qa-db-fra.com

Comment obtenir la hauteur et la largeur de la barre de navigation Android par programmation?

La barre de navigation noire au bas de l'écran n'est pas facilement amovible dans Android. Il fait partie de Android depuis la version 3.0 en remplacement des boutons matériels. Voici une photo:

System Bar

Comment puis-je obtenir la taille de la largeur et la hauteur de cet élément d'interface utilisateur en pixels?

108
Kevik

Essayez ci-dessous le code:

Resources resources = context.getResources();
int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "Android");
if (resourceId > 0) {
    return resources.getDimensionPixelSize(resourceId);
}
return 0;
166
Sanket

J'obtiens la taille de la barre de navigation en comparant la taille d'écran utilisable par l'application avec la taille réelle de l'écran. Je suppose que la barre de navigation est présente lorsque la taille d'écran utilisable par l'application est inférieure à la taille réelle de l'écran. Ensuite, je calcule la taille de la barre de navigation. Cette méthode fonctionne avec les API 14 et supérieures.

public static Point getNavigationBarSize(Context context) {
    Point appUsableSize = getAppUsableScreenSize(context);
    Point realScreenSize = getRealScreenSize(context);

    // navigation bar on the side
    if (appUsableSize.x < realScreenSize.x) {
        return new Point(realScreenSize.x - appUsableSize.x, appUsableSize.y);
    }

    // navigation bar at the bottom
    if (appUsableSize.y < realScreenSize.y) {
        return new Point(appUsableSize.x, realScreenSize.y - appUsableSize.y);
    }

    // navigation bar is not present
    return new Point();
}

public static Point getAppUsableScreenSize(Context context) {
    WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = windowManager.getDefaultDisplay();
    Point size = new Point();
    display.getSize(size);
    return size;
}

public static Point getRealScreenSize(Context context) {
    WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = windowManager.getDefaultDisplay();
    Point size = new Point();

    if (Build.VERSION.SDK_INT >= 17) {
        display.getRealSize(size);
    } else if (Build.VERSION.SDK_INT >= 14) {
        try {
            size.x = (Integer) Display.class.getMethod("getRawWidth").invoke(display);
            size.y = (Integer) Display.class.getMethod("getRawHeight").invoke(display);
        } catch (IllegalAccessException e) {} catch (InvocationTargetException e) {} catch (NoSuchMethodException e) {}
    }

    return size;
}

UPDATE

Pour une solution prenant en compte les découpes d’affichage, veuillez vérifier réponse de John .

95
Egis

La hauteur de la barre de navigation varie pour certains appareils, mais également pour certaines orientations. Vous devez d’abord vérifier si l’appareil dispose d’une barre de navigation, puis, si l’appareil est une tablette ou non, et enfin, vous devez regarder l’orientation de l’appareil pour obtenir la bonne hauteur.

public int getNavBarHeight(Context c) {
         int result = 0;
         boolean hasMenuKey = ViewConfiguration.get(c).hasPermanentMenuKey();
         boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);

         if(!hasMenuKey && !hasBackKey) {
             //The device has a navigation bar
             Resources resources = c.getResources();

             int orientation = resources.getConfiguration().orientation;
             int resourceId;
             if (isTablet(c)){
                 resourceId = resources.getIdentifier(orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_height_landscape", "dimen", "Android");
             }  else {
                 resourceId = resources.getIdentifier(orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_width", "dimen", "Android");     
             }

             if (resourceId > 0) {
                 return resources.getDimensionPixelSize(resourceId);
             }
         }
         return result;
} 


private boolean isTablet(Context c) {
    return (c.getResources().getConfiguration().screenLayout
            & Configuration.SCREENLAYOUT_SIZE_MASK)
            >= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
35
Mdlc

En fait, la barre de navigation sur les tablettes (au moins Nexus 7) a une taille différente en portrait et en paysage; cette fonction devrait donc ressembler à ceci:

private int getNavigationBarHeight(Context context, int orientation) {
    Resources resources = context.getResources();

    int id = resources.getIdentifier(
            orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_height_landscape",
            "dimen", "Android");
    if (id > 0) {
        return resources.getDimensionPixelSize(id);
    }
    return 0;
}
25
Danylo Volokh

Je pense que la meilleure réponse est ici parce que cela vous permet d’obtenir une hauteur de découpe égale aussi.

Prenez votre vue racine et ajoutez setOnApplyWindowInsetsListener (ou vous pouvez en remplacer sur ApplyWindowInsets), puis insets.getSystemWindowInsets.

Dans mon activité caméra, j'ajoute un rembourrage égal à la valeur systemWindowInsetBottom à la disposition inférieure. Et enfin, cela corrige le problème de découpe.

Camera activity insets

avec appcompat c'est comme ça

ViewCompat.setOnApplyWindowInsetsListener(mCameraSourcePreview, (v, insets) -> {
    takePictureLayout.setPadding(0,0,0,insets.getSystemWindowInsetBottom());
    return insets.consumeSystemWindowInsets();
});

sans appcompat, ceci:

mCameraSourcePreview.setOnApplyWindowInsetsListener((v, insets) -> { ... })
12
John

J'espère que ceci vous aide

public int getStatusBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "Android");
    if (resourceId > 0) {
        result = getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

public int getNavigationBarHeight()
{
    boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey();
    int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "Android");
    if (resourceId > 0 && !hasMenuKey)
    {
        return getResources().getDimensionPixelSize(resourceId);
    }
    return 0;
}
9
Francisco Drumond

Ceci est mon code pour ajouter paddingRight et paddingBottom à une vue pour esquiver la barre de navigation. J'ai combiné certaines des réponses ici et fait une clause spéciale pour l'orientation paysage avec isInMultiWindowMode. La clé est de lire navigation_bar_height , mais aussi de vérifier config_showNavigationBar pour vous assurer que nous devrions réellement utiliser la hauteur.

Aucune des solutions précédentes n'a fonctionné pour moi. À partir de Android 7.0, vous devez prendre en considération le mode multi-fenêtres. Ceci rompt les implémentations comparant display.realSize avec display.size depuis realSize vous donne les dimensions de l'écran entier (les deux fenêtres divisées) et la taille ne vous donnent que les dimensions de la fenêtre de votre application. Si vous réglez le rembourrage sur cette différence, votre vue entière reste en cours de remplissage.

/** Adds padding to a view to dodge the navigation bar.

    Unfortunately something like this needs to be done since there
    are no attr or dimens value available to get the navigation bar
    height (as of December 2016). */
public static void addNavigationBarPadding(Activity context, View v) {
    Resources resources = context.getResources();
    if (hasNavigationBar(resources)) {
        int orientation = resources.getConfiguration().orientation;
        int size = getNavigationBarSize(resources);
        switch (orientation) {
        case Configuration.ORIENTATION_LANDSCAPE:
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N &&
                context.isInMultiWindowMode()) { break; }
            v.setPadding(v.getPaddingLeft(), v.getPaddingTop(),
                         v.getPaddingRight() + size, v.getPaddingBottom());
            break;
        case Configuration.ORIENTATION_PORTRAIT:
            v.setPadding(v.getPaddingLeft(), v.getPaddingTop(),
                         v.getPaddingRight(), v.getPaddingBottom() + size);
            break;
        }
    }
}

private static int getNavigationBarSize(Resources resources) {
    int resourceId = resources.getIdentifier("navigation_bar_height",
                                             "dimen", "Android");
    return resourceId > 0 ? resources.getDimensionPixelSize(resourceId) : 0;
}

private static boolean hasNavigationBar(Resources resources) {
    int hasNavBarId = resources.getIdentifier("config_showNavigationBar",
                                              "bool", "Android");
    return hasNavBarId > 0 && resources.getBoolean(hasNavBarId);
}
5
marcus

La solution proposée par Egidijus fonctionne parfaitement pour Build.VERSION.SDK_INT> = 17

Mais j'ai reçu "NoSuchMethodException" lors de l'exécution de l'instruction suivante avec Build.VERSION.SDK_INT <17 sur mon appareil:

Display.class.getMethod("getRawHeight").invoke(display);

J'ai modifié la méthode getRealScreenSize () pour de tels cas:

else if(Build.VERSION.SDK_INT >= 14) 
{
    View decorView = getActivity().getWindow().getDecorView();
    size.x = decorView.getWidth();
    size.y = decorView.getHeight();
}
1
Chebyr

J'ai résolu ce problème pour tous les appareils (Nexus 5, Samsung Galaxy Nexus 6 Edge +, Samsung S10, Samsung Note II, etc.). Je pense que cela vous aidera à gérer les problèmes liés aux périphériques.

Ici, j'ajoute deux types de codes,

Code Java (pour Android natif):

import Android.content.Context;
import Android.content.res.Resources;
import Android.os.Build;
import Android.util.DisplayMetrics;
import Android.view.Display;
import Android.view.ViewConfiguration;
import Android.view.WindowManager;

public class DeviceSpec {

    private int resourceID = -1;
    private Display display = null;
    private DisplayMetrics displayMetrics = null;
    private DisplayMetrics realDisplayMetrics = null;
    private Resources resources = null;
    private WindowManager windowManager = null;

    public double GetNavigationBarHeight(Context context) {
        try {
            windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            display = windowManager.getDefaultDisplay();
            displayMetrics = new DisplayMetrics();
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
                realDisplayMetrics = new DisplayMetrics();
                display.getMetrics(displayMetrics);
                display.getRealMetrics(realDisplayMetrics);
                if(displayMetrics.heightPixels != realDisplayMetrics.heightPixels) {
                    resources = context.getResources();
                    return GetNavigationBarSize(context);
                }
            }
            else {
                resources = context.getResources();
                resourceID = resources.getIdentifier("config_showNavigationBar", "bool", "Android");
                if (resourceID > 0 && resources.getBoolean(resourceID))
                    return GetNavigationBarSize(context);
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
        return 0;
    }

    private double GetNavigationBarSize(Context context) {
        resourceID = resources.getIdentifier("navigation_bar_height", "dimen", "Android");
        if (resourceID > 0 && ViewConfiguration.get(context).hasPermanentMenuKey())
           return (resources.getDimensionPixelSize(resourceID) / displayMetrics.density);
        return 0;
    }
}

Et code C # (pour Xamarin Forms/Android)

int resourceId = -1;
        IWindowManager windowManager = null;
        Display defaultDisplay = null;
        DisplayMetrics displayMatrics = null;
        DisplayMetrics realMatrics = null;
        Resources resources = null;

        public double NavigationBarHeight
        {
            get
            {
                try
                {
                    windowManager = Forms.Context.GetSystemService(Context.WindowService).JavaCast<IWindowManager>();
                    defaultDisplay = windowManager.DefaultDisplay;
                    displayMatrics = new DisplayMetrics();
                    if (Build.VERSION.SdkInt >= BuildVersionCodes.JellyBeanMr2)
                    {
                        realMatrics = new DisplayMetrics();
                        defaultDisplay.GetMetrics(displayMatrics);
                        defaultDisplay.GetRealMetrics(realMatrics);
                        if (displayMatrics.HeightPixels != realMatrics.HeightPixels)
                        {
                            resources = Forms.Context.Resources;
                            return GetHeightOfNivigationBar();
                        }
                    }
                    else {
                        resources = Forms.Context.Resources;
                        resourceId = resources.GetIdentifier("config_showNavigationBar", "bool", "Android");
                        if (resourceId > 0 && resources.GetBoolean(resourceId))
                            return GetHeightOfNivigationBar();
                    }
                }
                catch (Exception e) { }
                return 0;
            }
        }

        private double GetHeightOfNivigationBar()
        {
            resourceId = resources.GetIdentifier("navigation_bar_height", "dimen", "Android");
            if (!ViewConfiguration.Get(Forms.Context).HasPermanentMenuKey && resourceId > 0)
            {
                return resources.GetDimensionPixelSize(resourceId) / displayMatrics.Density;
            }
            return 0;
        }
1
Sino Raj

Combinant la réponse de @egis et d’autres - cela fonctionne bien sur une variété de périphériques, testé sur Pixel EMU, Samsung S6, Sony Z3, Nexus 4. Ce code utilise les dimensions de l’affichage pour tester la disponibilité de la barre de navigation, puis utilise la taille réelle. taille de la barre de navigation système, le cas échéant.

/**
 * Calculates the system navigation bar size.
 */

public final class NavigationBarSize {

        private final int systemNavBarHeight;
        @NonNull
        private final Point navBarSize;

        public NavigationBarSize(@NonNull Context context) {
                Resources resources = context.getResources();
                int displayOrientation = resources.getConfiguration().orientation;
                final String name;
                switch (displayOrientation) {
                        case Configuration.ORIENTATION_PORTRAIT:
                                name = "navigation_bar_height";
                                break;
                        default:
                                name = "navigation_bar_height_landscape";
                }
                int id = resources.getIdentifier(name, "dimen", "Android");
                systemNavBarHeight = id > 0 ? resources.getDimensionPixelSize(id) : 0;
                navBarSize = getNavigationBarSize(context);
        }

        public void adjustBottomPadding(@NonNull View view, @DimenRes int defaultHeight) {
                int height = 0;
                if (navBarSize.y > 0) {
                        // the device has a nav bar, get the correct size from the system
                        height = systemNavBarHeight;
                }
                if (height == 0) {
                        // fallback to default
                        height = view.getContext().getResources().getDimensionPixelSize(defaultHeight);
                }
                view.setPadding(0, 0, 0, height);
        }

        @NonNull
        private static Point getNavigationBarSize(@NonNull Context context) {
                Point appUsableSize = new Point();
                Point realScreenSize = new Point();
                WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
                if (windowManager != null) {
                        Display display = windowManager.getDefaultDisplay();
                        display.getSize(appUsableSize);
                        display.getRealSize(realScreenSize);
                }
                return new Point(realScreenSize.x - appUsableSize.x, realScreenSize.y - appUsableSize.y);
        }

}
1
Meanman

La hauteur de la barre de navigation inférieure est de 48dp (en mode portrait et paysage) et de 42dp lorsque la barre est placée verticalement.

1
Aritra Roy

Dans le cas de Samsung S8, aucune des méthodes ci-dessus ne donnait une hauteur de barre de navigation correcte. J'ai donc utilisé KeyboardHeightProvider fournisseur de hauteur de clavier Android . Et cela m'a donné la hauteur en valeurs négatives et pour le positionnement de ma mise en page, j'ai ajusté cette valeur dans les calculs.

Voici KeyboardHeightProvider.Java:

import Android.app.Activity;
import Android.content.res.Configuration;
import Android.graphics.Point;
import Android.graphics.Rect;
import Android.graphics.drawable.ColorDrawable;
import Android.view.Gravity;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewTreeObserver.OnGlobalLayoutListener;
import Android.view.WindowManager.LayoutParams;
import Android.widget.PopupWindow;


/**
 * The keyboard height provider, this class uses a PopupWindow
 * to calculate the window height when the floating keyboard is opened and closed. 
 */
public class KeyboardHeightProvider extends PopupWindow {

    /** The tag for logging purposes */
    private final static String TAG = "sample_KeyboardHeightProvider";

    /** The keyboard height observer */
    private KeyboardHeightObserver observer;

    /** The cached landscape height of the keyboard */
    private int keyboardLandscapeHeight;

    /** The cached portrait height of the keyboard */
    private int keyboardPortraitHeight;

    /** The view that is used to calculate the keyboard height */
    private View popupView;

    /** The parent view */
    private View parentView;

    /** The root activity that uses this KeyboardHeightProvider */
    private Activity activity;

    /** 
     * Construct a new KeyboardHeightProvider
     * 
     * @param activity The parent activity
     */
    public KeyboardHeightProvider(Activity activity) {
        super(activity);
        this.activity = activity;

        LayoutInflater inflator = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        this.popupView = inflator.inflate(R.layout.popupwindow, null, false);
        setContentView(popupView);

        setSoftInputMode(LayoutParams.SOFT_INPUT_ADJUST_RESIZE | LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
        setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);

        parentView = activity.findViewById(Android.R.id.content);

        setWidth(0);
        setHeight(LayoutParams.MATCH_PARENT);

        popupView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

                @Override
                public void onGlobalLayout() {
                    if (popupView != null) {
                        handleOnGlobalLayout();
                    }
                }
            });
    }

    /**
     * Start the KeyboardHeightProvider, this must be called after the onResume of the Activity.
     * PopupWindows are not allowed to be registered before the onResume has finished
     * of the Activity.
     */
    public void start() {

        if (!isShowing() && parentView.getWindowToken() != null) {
            setBackgroundDrawable(new ColorDrawable(0));
            showAtLocation(parentView, Gravity.NO_GRAVITY, 0, 0);
        }
    }

    /**
     * Close the keyboard height provider, 
     * this provider will not be used anymore.
     */
    public void close() {
        this.observer = null;
        dismiss();
    }

    /** 
     * Set the keyboard height observer to this provider. The 
     * observer will be notified when the keyboard height has changed. 
     * For example when the keyboard is opened or closed.
     * 
     * @param observer The observer to be added to this provider.
     */
    public void setKeyboardHeightObserver(KeyboardHeightObserver observer) {
        this.observer = observer;
    }

    /**
     * Get the screen orientation
     *
     * @return the screen orientation
     */
    private int getScreenOrientation() {
        return activity.getResources().getConfiguration().orientation;
    }

    /**
     * Popup window itself is as big as the window of the Activity. 
     * The keyboard can then be calculated by extracting the popup view bottom 
     * from the activity window height. 
     */
    private void handleOnGlobalLayout() {

        Point screenSize = new Point();
        activity.getWindowManager().getDefaultDisplay().getSize(screenSize);

        Rect rect = new Rect();
        popupView.getWindowVisibleDisplayFrame(rect);

        // REMIND, you may like to change this using the fullscreen size of the phone
        // and also using the status bar and navigation bar heights of the phone to calculate
        // the keyboard height. But this worked fine on a Nexus.
        int orientation = getScreenOrientation();
        int keyboardHeight = screenSize.y - rect.bottom;

        if (keyboardHeight == 0) {
            notifyKeyboardHeightChanged(0, orientation);
        }
        else if (orientation == Configuration.ORIENTATION_PORTRAIT) {
            this.keyboardPortraitHeight = keyboardHeight; 
            notifyKeyboardHeightChanged(keyboardPortraitHeight, orientation);
        } 
        else {
            this.keyboardLandscapeHeight = keyboardHeight; 
            notifyKeyboardHeightChanged(keyboardLandscapeHeight, orientation);
        }
    }

    /**
     *
     */
    private void notifyKeyboardHeightChanged(int height, int orientation) {
        if (observer != null) {
            observer.onKeyboardHeightChanged(height, orientation);
        }
    }

    public interface KeyboardHeightObserver {
        void onKeyboardHeightChanged(int height, int orientation);
    }
}

popupwindow.xml:

<?xml version="1.0" encoding="utf-8"?>
<View
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/popuplayout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:background="@Android:color/transparent"
    Android:orientation="horizontal"/>

Utilisation dans MainActivity

import Android.os.Bundle
import Android.support.v7.app.AppCompatActivity
import kotlinx.Android.synthetic.main.activity_main.*

/**
 * Created by nileshdeokar on 22/02/2018.
 */
class MainActivity : AppCompatActivity() , KeyboardHeightProvider.KeyboardHeightObserver  {

    private lateinit var keyboardHeightProvider : KeyboardHeightProvider


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        keyboardHeightProvider = KeyboardHeightProvider(this)
        parentActivityView.post { keyboardHeightProvider?.start() }
    }

    override fun onKeyboardHeightChanged(height: Int, orientation: Int) {
        // In case of 18:9 - e.g. Samsung S8
        // here you get the height of the navigation bar as negative value when keyboard is closed.
        // and some positive integer when keyboard is opened.
    }

    public override fun onPause() {
        super.onPause()
        keyboardHeightProvider?.setKeyboardHeightObserver(null)
    }

    public override fun onResume() {
        super.onResume()
        keyboardHeightProvider?.setKeyboardHeightObserver(this)
    }

    public override fun onDestroy() {
        super.onDestroy()
        keyboardHeightProvider?.close()
    }
}

Pour toute aide supplémentaire, vous pouvez jeter un coup d'œil à l'utilisation avancée de ceci ici .

0
Nilesh Deokar

Dans mon cas où je voulais avoir quelque chose comme ça:

Screenshot

Je devais suivre la même chose que suggéré par @ Mdlc mais probablement un peu plus simple (ciblage seulement > = 21):

    //kotlin
    val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
    val realSize = Point()
    windowManager.defaultDisplay.getRealSize(realSize);
    val usableRect = Rect()
    windowManager.defaultDisplay.getRectSize(usableRect)
    Toast.makeText(this, "Usable Screen: " + usableRect + " real:"+realSize, Toast.LENGTH_LONG).show()

    window.decorView.setPadding(usableRect.left, usableRect.top, realSize.x - usableRect.right, realSize.y - usableRect.bottom)

Cela fonctionne aussi sur le paysage:

landscape

Modifier La solution ci-dessus ne fonctionne pas correctement en mode multi-fenêtre où le rectangle utilisable n'est pas plus petit simplement à cause de la barre de navigation mais également à cause de la fenêtre personnalisée. Taille. Une chose que j'ai remarquée est que, dans les fenêtres multiples, la barre de navigation ne survole pas l'application. Par conséquent, même en l'absence de modification du remplissage de DecorView, nous avons le comportement correct:

Multi-window with no changes to decor view paddingSingle-window with no changes to decor view padding

Notez la différence entre la façon dont la barre de navigation flotte au bas de l'application dans ces scénarios. Heureusement, c'est facile à corriger. Nous pouvons vérifier si l'application est multi-fenêtre. Le code ci-dessous comprend également la partie permettant de calculer et d’ajuster la position de la barre d’outils (solution complète: https://stackoverflow.com/a/14213035/47779 )

    // kotlin
    // Let the window flow into where window decorations are
    window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN)
    window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)

    // calculate where the bottom of the page should end up, considering the navigation bar (back buttons, ...)
    val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
    val realSize = Point()
    windowManager.defaultDisplay.getRealSize(realSize);
    val usableRect = Rect()
    windowManager.defaultDisplay.getRectSize(usableRect)
    Toast.makeText(this, "Usable Screen: " + usableRect + " real:" + realSize, Toast.LENGTH_LONG).show()

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N || !isInMultiWindowMode) {
        window.decorView.setPadding(usableRect.left, usableRect.top, realSize.x - usableRect.right, realSize.y - usableRect.bottom)
        // move toolbar/appbar further down to where it should be and not to overlap with status bar
        val layoutParams = ConstraintLayout.LayoutParams(appBarLayout.layoutParams as ConstraintLayout.LayoutParams)
        layoutParams.topMargin = getSystemSize(Constants.statusBarHeightKey)
        appBarLayout.layoutParams = layoutParams
    }

Résultat sur le mode popup Samsung:

enter image description here

0
Bakhshi

Voici comment j'ai résolu ceci. J'ai créé une barre inférieure masquable qui nécessitait un rembourrage selon qu'il y avait ou non une barre de navigation (capacitive, à l'écran ou juste avant Lollipop).


Voir

setPadding(0, 0, 0, Utils.hasNavBar(getContext()) ? 30 : 0);

tils.Java

public static boolean hasNavBar(Context context) {
    // KitKat and less shows container above nav bar
    if (Android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.KitKat) {
        return false;
    }
    // Emulator
    if (Build.FINGERPRINT.startsWith("generic")) {
        return true;
    }
    boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey();
    boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
    boolean hasNoCapacitiveKeys = !hasMenuKey && !hasBackKey;
    Resources resources = context.getResources();
    int id = resources.getIdentifier("config_showNavigationBar", "bool", "Android");
    boolean hasOnScreenNavBar = id > 0 && resources.getBoolean(id);
    return hasOnScreenNavBar || hasNoCapacitiveKeys || getNavigationBarHeight(context, true) > 0;
}

public static int getNavigationBarHeight(Context context, boolean skipRequirement) {
    int resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "Android");
    if (resourceId > 0 && (skipRequirement || hasNavBar(context))) {
        return context.getResources().getDimensionPixelSize(resourceId);
    }
    return 0;
}
0
Jonas Borggren

Code testé pour obtenir la hauteur de la barre de navigation (en pixels):

public static int getNavBarHeight(Context c) {
    int resourceId = c.getResources()
                      .getIdentifier("navigation_bar_height", "dimen", "Android");
    if (resourceId > 0) {
        return c.getResources().getDimensionPixelSize(resourceId);
    }
    return 0;
}

Code testé pour obtenir la hauteur de la barre d'état (en pixels):

public static int getStatusBarHeight(Context c) {
    int resourceId = c.getResources()
                      .getIdentifier("status_bar_height", "dimen", "Android");
    if (resourceId > 0) {
        return c.getResources().getDimensionPixelSize(resourceId);
    }
    return 0;
}

Conversion de pixels en dp:

public static int pxToDp(int px) {
    return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}
0
Sagar