1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.view; 18 19 import android.annotation.NonNull; 20 import android.graphics.Point; 21 import android.graphics.Rect; 22 23 import java.util.function.Supplier; 24 25 /** 26 * Metrics about a Window, consisting of the bounds and {@link WindowInsets}. 27 * <p> 28 * This is usually obtained from {@link WindowManager#getCurrentWindowMetrics()} and 29 * {@link WindowManager#getMaximumWindowMetrics()}. 30 * </p> 31 * After {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, it also provides density. 32 * <h3>Obtains Window Dimensions in Density-independent Pixel(DP)</h3> 33 * <p> 34 * While {@link #getDensity()} is provided, the dimension in density-independent pixel could also be 35 * calculated with {@code WindowMetrics} properties, which is similar to 36 * {@link android.content.res.Configuration#screenWidthDp} 37 * <pre class="prettyprint"> 38 * float widthInDp = windowMetrics.getBounds().width() / windowMetrics.getDensity(); 39 * float heightInDp = windowMetrics.getBounds().height() / windowMetrics.getDensity(); 40 * </pre> 41 * Also, the density in DPI can be obtained by: 42 * <pre class="prettyprint"> 43 * float densityDp = DisplayMetrics.DENSITY_DEFAULT * windowMetrics.getDensity(); 44 * </pre> 45 * </p> 46 * 47 * @see WindowInsets#getInsets(int) 48 * @see WindowManager#getCurrentWindowMetrics() 49 * @see WindowManager#getMaximumWindowMetrics() 50 */ 51 public final class WindowMetrics { 52 @NonNull 53 private final Rect mBounds; 54 55 private WindowInsets mWindowInsets; 56 private Supplier<WindowInsets> mWindowInsetsSupplier; 57 58 /** @see android.util.DisplayMetrics#density */ 59 private final float mDensity; 60 61 /** @deprecated use {@link #WindowMetrics(Rect, WindowInsets, float)} instead. */ 62 @Deprecated WindowMetrics(@onNull Rect bounds, @NonNull WindowInsets windowInsets)63 public WindowMetrics(@NonNull Rect bounds, @NonNull WindowInsets windowInsets) { 64 this(bounds, windowInsets, 1.0f); 65 } 66 67 /** 68 * The constructor to create a {@link WindowMetrics} instance. 69 * <p> 70 * Note that in most cases {@link WindowMetrics} is obtained from 71 * {@link WindowManager#getCurrentWindowMetrics()} or 72 * {@link WindowManager#getMaximumWindowMetrics()}. 73 * </p> 74 * 75 * @param bounds The window bounds 76 * @param windowInsets The {@link WindowInsets} of the window 77 * @param density The window density 78 */ WindowMetrics(@onNull Rect bounds, @NonNull WindowInsets windowInsets, float density)79 public WindowMetrics(@NonNull Rect bounds, @NonNull WindowInsets windowInsets, float density) { 80 mBounds = bounds; 81 mWindowInsets = windowInsets; 82 mDensity = density; 83 } 84 85 /** 86 * Similar to {@link #WindowMetrics(Rect, WindowInsets, float)} but the window insets are 87 * computed when {@link #getWindowInsets()} is first time called. This reduces unnecessary 88 * calculation and the overhead of obtaining insets state from server side because most 89 * callers are usually only interested in {@link #getBounds()}. 90 * 91 * @hide 92 */ WindowMetrics(@onNull Rect bounds, @NonNull Supplier<WindowInsets> windowInsetsSupplier, float density)93 public WindowMetrics(@NonNull Rect bounds, @NonNull Supplier<WindowInsets> windowInsetsSupplier, 94 float density) { 95 mBounds = bounds; 96 mWindowInsetsSupplier = windowInsetsSupplier; 97 mDensity = density; 98 } 99 100 /** 101 * Returns the bounds of the area associated with this window or {@code UiContext}. 102 * <p> 103 * <b>Note that the size of the reported bounds can have different size than 104 * {@link Display#getSize(Point)} based on your target API level and calling context.</b> 105 * This method reports the window size including all system 106 * bar areas, while {@link Display#getSize(Point)} can report the area excluding navigation bars 107 * and display cutout areas depending on the calling context and target SDK level. Please refer 108 * to {@link Display#getSize(Point)} for details. 109 * <p> 110 * The value reported by {@link Display#getSize(Point)} excluding system decoration areas can be 111 * obtained by using: 112 * <pre class="prettyprint"> 113 * final WindowMetrics metrics = windowManager.getCurrentWindowMetrics(); 114 * // Gets all excluding insets 115 * final WindowInsets windowInsets = metrics.getWindowInsets(); 116 * Insets insets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars() 117 * | WindowInsets.Type.displayCutout()); 118 * 119 * int insetsWidth = insets.right + insets.left; 120 * int insetsHeight = insets.top + insets.bottom; 121 * 122 * // Legacy size that Display#getSize reports 123 * final Rect bounds = metrics.getBounds(); 124 * final Size legacySize = new Size(bounds.width() - insetsWidth, 125 * bounds.height() - insetsHeight); 126 * </pre> 127 * </p> 128 * 129 * @return window bounds in pixels. 130 */ 131 @NonNull getBounds()132 public Rect getBounds() { 133 return mBounds; 134 } 135 136 /** 137 * Returns the {@link WindowInsets} of the area associated with this window or 138 * {@code UiContext}. 139 * 140 * @return the {@link WindowInsets} of the visual area. 141 */ 142 @NonNull getWindowInsets()143 public WindowInsets getWindowInsets() { 144 if (mWindowInsets != null) { 145 return mWindowInsets; 146 } 147 return mWindowInsets = mWindowInsetsSupplier.get(); 148 } 149 150 /** 151 * Returns the density of the area associated with this window or {@code UiContext}, 152 * which uses the same units as {@link android.util.DisplayMetrics#density}. 153 * 154 * @see android.util.DisplayMetrics#DENSITY_DEFAULT 155 * @see android.util.DisplayMetrics#density 156 */ getDensity()157 public float getDensity() { 158 return mDensity; 159 } 160 161 @Override toString()162 public String toString() { 163 return WindowMetrics.class.getSimpleName() + ":{" 164 + "bounds=" + mBounds 165 + ", windowInsets=" + mWindowInsets 166 + ", density=" + mDensity 167 + "}"; 168 } 169 } 170