diff --git a/core/api/current.txt b/core/api/current.txt index fc319ce6891e9..975f99a0408a2 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -52288,8 +52288,10 @@ package android.view { } public final class WindowMetrics { - ctor public WindowMetrics(@NonNull android.graphics.Rect, @NonNull android.view.WindowInsets); + ctor @Deprecated public WindowMetrics(@NonNull android.graphics.Rect, @NonNull android.view.WindowInsets); + ctor public WindowMetrics(@NonNull android.graphics.Rect, @NonNull android.view.WindowInsets, float); method @NonNull public android.graphics.Rect getBounds(); + method public float getDensity(); method @NonNull public android.view.WindowInsets getWindowInsets(); } diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index fb1fcf8e2a063..d6934bca46b76 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -43,6 +43,7 @@ import android.annotation.StyleableRes; import android.annotation.XmlRes; import android.app.Application; import android.compat.annotation.UnsupportedAppUsage; +import android.content.Context; import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo.Config; import android.content.res.loader.ResourcesLoader; @@ -2181,17 +2182,19 @@ public class Resources { } /** - * Return the current display metrics that are in effect for this resource + * Returns the current display metrics that are in effect for this resource * object. The returned object should be treated as read-only. * *

Note that the reported value may be different than the window this application is * interested in.

* - *

Best practices are to obtain metrics from {@link WindowManager#getCurrentWindowMetrics()} - * for window bounds, {@link Display#getRealMetrics(DisplayMetrics)} for display bounds and - * obtain density from {@link Configuration#densityDpi}. The value obtained from this API may be - * wrong if the {@link Resources} is from the context which is different than the window is - * attached such as {@link Application#getResources()}. + *

The best practices is to obtain metrics from + * {@link WindowManager#getCurrentWindowMetrics()} for window bounds. The value obtained from + * this API may be wrong if {@link Context#getResources()} is from + * non-{@link android.annotation.UiContext}. + * For example, use the {@link DisplayMetrics} obtained from {@link Application#getResources()} + * to build {@link android.app.Activity} UI elements especially when the + * {@link android.app.Activity} is in the multi-window mode or on the secondary {@link Display}. *

* * @return The resource's current display metrics. diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java index 517d98222093a..2defb13299adf 100755 --- a/core/java/android/util/DisplayMetrics.java +++ b/core/java/android/util/DisplayMetrics.java @@ -19,12 +19,23 @@ package android.util; import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.os.SystemProperties; +import android.view.WindowManager; /** * A structure describing general information about a display, such as its * size, density, and font scaling. *

To access the DisplayMetrics members, retrieve display metrics like this:

*
context.getResources().getDisplayMetrics();
+ * + *

+ * For UI layout, obtain {@link android.view.WindowMetrics} from + * {@link WindowManager#getCurrentWindowMetrics()}. {@code DisplayMetrics} should only be used for + * obtaining display related properties, such as {@link #xdpi} and {@link #ydpi} + *

+ * See {@link #density} for more information about the differences between {@link #xdpi}, + * {@link #ydpi} and {@link #density}. + *

+ * */ public class DisplayMetrics { /** diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 5933ae4f8ca45..d06eb44f0ac49 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -1434,7 +1434,8 @@ public final class Display { * @param outMetrics A {@link DisplayMetrics} object which receives the display metrics. * * @deprecated Use {@link WindowMetrics#getBounds()} to get the dimensions of the application - * window. Use {@link Configuration#densityDpi} to get the display density. + * window. Use {@link WindowMetrics#getDensity()} to get the density of the application + * window. */ @Deprecated public void getMetrics(DisplayMetrics outMetrics) { diff --git a/core/java/android/view/WindowMetrics.java b/core/java/android/view/WindowMetrics.java index 52e4e15cc9a01..141849f0593a0 100644 --- a/core/java/android/view/WindowMetrics.java +++ b/core/java/android/view/WindowMetrics.java @@ -25,22 +25,64 @@ import android.graphics.Rect; *

* This is usually obtained from {@link WindowManager#getCurrentWindowMetrics()} and * {@link WindowManager#getMaximumWindowMetrics()}. + *

+ * After {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, it also provides density. + *

Obtains Window Dimensions in Density-independent Pixel(DP)

+ *

+ * While {@link #getDensity()} is provided, the dimension in density-independent pixel could also be + * calculated with {@code WindowMetrics} properties, which is similar to + * {@link android.content.res.Configuration#screenWidthDp} + *

+ * float widthInDp = windowMetrics.getBounds().width() / windowMetrics.getDensity();
+ * float heightInDp = windowMetrics.getBounds().height() / windowMetrics.getDensity();
+ * 
+ * Also, the density in DPI can be obtained by: + *
+ * float densityDp = DisplayMetrics.DENSITY_DEFAULT * windowMetrics.getDensity();
+ * 
+ *

* * @see WindowInsets#getInsets(int) * @see WindowManager#getCurrentWindowMetrics() * @see WindowManager#getMaximumWindowMetrics() + * @see android.annotation.UiContext */ public final class WindowMetrics { - private final @NonNull Rect mBounds; - private final @NonNull WindowInsets mWindowInsets; + @NonNull + private final Rect mBounds; + @NonNull + private final WindowInsets mWindowInsets; + /** @see android.util.DisplayMetrics#density */ + private final float mDensity; + + /** @deprecated use {@link #WindowMetrics(Rect, WindowInsets, float)} instead. */ + @Deprecated public WindowMetrics(@NonNull Rect bounds, @NonNull WindowInsets windowInsets) { - mBounds = bounds; - mWindowInsets = windowInsets; + this(bounds, windowInsets, 1.0f); } /** - * Returns the bounds of the area associated with this window or visual context. + * The constructor to create a {@link WindowMetrics} instance. + *

+ * Note that in most cases {@link WindowMetrics} is obtained from + * {@link WindowManager#getCurrentWindowMetrics()} or + * {@link WindowManager#getMaximumWindowMetrics()}. + *

+ * + * @param bounds The window bounds + * @param windowInsets The {@link WindowInsets} of the window + * @param density The window density + */ + public WindowMetrics(@NonNull Rect bounds, @NonNull WindowInsets windowInsets, float density) { + mBounds = bounds; + mWindowInsets = windowInsets; + mDensity = density; + } + + /** + * Returns the bounds of the area associated with this window or + * {@link android.annotation.UiContext}. *

* Note that the size of the reported bounds can have different size than * {@link Display#getSize(Point)}. This method reports the window size including all system @@ -66,16 +108,40 @@ public final class WindowMetrics { * * @return window bounds in pixels. */ - public @NonNull Rect getBounds() { + @NonNull + public Rect getBounds() { return mBounds; } /** - * Returns the {@link WindowInsets} of the area associated with this window or visual context. + * Returns the {@link WindowInsets} of the area associated with this window or + * {@link android.annotation.UiContext}. * * @return the {@link WindowInsets} of the visual area. */ - public @NonNull WindowInsets getWindowInsets() { + @NonNull + public WindowInsets getWindowInsets() { return mWindowInsets; } + + /** + * Returns the density of the area associated with this window or + * {@link android.annotation.UiContext}, which uses the same units as + * {@link android.util.DisplayMetrics#density}. + * + * @see android.util.DisplayMetrics#DENSITY_DEFAULT + * @see android.util.DisplayMetrics#density + */ + public float getDensity() { + return mDensity; + } + + @Override + public String toString() { + return WindowMetrics.class.getSimpleName() + ":{" + + "bounds=" + mBounds + + ", windowInsets=" + mWindowInsets + + ", density" + mDensity + + "}"; + } }