WindowInsets.java revision d72068b38ec4e5732dde6093e39b2602babc27a3
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 * Returns a copy of this WindowInsets with selected system window insets replaced 345 * with new values. 346 * 347 * @param systemWindowInsets New system window insets. Each field is the inset in pixels 348 * for that edge 349 * @return A modified copy of this WindowInsets 350 */ 351 public WindowInsets replaceSystemWindowInsets(Rect systemWindowInsets) { 352 final WindowInsets result = new WindowInsets(this); 353 result.mSystemWindowInsets = new Rect(systemWindowInsets); 354 result.mSystemWindowInsetsConsumed = !hasSystemWindowInsets(); 355 return result; 356 } 357 358 /** 359 * @hide 360 */ 361 public WindowInsets consumeWindowDecorInsets() { 362 final WindowInsets result = new WindowInsets(this); 363 result.mWindowDecorInsets.set(0, 0, 0, 0); 364 result.mWindowDecorInsetsConsumed = true; 365 return result; 366 } 367 368 /** 369 * @hide 370 */ 371 public WindowInsets consumeWindowDecorInsets(boolean left, boolean top, 372 boolean right, boolean bottom) { 373 if (left || top || right || bottom) { 374 final WindowInsets result = new WindowInsets(this); 375 result.mWindowDecorInsets = new Rect(left ? 0 : mWindowDecorInsets.left, 376 top ? 0 : mWindowDecorInsets.top, 377 right ? 0 : mWindowDecorInsets.right, 378 bottom ? 0 : mWindowDecorInsets.bottom); 379 result.mWindowDecorInsetsConsumed = !hasWindowDecorInsets(); 380 return result; 381 } 382 return this; 383 } 384 385 /** 386 * @hide 387 */ 388 public WindowInsets replaceWindowDecorInsets(int left, int top, int right, int bottom) { 389 final WindowInsets result = new WindowInsets(this); 390 result.mWindowDecorInsets = new Rect(left, top, right, bottom); 391 result.mWindowDecorInsetsConsumed = !hasWindowDecorInsets(); 392 return result; 393 } 394 395 /** 396 * Returns the top stable inset in pixels. 397 * 398 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be 399 * partially or fully obscured by the system UI elements. This value does not change 400 * based on the visibility state of those elements; for example, if the status bar is 401 * normally shown, but temporarily hidden, the stable inset will still provide the inset 402 * associated with the status bar being shown.</p> 403 * 404 * @return The top stable inset 405 */ 406 public int getStableInsetTop() { 407 return mStableInsets.top; 408 } 409 410 /** 411 * Returns the left stable inset in pixels. 412 * 413 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be 414 * partially or fully obscured by the system UI elements. This value does not change 415 * based on the visibility state of those elements; for example, if the status bar is 416 * normally shown, but temporarily hidden, the stable inset will still provide the inset 417 * associated with the status bar being shown.</p> 418 * 419 * @return The left stable inset 420 */ 421 public int getStableInsetLeft() { 422 return mStableInsets.left; 423 } 424 425 /** 426 * Returns the right stable inset in pixels. 427 * 428 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be 429 * partially or fully obscured by the system UI elements. This value does not change 430 * based on the visibility state of those elements; for example, if the status bar is 431 * normally shown, but temporarily hidden, the stable inset will still provide the inset 432 * associated with the status bar being shown.</p> 433 * 434 * @return The right stable inset 435 */ 436 public int getStableInsetRight() { 437 return mStableInsets.right; 438 } 439 440 /** 441 * Returns the bottom stable inset in pixels. 442 * 443 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be 444 * partially or fully obscured by the system UI elements. This value does not change 445 * based on the visibility state of those elements; for example, if the status bar is 446 * normally shown, but temporarily hidden, the stable inset will still provide the inset 447 * associated with the status bar being shown.</p> 448 * 449 * @return The bottom stable inset 450 */ 451 public int getStableInsetBottom() { 452 return mStableInsets.bottom; 453 } 454 455 /** 456 * Returns true if this WindowInsets has nonzero stable insets. 457 * 458 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be 459 * partially or fully obscured by the system UI elements. This value does not change 460 * based on the visibility state of those elements; for example, if the status bar is 461 * normally shown, but temporarily hidden, the stable inset will still provide the inset 462 * associated with the status bar being shown.</p> 463 * 464 * @return true if any of the stable inset values are nonzero 465 */ 466 public boolean hasStableInsets() { 467 return mStableInsets.top != 0 || mStableInsets.left != 0 || mStableInsets.right != 0 468 || mStableInsets.bottom != 0; 469 } 470 471 /** 472 * Returns a copy of this WindowInsets with the stable insets fully consumed. 473 * 474 * @return A modified copy of this WindowInsets 475 */ 476 public WindowInsets consumeStableInsets() { 477 final WindowInsets result = new WindowInsets(this); 478 result.mStableInsets = EMPTY_RECT; 479 result.mStableInsetsConsumed = true; 480 return result; 481 } 482 483 @Override 484 public String toString() { 485 return "WindowInsets{systemWindowInsets=" + mSystemWindowInsets 486 + " windowDecorInsets=" + mWindowDecorInsets 487 + " stableInsets=" + mStableInsets + 488 (isRound() ? " round}" : "}"); 489 } 490} 491