프로그래밍 방식으로 Android 탐색 모음의 높이와 너비를 어떻게 얻습니까? 하드웨어 버튼을

화면 하단의 검은 색 탐색 표시 줄은 Android에서 쉽게 제거 할 수 없습니다. 3.0부터 하드웨어 버튼을 대체하기 위해 Android의 일부였습니다. 다음은 사진입니다.

이 UI 요소의 너비와 높이의 크기를 픽셀 단위로 구하려면 어떻게해야합니까?



답변

아래 코드를 시도하십시오.

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

답변

앱에서 사용 가능한 화면 크기와 실제 화면 크기를 비교하여 내비게이션 막대 크기를 얻습니다. 앱에서 사용할 수있는 화면 크기가 실제 화면 크기보다 작을 때 내비게이션 바가 있다고 가정합니다. 그런 다음 내비게이션 막대 크기를 계산합니다. 이 방법은 API 14 이상에서 작동합니다.

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;
}

최신 정보

디스플레이 컷 아웃을 고려하는 솔루션에 대해서는 John의 답변을 확인하십시오 .


답변

NavigationBar 높이는 장치에 따라 다르지만 방향에 따라 다릅니다. 먼저 장치에 navbar가 있는지 확인한 다음 장치가 태블릿인지 아니면 태블릿이 아닌지 (휴대폰) 마지막으로 올바른 높이를 얻으려면 장치의 방향을 확인해야합니다.

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;
}

답변

실제로 태블릿 (최소 Nexus 7)의 내비게이션 바는 세로와 가로에서 크기가 다르므로이 기능은 다음과 같이 표시됩니다.

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;
}

답변

더 나은 답이 여기에 있다고 생각합니다. 왜냐하면 컷 아웃 높이도 얻을 수 있기 때문입니다.

루트 뷰를 가져 와서 setOnApplyWindowInsetsListener를 추가하고 (또는 여기에서 onApplyWindowInsets를 재정의 할 수 있음) 여기에서 insets.getSystemWindowInsets를 가져옵니다.

내 카메라 활동에서 systemWindowInsetBottom과 동일한 패딩을 하단 레이아웃에 추가합니다. 마지막으로 컷 아웃 문제를 수정합니다.

appcompat을 사용하면 다음과 같습니다.

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

appcompat이 없으면 다음과 같습니다.

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

답변

도움이 되었기를 바랍니다.

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;
}

답변

이것은 탐색 모음을 피하기 위해 paddingRight 및 paddingBottom을 View에 추가하는 코드입니다. 여기에 몇 가지 답변을 결합하고 isInMultiWindowMode와 함께 가로 방향에 대한 특수 절을 만들었습니다. 핵심은 navigation_bar_height 를 읽고 config_showNavigationBar 도 확인하는 것입니다. 를 확인하여 실제로 높이를 사용해야하는지 확인합니다.

이전 솔루션 중 어느 것도 나를 위해 일하지 않았습니다. Android 7.0부터는 다중 창 모드를 고려해야합니다. realSize 는 전체 화면 (두 분할 창 모두)의 크기를 제공 하고 크기 는 앱 창의 크기 만 제공 하므로 display.realSizedisplay.size를 비교하는 구현이 중단 됩니다. 패딩을이 차이로 설정하면 전체 뷰가 패딩이됩니다.

/** 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);
}