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 * @see android.annotation.UiContext 51 */ 52 public final class WindowMetrics { 53 @NonNull 54 private final Rect mBounds; 55 56 private WindowInsets mWindowInsets; 57 private Supplier<WindowInsets> mWindowInsetsSupplier; 58 59 /** @see android.util.DisplayMetrics#density */ 60 private final float mDensity; 61 62 /** @deprecated use {@link #WindowMetrics(Rect, WindowInsets, float)} instead. */ 63 @Deprecated WindowMetrics(@onNull Rect bounds, @NonNull WindowInsets windowInsets)64 public WindowMetrics(@NonNull Rect bounds, @NonNull WindowInsets windowInsets) { 65 this(bounds, windowInsets, 1.0f); 66 } 67 68 /** 69 * The constructor to create a {@link WindowMetrics} instance. 70 * <p> 71 * Note that in most cases {@link WindowMetrics} is obtained from 72 * {@link WindowManager#getCurrentWindowMetrics()} or 73 * {@link WindowManager#getMaximumWindowMetrics()}. 74 * </p> 75 * 76 * @param bounds The window bounds 77 * @param windowInsets The {@link WindowInsets} of the window 78 * @param density The window density 79 */ WindowMetrics(@onNull Rect bounds, @NonNull WindowInsets windowInsets, float density)80 public WindowMetrics(@NonNull Rect bounds, @NonNull WindowInsets windowInsets, float density) { 81 mBounds = bounds; 82 mWindowInsets = windowInsets; 83 mDensity = density; 84 } 85 86 /** 87 * Similar to {@link #WindowMetrics(Rect, WindowInsets, float)} but the window insets are 88 * computed when {@link #getWindowInsets()} is first time called. This reduces unnecessary 89 * calculation and the overhead of obtaining insets state from server side because most 90 * callers are usually only interested in {@link #getBounds()}. 91 * 92 * @hide 93 */ WindowMetrics(@onNull Rect bounds, @NonNull Supplier<WindowInsets> windowInsetsSupplier, float density)94 public WindowMetrics(@NonNull Rect bounds, @NonNull Supplier<WindowInsets> windowInsetsSupplier, 95 float density) { 96 mBounds = bounds; 97 mWindowInsetsSupplier = windowInsetsSupplier; 98 mDensity = density; 99 } 100 101 /** 102 * Returns the bounds of the area associated with this window or 103 * {@link android.annotation.UiContext}. 104 * <p> 105 * <b>Note that the size of the reported bounds can have different size than 106 * {@link Display#getSize(Point)}.</b> This method reports the window size including all system 107 * bar areas, while {@link Display#getSize(Point)} reports the area excluding navigation bars 108 * and display cutout areas. The value reported by {@link Display#getSize(Point)} can be 109 * obtained by using: 110 * <pre class="prettyprint"> 111 * final WindowMetrics metrics = windowManager.getCurrentWindowMetrics(); 112 * // Gets all excluding insets 113 * final WindowInsets windowInsets = metrics.getWindowInsets(); 114 * Insets insets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars() 115 * | WindowInsets.Type.displayCutout()); 116 * 117 * int insetsWidth = insets.right + insets.left; 118 * int insetsHeight = insets.top + insets.bottom; 119 * 120 * // Legacy size that Display#getSize reports 121 * final Rect bounds = metrics.getBounds(); 122 * final Size legacySize = new Size(bounds.width() - insetsWidth, 123 * bounds.height() - insetsHeight); 124 * </pre> 125 * </p> 126 * 127 * @return window bounds in pixels. 128 */ 129 @NonNull getBounds()130 public Rect getBounds() { 131 return mBounds; 132 } 133 134 /** 135 * Returns the {@link WindowInsets} of the area associated with this window or 136 * {@link android.annotation.UiContext}. 137 * 138 * @return the {@link WindowInsets} of the visual area. 139 */ 140 @NonNull getWindowInsets()141 public WindowInsets getWindowInsets() { 142 if (mWindowInsets != null) { 143 return mWindowInsets; 144 } 145 return mWindowInsets = mWindowInsetsSupplier.get(); 146 } 147 148 /** 149 * Returns the density of the area associated with this window or 150 * {@link android.annotation.UiContext}, which uses the same units as 151 * {@link android.util.DisplayMetrics#density}. 152 * 153 * @see android.util.DisplayMetrics#DENSITY_DEFAULT 154 * @see android.util.DisplayMetrics#density 155 */ getDensity()156 public float getDensity() { 157 return mDensity; 158 } 159 160 @Override toString()161 public String toString() { 162 return WindowMetrics.class.getSimpleName() + ":{" 163 + "bounds=" + mBounds 164 + ", windowInsets=" + mWindowInsets 165 + ", density=" + mDensity 166 + "}"; 167 } 168 } 169