WindowInsets.java revision 82a53881f1e0257f700bdca27216fc26d0c87b59
1/* 2 * Copyright (C) 2014 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 18package android.view; 19 20import android.graphics.Rect; 21 22/** 23 * Describes a set of insets for window content. 24 * 25 * <p>WindowInsets are immutable and may be expanded to include more inset types in the future. 26 * To adjust insets, use one of the supplied clone methods to obtain a new WindowInsets instance 27 * with the adjusted properties.</p> 28 * 29 * @see View.OnApplyWindowInsetsListener 30 * @see View#onApplyWindowInsets(WindowInsets) 31 */ 32public final class WindowInsets { 33 34 private Rect mSystemWindowInsets; 35 private Rect mWindowDecorInsets; 36 private Rect mStableInsets; 37 private Rect mTempRect; 38 private boolean mIsRound; 39 40 private boolean mSystemWindowInsetsConsumed = false; 41 private boolean mWindowDecorInsetsConsumed = false; 42 private boolean mStableInsetsConsumed = false; 43 44 private static final Rect EMPTY_RECT = new Rect(0, 0, 0, 0); 45 46 /** 47 * Since new insets may be added in the future that existing apps couldn't 48 * know about, this fully empty constant shouldn't be made available to apps 49 * since it would allow them to inadvertently consume unknown insets by returning it. 50 * @hide 51 */ 52 public static final WindowInsets CONSUMED; 53 54 static { 55 CONSUMED = new WindowInsets(null, null, null, false); 56 } 57 58 /** @hide */ 59 public WindowInsets(Rect systemWindowInsets, Rect windowDecorInsets, Rect stableInsets, 60 boolean isRound) { 61 mSystemWindowInsetsConsumed = systemWindowInsets == null; 62 mSystemWindowInsets = mSystemWindowInsetsConsumed ? EMPTY_RECT : systemWindowInsets; 63 64 mWindowDecorInsetsConsumed = windowDecorInsets == null; 65 mWindowDecorInsets = mWindowDecorInsetsConsumed ? EMPTY_RECT : windowDecorInsets; 66 67 mStableInsetsConsumed = stableInsets == null; 68 mStableInsets = mStableInsetsConsumed ? EMPTY_RECT : stableInsets; 69 70 mIsRound = isRound; 71 } 72 73 /** 74 * Construct a new WindowInsets, copying all values from a source WindowInsets. 75 * 76 * @param src Source to copy insets from 77 */ 78 public WindowInsets(WindowInsets src) { 79 mSystemWindowInsets = src.mSystemWindowInsets; 80 mWindowDecorInsets = src.mWindowDecorInsets; 81 mStableInsets = src.mStableInsets; 82 mSystemWindowInsetsConsumed = src.mSystemWindowInsetsConsumed; 83 mWindowDecorInsetsConsumed = src.mWindowDecorInsetsConsumed; 84 mStableInsetsConsumed = src.mStableInsetsConsumed; 85 mIsRound = src.mIsRound; 86 } 87 88 /** @hide */ 89 public WindowInsets(Rect systemWindowInsets) { 90 this(systemWindowInsets, null, null, false); 91 } 92 93 /** 94 * Used to provide a safe copy of the system window insets to pass through 95 * to the existing fitSystemWindows method and other similar internals. 96 * @hide 97 */ 98 public Rect getSystemWindowInsets() { 99 if (mTempRect == null) { 100 mTempRect = new Rect(); 101 } 102 if (mSystemWindowInsets != null) { 103 mTempRect.set(mSystemWindowInsets); 104 } else { 105 // If there were no system window insets, this is just empty. 106 mTempRect.setEmpty(); 107 } 108 return mTempRect; 109 } 110 111 /** 112 * Returns the left system window inset in pixels. 113 * 114 * <p>The system window inset represents the area of a full-screen window that is 115 * partially or fully obscured by the status bar, navigation bar, IME or other system windows. 116 * </p> 117 * 118 * @return The left system window inset 119 */ 120 public int getSystemWindowInsetLeft() { 121 return mSystemWindowInsets.left; 122 } 123 124 /** 125 * Returns the top system window inset in pixels. 126 * 127 * <p>The system window inset represents the area of a full-screen window that is 128 * partially or fully obscured by the status bar, navigation bar, IME or other system windows. 129 * </p> 130 * 131 * @return The top system window inset 132 */ 133 public int getSystemWindowInsetTop() { 134 return mSystemWindowInsets.top; 135 } 136 137 /** 138 * Returns the right system window inset in pixels. 139 * 140 * <p>The system window inset represents the area of a full-screen window that is 141 * partially or fully obscured by the status bar, navigation bar, IME or other system windows. 142 * </p> 143 * 144 * @return The right system window inset 145 */ 146 public int getSystemWindowInsetRight() { 147 return mSystemWindowInsets.right; 148 } 149 150 /** 151 * Returns the bottom system window inset in pixels. 152 * 153 * <p>The system window inset represents the area of a full-screen window that is 154 * partially or fully obscured by the status bar, navigation bar, IME or other system windows. 155 * </p> 156 * 157 * @return The bottom system window inset 158 */ 159 public int getSystemWindowInsetBottom() { 160 return mSystemWindowInsets.bottom; 161 } 162 163 /** 164 * Returns the left window decor inset in pixels. 165 * 166 * <p>The window decor inset represents the area of the window content area that is 167 * partially or fully obscured by decorations within the window provided by the framework. 168 * This can include action bars, title bars, toolbars, etc.</p> 169 * 170 * @return The left window decor inset 171 * @hide pending API 172 */ 173 public int getWindowDecorInsetLeft() { 174 return mWindowDecorInsets.left; 175 } 176 177 /** 178 * Returns the top window decor inset in pixels. 179 * 180 * <p>The window decor inset represents the area of the window content area that is 181 * partially or fully obscured by decorations within the window provided by the framework. 182 * This can include action bars, title bars, toolbars, etc.</p> 183 * 184 * @return The top window decor inset 185 * @hide pending API 186 */ 187 public int getWindowDecorInsetTop() { 188 return mWindowDecorInsets.top; 189 } 190 191 /** 192 * Returns the right window decor inset in pixels. 193 * 194 * <p>The window decor inset represents the area of the window content area that is 195 * partially or fully obscured by decorations within the window provided by the framework. 196 * This can include action bars, title bars, toolbars, etc.</p> 197 * 198 * @return The right window decor inset 199 * @hide pending API 200 */ 201 public int getWindowDecorInsetRight() { 202 return mWindowDecorInsets.right; 203 } 204 205 /** 206 * Returns the bottom window decor inset in pixels. 207 * 208 * <p>The window decor inset represents the area of the window content area that is 209 * partially or fully obscured by decorations within the window provided by the framework. 210 * This can include action bars, title bars, toolbars, etc.</p> 211 * 212 * @return The bottom window decor inset 213 * @hide pending API 214 */ 215 public int getWindowDecorInsetBottom() { 216 return mWindowDecorInsets.bottom; 217 } 218 219 /** 220 * Returns true if this WindowInsets has nonzero system window insets. 221 * 222 * <p>The system window inset represents the area of a full-screen window that is 223 * partially or fully obscured by the status bar, navigation bar, IME or other system windows. 224 * </p> 225 * 226 * @return true if any of the system window inset values are nonzero 227 */ 228 public boolean hasSystemWindowInsets() { 229 return mSystemWindowInsets.left != 0 || mSystemWindowInsets.top != 0 || 230 mSystemWindowInsets.right != 0 || mSystemWindowInsets.bottom != 0; 231 } 232 233 /** 234 * Returns true if this WindowInsets has nonzero window decor insets. 235 * 236 * <p>The window decor inset represents the area of the window content area that is 237 * partially or fully obscured by decorations within the window provided by the framework. 238 * This can include action bars, title bars, toolbars, etc.</p> 239 * 240 * @return true if any of the window decor inset values are nonzero 241 * @hide pending API 242 */ 243 public boolean hasWindowDecorInsets() { 244 return mWindowDecorInsets.left != 0 || mWindowDecorInsets.top != 0 || 245 mWindowDecorInsets.right != 0 || mWindowDecorInsets.bottom != 0; 246 } 247 248 /** 249 * Returns true if this WindowInsets has any nonzero insets. 250 * 251 * @return true if any inset values are nonzero 252 */ 253 public boolean hasInsets() { 254 return hasSystemWindowInsets() || hasWindowDecorInsets(); 255 } 256 257 /** 258 * Check if these insets have been fully consumed. 259 * 260 * <p>Insets are considered "consumed" if the applicable <code>consume*</code> methods 261 * have been called such that all insets have been set to zero. This affects propagation of 262 * insets through the view hierarchy; insets that have not been fully consumed will continue 263 * to propagate down to child views.</p> 264 * 265 * <p>The result of this method is equivalent to the return value of 266 * {@link View#fitSystemWindows(android.graphics.Rect)}.</p> 267 * 268 * @return true if the insets have been fully consumed. 269 */ 270 public boolean isConsumed() { 271 return mSystemWindowInsetsConsumed && mWindowDecorInsetsConsumed && mStableInsetsConsumed; 272 } 273 274 /** 275 * Returns true if the associated window has a round shape. 276 * 277 * <p>A round window's left, top, right and bottom edges reach all the way to the 278 * associated edges of the window but the corners may not be visible. Views responding 279 * to round insets should take care to not lay out critical elements within the corners 280 * where they may not be accessible.</p> 281 * 282 * @return True if the window is round 283 */ 284 public boolean isRound() { 285 return mIsRound; 286 } 287 288 /** 289 * Returns a copy of this WindowInsets with the system window insets fully consumed. 290 * 291 * @return A modified copy of this WindowInsets 292 */ 293 public WindowInsets consumeSystemWindowInsets() { 294 final WindowInsets result = new WindowInsets(this); 295 result.mSystemWindowInsets = EMPTY_RECT; 296 result.mSystemWindowInsetsConsumed = true; 297 return result; 298 } 299 300 /** 301 * Returns a copy of this WindowInsets with selected system window insets fully consumed. 302 * 303 * @param left true to consume the left system window inset 304 * @param top true to consume the top system window inset 305 * @param right true to consume the right system window inset 306 * @param bottom true to consume the bottom system window inset 307 * @return A modified copy of this WindowInsets 308 * @hide pending API 309 */ 310 public WindowInsets consumeSystemWindowInsets(boolean left, boolean top, 311 boolean right, boolean bottom) { 312 if (left || top || right || bottom) { 313 final WindowInsets result = new WindowInsets(this); 314 result.mSystemWindowInsets = new Rect( 315 left ? 0 : mSystemWindowInsets.left, 316 top ? 0 : mSystemWindowInsets.top, 317 right ? 0 : mSystemWindowInsets.right, 318 bottom ? 0 : mSystemWindowInsets.bottom); 319 result.mSystemWindowInsetsConsumed = !hasSystemWindowInsets(); 320 return result; 321 } 322 return this; 323 } 324 325 /** 326 * Returns a copy of this WindowInsets with selected system window insets replaced 327 * with new values. 328 * 329 * @param left New left inset in pixels 330 * @param top New top inset in pixels 331 * @param right New right inset in pixels 332 * @param bottom New bottom inset in pixels 333 * @return A modified copy of this WindowInsets 334 */ 335 public WindowInsets replaceSystemWindowInsets(int left, int top, 336 int right, int bottom) { 337 final WindowInsets result = new WindowInsets(this); 338 result.mSystemWindowInsets = new Rect(left, top, right, bottom); 339 result.mSystemWindowInsetsConsumed = !hasSystemWindowInsets(); 340 return result; 341 } 342 343 /** 344 * @hide 345 */ 346 public WindowInsets consumeWindowDecorInsets() { 347 final WindowInsets result = new WindowInsets(this); 348 result.mWindowDecorInsets.set(0, 0, 0, 0); 349 result.mWindowDecorInsetsConsumed = true; 350 return result; 351 } 352 353 /** 354 * @hide 355 */ 356 public WindowInsets consumeWindowDecorInsets(boolean left, boolean top, 357 boolean right, boolean bottom) { 358 if (left || top || right || bottom) { 359 final WindowInsets result = new WindowInsets(this); 360 result.mWindowDecorInsets = new Rect(left ? 0 : mWindowDecorInsets.left, 361 top ? 0 : mWindowDecorInsets.top, 362 right ? 0 : mWindowDecorInsets.right, 363 bottom ? 0 : mWindowDecorInsets.bottom); 364 result.mWindowDecorInsetsConsumed = !hasWindowDecorInsets(); 365 return result; 366 } 367 return this; 368 } 369 370 /** 371 * @hide 372 */ 373 public WindowInsets replaceWindowDecorInsets(int left, int top, int right, int bottom) { 374 final WindowInsets result = new WindowInsets(this); 375 result.mWindowDecorInsets = new Rect(left, top, right, bottom); 376 result.mWindowDecorInsetsConsumed = !hasWindowDecorInsets(); 377 return result; 378 } 379 380 /** 381 * @hide 382 */ 383 public int getStableInsetTop() { 384 return mStableInsets.top; 385 } 386 387 /** 388 * @hide 389 */ 390 public int getStableInsetLeft() { 391 return mStableInsets.left; 392 } 393 394 /** 395 * @hide 396 */ 397 public int getStableInsetRight() { 398 return mStableInsets.right; 399 } 400 401 /** 402 * @hide 403 */ 404 public int getStableInsetBottom() { 405 return mStableInsets.bottom; 406 } 407 408 /** 409 * @hide 410 */ 411 public boolean hasStableInsets() { 412 return mStableInsets.top != 0 || mStableInsets.left != 0 || mStableInsets.right != 0 413 || mStableInsets.bottom != 0; 414 } 415 416 /** 417 * @hide 418 */ 419 public WindowInsets consumeStableInsets() { 420 final WindowInsets result = new WindowInsets(this); 421 result.mStableInsets = EMPTY_RECT; 422 result.mStableInsetsConsumed = true; 423 return result; 424 } 425 426 @Override 427 public String toString() { 428 return "WindowInsets{systemWindowInsets=" + mSystemWindowInsets 429 + " windowDecorInsets=" + mWindowDecorInsets 430 + " stableInsets=" + mStableInsets + 431 (isRound() ? " round}" : "}"); 432 } 433} 434