From 8e603940e3fca4ed2fe420c02a66d860b53f3076 Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Mon, 1 Feb 2016 09:08:56 -0800 Subject: [PATCH] Use `getRealMetrics` for display metrics. Closes #4934 Summary: Fixes https://github.com/facebook/react-native/issues/4934. Since API level 17, there has a `Display.getRealMetrics` method. This allows us to get the actual sizes of the screen (including soft menu bar and other system decor elements). See: http://developer.android.com/reference/android/view/Display.html#getRealMetrics(android.util.DisplayMetrics) I'm not sure if there is a good way to write unit or integration tests for this. Please let me know if there are any suggestions or concerns. Closes https://github.com/facebook/react-native/pull/4935 Reviewed By: svcscm Differential Revision: D2811091 Pulled By: bestander fb-gh-sync-id: fed4e357db7eb36d638eebabd8ced4bdffd766a4 --- .../react/uimanager/UIManagerModule.java | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java index 2a701d692..725c874c3 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java @@ -11,11 +11,17 @@ package com.facebook.react.uimanager; import javax.annotation.Nullable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; import java.util.Map; +import android.content.Context; +import android.os.Build; import android.util.DisplayMetrics; +import android.view.Display; +import android.view.WindowManager; import com.facebook.csslayout.CSSLayoutContext; import com.facebook.infer.annotation.Assertions; @@ -84,7 +90,9 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements UIImplementation uiImplementation) { super(reactContext); mEventDispatcher = new EventDispatcher(reactContext); - DisplayMetrics displayMetrics = reactContext.getResources().getDisplayMetrics(); + + DisplayMetrics displayMetrics = getDisplayMetrics(); + DisplayMetricsHolder.setDisplayMetrics(displayMetrics); mModuleConstants = createConstants(displayMetrics, viewManagerList); mUIImplementation = uiImplementation; @@ -452,4 +460,39 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements public void sendAccessibilityEvent(int tag, int eventType) { mUIImplementation.sendAccessibilityEvent(tag, eventType); } + + private DisplayMetrics getDisplayMetrics() { + Context context = getReactApplicationContext(); + + DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Display display = wm.getDefaultDisplay(); + + // Get the real display metrics if we are using API level 17 or higher. + // The real metrics include system decor elements (e.g. soft menu bar). + // + // See: http://developer.android.com/reference/android/view/Display.html#getRealMetrics(android.util.DisplayMetrics) + if (Build.VERSION.SDK_INT >= 17){ + display.getRealMetrics(displayMetrics); + + } else { + // For 14 <= API level <= 16, we need to invoke getRawHeight and getRawWidth to get the real dimensions. + // Since react-native only supports API level 16+ we don't have to worry about other cases. + // + // Reflection exceptions are rethrown at runtime. + // + // See: http://stackoverflow.com/questions/14341041/how-to-get-real-screen-height-and-width/23861333#23861333 + try { + Method mGetRawH = Display.class.getMethod("getRawHeight"); + Method mGetRawW = Display.class.getMethod("getRawWidth"); + displayMetrics.widthPixels = (Integer) mGetRawW.invoke(display); + displayMetrics.heightPixels = (Integer) mGetRawH.invoke(display); + } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) { + throw new RuntimeException("Error getting real dimensions for API level < 17", e); + } + } + + return displayMetrics; + } + }