blob: 929fdac82c284322d58547a7847fdcd283d1f753 [file] [log] [blame]
Adam Powell50d7bfd2014-02-03 10:16:49 -08001/*
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 */
Adam Powellf4a39412014-05-05 17:29:17 -070032public final class WindowInsets {
Adrian Roosfa104232014-06-20 16:10:14 -070033
Adam Powell50d7bfd2014-02-03 10:16:49 -080034 private Rect mSystemWindowInsets;
35 private Rect mWindowDecorInsets;
Adrian Roosfa104232014-06-20 16:10:14 -070036 private Rect mStableInsets;
Adam Powell50d7bfd2014-02-03 10:16:49 -080037 private Rect mTempRect;
Adam Powell973ddaa2014-04-15 17:38:54 -070038 private boolean mIsRound;
Adam Powell50d7bfd2014-02-03 10:16:49 -080039
Jorim Jaggi0ffd49c2016-02-12 15:04:21 -080040 /**
41 * In multi-window we force show the navigation bar. Because we don't want that the surface size
42 * changes in this mode, we instead have a flag whether the navigation bar size should always
43 * be consumed, so the app is treated like there is no virtual navigation bar at all.
44 */
45 private boolean mAlwaysConsumeNavBar;
46
Adam Powell0d9fdba2014-06-11 15:33:08 -070047 private boolean mSystemWindowInsetsConsumed = false;
48 private boolean mWindowDecorInsetsConsumed = false;
Adrian Roosfa104232014-06-20 16:10:14 -070049 private boolean mStableInsetsConsumed = false;
Adam Powell0d9fdba2014-06-11 15:33:08 -070050
Adam Powell50d7bfd2014-02-03 10:16:49 -080051 private static final Rect EMPTY_RECT = new Rect(0, 0, 0, 0);
52
53 /**
54 * Since new insets may be added in the future that existing apps couldn't
55 * know about, this fully empty constant shouldn't be made available to apps
56 * since it would allow them to inadvertently consume unknown insets by returning it.
57 * @hide
58 */
Adam Powell720924b2014-06-12 14:51:10 -070059 public static final WindowInsets CONSUMED;
60
61 static {
Jorim Jaggi0ffd49c2016-02-12 15:04:21 -080062 CONSUMED = new WindowInsets(null, null, null, false, false);
Adam Powell720924b2014-06-12 14:51:10 -070063 }
Adam Powell50d7bfd2014-02-03 10:16:49 -080064
65 /** @hide */
Adrian Roosfa104232014-06-20 16:10:14 -070066 public WindowInsets(Rect systemWindowInsets, Rect windowDecorInsets, Rect stableInsets,
Jorim Jaggi0ffd49c2016-02-12 15:04:21 -080067 boolean isRound, boolean alwaysConsumeNavBar) {
Adam Powell0d9fdba2014-06-11 15:33:08 -070068 mSystemWindowInsetsConsumed = systemWindowInsets == null;
69 mSystemWindowInsets = mSystemWindowInsetsConsumed ? EMPTY_RECT : systemWindowInsets;
70
71 mWindowDecorInsetsConsumed = windowDecorInsets == null;
72 mWindowDecorInsets = mWindowDecorInsetsConsumed ? EMPTY_RECT : windowDecorInsets;
73
Adrian Roosfa104232014-06-20 16:10:14 -070074 mStableInsetsConsumed = stableInsets == null;
75 mStableInsets = mStableInsetsConsumed ? EMPTY_RECT : stableInsets;
76
Adam Powell973ddaa2014-04-15 17:38:54 -070077 mIsRound = isRound;
Jorim Jaggi0ffd49c2016-02-12 15:04:21 -080078 mAlwaysConsumeNavBar = alwaysConsumeNavBar;
Adam Powell50d7bfd2014-02-03 10:16:49 -080079 }
80
81 /**
82 * Construct a new WindowInsets, copying all values from a source WindowInsets.
83 *
84 * @param src Source to copy insets from
85 */
86 public WindowInsets(WindowInsets src) {
87 mSystemWindowInsets = src.mSystemWindowInsets;
88 mWindowDecorInsets = src.mWindowDecorInsets;
Adrian Roosfa104232014-06-20 16:10:14 -070089 mStableInsets = src.mStableInsets;
Adam Powell0d9fdba2014-06-11 15:33:08 -070090 mSystemWindowInsetsConsumed = src.mSystemWindowInsetsConsumed;
91 mWindowDecorInsetsConsumed = src.mWindowDecorInsetsConsumed;
Adrian Roosfa104232014-06-20 16:10:14 -070092 mStableInsetsConsumed = src.mStableInsetsConsumed;
Adam Powell973ddaa2014-04-15 17:38:54 -070093 mIsRound = src.mIsRound;
Adam Powell50d7bfd2014-02-03 10:16:49 -080094 }
95
96 /** @hide */
97 public WindowInsets(Rect systemWindowInsets) {
Jorim Jaggi0ffd49c2016-02-12 15:04:21 -080098 this(systemWindowInsets, null, null, false, false);
Adam Powell50d7bfd2014-02-03 10:16:49 -080099 }
100
101 /**
102 * Used to provide a safe copy of the system window insets to pass through
103 * to the existing fitSystemWindows method and other similar internals.
104 * @hide
105 */
106 public Rect getSystemWindowInsets() {
107 if (mTempRect == null) {
108 mTempRect = new Rect();
109 }
Justin Koheba87822014-06-06 12:13:16 -0700110 if (mSystemWindowInsets != null) {
111 mTempRect.set(mSystemWindowInsets);
112 } else {
113 // If there were no system window insets, this is just empty.
114 mTempRect.setEmpty();
115 }
Adam Powell50d7bfd2014-02-03 10:16:49 -0800116 return mTempRect;
117 }
118
119 /**
120 * Returns the left system window inset in pixels.
121 *
122 * <p>The system window inset represents the area of a full-screen window that is
123 * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
124 * </p>
125 *
126 * @return The left system window inset
127 */
128 public int getSystemWindowInsetLeft() {
129 return mSystemWindowInsets.left;
130 }
131
132 /**
133 * Returns the top system window inset in pixels.
134 *
135 * <p>The system window inset represents the area of a full-screen window that is
136 * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
137 * </p>
138 *
139 * @return The top system window inset
140 */
141 public int getSystemWindowInsetTop() {
142 return mSystemWindowInsets.top;
143 }
144
145 /**
146 * Returns the right system window inset in pixels.
147 *
148 * <p>The system window inset represents the area of a full-screen window that is
149 * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
150 * </p>
151 *
152 * @return The right system window inset
153 */
154 public int getSystemWindowInsetRight() {
155 return mSystemWindowInsets.right;
156 }
157
158 /**
159 * Returns the bottom system window inset in pixels.
160 *
161 * <p>The system window inset represents the area of a full-screen window that is
162 * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
163 * </p>
164 *
165 * @return The bottom system window inset
166 */
167 public int getSystemWindowInsetBottom() {
168 return mSystemWindowInsets.bottom;
169 }
170
171 /**
172 * Returns the left window decor inset in pixels.
173 *
174 * <p>The window decor inset represents the area of the window content area that is
175 * partially or fully obscured by decorations within the window provided by the framework.
176 * This can include action bars, title bars, toolbars, etc.</p>
177 *
178 * @return The left window decor inset
Adam Powellf4a39412014-05-05 17:29:17 -0700179 * @hide pending API
Adam Powell50d7bfd2014-02-03 10:16:49 -0800180 */
181 public int getWindowDecorInsetLeft() {
182 return mWindowDecorInsets.left;
183 }
184
185 /**
186 * Returns the top window decor inset in pixels.
187 *
188 * <p>The window decor inset represents the area of the window content area that is
189 * partially or fully obscured by decorations within the window provided by the framework.
190 * This can include action bars, title bars, toolbars, etc.</p>
191 *
192 * @return The top window decor inset
Adam Powellf4a39412014-05-05 17:29:17 -0700193 * @hide pending API
Adam Powell50d7bfd2014-02-03 10:16:49 -0800194 */
195 public int getWindowDecorInsetTop() {
196 return mWindowDecorInsets.top;
197 }
198
199 /**
200 * Returns the right window decor inset in pixels.
201 *
202 * <p>The window decor inset represents the area of the window content area that is
203 * partially or fully obscured by decorations within the window provided by the framework.
204 * This can include action bars, title bars, toolbars, etc.</p>
205 *
206 * @return The right window decor inset
Adam Powellf4a39412014-05-05 17:29:17 -0700207 * @hide pending API
Adam Powell50d7bfd2014-02-03 10:16:49 -0800208 */
209 public int getWindowDecorInsetRight() {
210 return mWindowDecorInsets.right;
211 }
212
213 /**
214 * Returns the bottom window decor inset in pixels.
215 *
216 * <p>The window decor inset represents the area of the window content area that is
217 * partially or fully obscured by decorations within the window provided by the framework.
218 * This can include action bars, title bars, toolbars, etc.</p>
219 *
220 * @return The bottom window decor inset
Adam Powellf4a39412014-05-05 17:29:17 -0700221 * @hide pending API
Adam Powell50d7bfd2014-02-03 10:16:49 -0800222 */
223 public int getWindowDecorInsetBottom() {
224 return mWindowDecorInsets.bottom;
225 }
226
227 /**
228 * Returns true if this WindowInsets has nonzero system window insets.
229 *
230 * <p>The system window inset represents the area of a full-screen window that is
231 * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
232 * </p>
233 *
234 * @return true if any of the system window inset values are nonzero
235 */
236 public boolean hasSystemWindowInsets() {
237 return mSystemWindowInsets.left != 0 || mSystemWindowInsets.top != 0 ||
238 mSystemWindowInsets.right != 0 || mSystemWindowInsets.bottom != 0;
239 }
240
241 /**
242 * Returns true if this WindowInsets has nonzero window decor insets.
243 *
244 * <p>The window decor inset represents the area of the window content area that is
245 * partially or fully obscured by decorations within the window provided by the framework.
246 * This can include action bars, title bars, toolbars, etc.</p>
247 *
248 * @return true if any of the window decor inset values are nonzero
Adam Powellf4a39412014-05-05 17:29:17 -0700249 * @hide pending API
Adam Powell50d7bfd2014-02-03 10:16:49 -0800250 */
251 public boolean hasWindowDecorInsets() {
252 return mWindowDecorInsets.left != 0 || mWindowDecorInsets.top != 0 ||
253 mWindowDecorInsets.right != 0 || mWindowDecorInsets.bottom != 0;
254 }
255
256 /**
257 * Returns true if this WindowInsets has any nonzero insets.
258 *
259 * @return true if any inset values are nonzero
260 */
261 public boolean hasInsets() {
Adam Powell05e967822015-06-04 12:38:13 -0700262 return hasSystemWindowInsets() || hasWindowDecorInsets() || hasStableInsets();
Adam Powell50d7bfd2014-02-03 10:16:49 -0800263 }
264
Adam Powell973ddaa2014-04-15 17:38:54 -0700265 /**
Adam Powell0d9fdba2014-06-11 15:33:08 -0700266 * Check if these insets have been fully consumed.
267 *
268 * <p>Insets are considered "consumed" if the applicable <code>consume*</code> methods
269 * have been called such that all insets have been set to zero. This affects propagation of
270 * insets through the view hierarchy; insets that have not been fully consumed will continue
271 * to propagate down to child views.</p>
272 *
273 * <p>The result of this method is equivalent to the return value of
274 * {@link View#fitSystemWindows(android.graphics.Rect)}.</p>
275 *
276 * @return true if the insets have been fully consumed.
Adam Powell0d9fdba2014-06-11 15:33:08 -0700277 */
278 public boolean isConsumed() {
Adrian Roosfa104232014-06-20 16:10:14 -0700279 return mSystemWindowInsetsConsumed && mWindowDecorInsetsConsumed && mStableInsetsConsumed;
Adam Powell0d9fdba2014-06-11 15:33:08 -0700280 }
281
282 /**
Adam Powell973ddaa2014-04-15 17:38:54 -0700283 * Returns true if the associated window has a round shape.
284 *
285 * <p>A round window's left, top, right and bottom edges reach all the way to the
286 * associated edges of the window but the corners may not be visible. Views responding
287 * to round insets should take care to not lay out critical elements within the corners
288 * where they may not be accessible.</p>
289 *
290 * @return True if the window is round
291 */
292 public boolean isRound() {
293 return mIsRound;
294 }
295
Adam Powellf4a39412014-05-05 17:29:17 -0700296 /**
297 * Returns a copy of this WindowInsets with the system window insets fully consumed.
298 *
299 * @return A modified copy of this WindowInsets
300 */
301 public WindowInsets consumeSystemWindowInsets() {
Adam Powell50d7bfd2014-02-03 10:16:49 -0800302 final WindowInsets result = new WindowInsets(this);
Adam Powell0d9fdba2014-06-11 15:33:08 -0700303 result.mSystemWindowInsets = EMPTY_RECT;
304 result.mSystemWindowInsetsConsumed = true;
Adam Powell50d7bfd2014-02-03 10:16:49 -0800305 return result;
306 }
307
Adam Powellf4a39412014-05-05 17:29:17 -0700308 /**
309 * Returns a copy of this WindowInsets with selected system window insets fully consumed.
310 *
311 * @param left true to consume the left system window inset
312 * @param top true to consume the top system window inset
313 * @param right true to consume the right system window inset
314 * @param bottom true to consume the bottom system window inset
315 * @return A modified copy of this WindowInsets
316 * @hide pending API
317 */
318 public WindowInsets consumeSystemWindowInsets(boolean left, boolean top,
Adam Powell50d7bfd2014-02-03 10:16:49 -0800319 boolean right, boolean bottom) {
320 if (left || top || right || bottom) {
321 final WindowInsets result = new WindowInsets(this);
Adam Powell0d9fdba2014-06-11 15:33:08 -0700322 result.mSystemWindowInsets = new Rect(
323 left ? 0 : mSystemWindowInsets.left,
Adam Powell50d7bfd2014-02-03 10:16:49 -0800324 top ? 0 : mSystemWindowInsets.top,
325 right ? 0 : mSystemWindowInsets.right,
326 bottom ? 0 : mSystemWindowInsets.bottom);
327 return result;
328 }
329 return this;
330 }
331
Adam Powellf4a39412014-05-05 17:29:17 -0700332 /**
333 * Returns a copy of this WindowInsets with selected system window insets replaced
334 * with new values.
335 *
336 * @param left New left inset in pixels
337 * @param top New top inset in pixels
338 * @param right New right inset in pixels
339 * @param bottom New bottom inset in pixels
340 * @return A modified copy of this WindowInsets
341 */
342 public WindowInsets replaceSystemWindowInsets(int left, int top,
343 int right, int bottom) {
Adam Powell50d7bfd2014-02-03 10:16:49 -0800344 final WindowInsets result = new WindowInsets(this);
345 result.mSystemWindowInsets = new Rect(left, top, right, bottom);
346 return result;
347 }
348
Adam Powellf4a39412014-05-05 17:29:17 -0700349 /**
Adam Powelld72068b2014-09-12 14:42:25 -0700350 * Returns a copy of this WindowInsets with selected system window insets replaced
351 * with new values.
352 *
353 * @param systemWindowInsets New system window insets. Each field is the inset in pixels
354 * for that edge
355 * @return A modified copy of this WindowInsets
356 */
357 public WindowInsets replaceSystemWindowInsets(Rect systemWindowInsets) {
358 final WindowInsets result = new WindowInsets(this);
359 result.mSystemWindowInsets = new Rect(systemWindowInsets);
Adam Powelld72068b2014-09-12 14:42:25 -0700360 return result;
361 }
362
363 /**
Adam Powellf4a39412014-05-05 17:29:17 -0700364 * @hide
365 */
366 public WindowInsets consumeWindowDecorInsets() {
Adam Powell50d7bfd2014-02-03 10:16:49 -0800367 final WindowInsets result = new WindowInsets(this);
368 result.mWindowDecorInsets.set(0, 0, 0, 0);
Adam Powell0d9fdba2014-06-11 15:33:08 -0700369 result.mWindowDecorInsetsConsumed = true;
Adam Powell50d7bfd2014-02-03 10:16:49 -0800370 return result;
371 }
372
Adam Powellf4a39412014-05-05 17:29:17 -0700373 /**
374 * @hide
375 */
376 public WindowInsets consumeWindowDecorInsets(boolean left, boolean top,
Adam Powell50d7bfd2014-02-03 10:16:49 -0800377 boolean right, boolean bottom) {
378 if (left || top || right || bottom) {
379 final WindowInsets result = new WindowInsets(this);
380 result.mWindowDecorInsets = new Rect(left ? 0 : mWindowDecorInsets.left,
381 top ? 0 : mWindowDecorInsets.top,
382 right ? 0 : mWindowDecorInsets.right,
383 bottom ? 0 : mWindowDecorInsets.bottom);
384 return result;
385 }
386 return this;
387 }
388
Adam Powellf4a39412014-05-05 17:29:17 -0700389 /**
390 * @hide
391 */
392 public WindowInsets replaceWindowDecorInsets(int left, int top, int right, int bottom) {
Adam Powell50d7bfd2014-02-03 10:16:49 -0800393 final WindowInsets result = new WindowInsets(this);
394 result.mWindowDecorInsets = new Rect(left, top, right, bottom);
395 return result;
396 }
397
Adrian Roosfa104232014-06-20 16:10:14 -0700398 /**
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700399 * Returns the top stable inset in pixels.
400 *
401 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
402 * partially or fully obscured by the system UI elements. This value does not change
403 * based on the visibility state of those elements; for example, if the status bar is
404 * normally shown, but temporarily hidden, the stable inset will still provide the inset
405 * associated with the status bar being shown.</p>
406 *
407 * @return The top stable inset
Adrian Roosfa104232014-06-20 16:10:14 -0700408 */
409 public int getStableInsetTop() {
410 return mStableInsets.top;
411 }
412
413 /**
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700414 * Returns the left stable inset in pixels.
415 *
416 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
417 * partially or fully obscured by the system UI elements. This value does not change
418 * based on the visibility state of those elements; for example, if the status bar is
419 * normally shown, but temporarily hidden, the stable inset will still provide the inset
420 * associated with the status bar being shown.</p>
421 *
422 * @return The left stable inset
Adrian Roosfa104232014-06-20 16:10:14 -0700423 */
424 public int getStableInsetLeft() {
425 return mStableInsets.left;
426 }
427
428 /**
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700429 * Returns the right stable inset in pixels.
430 *
431 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
432 * partially or fully obscured by the system UI elements. This value does not change
433 * based on the visibility state of those elements; for example, if the status bar is
434 * normally shown, but temporarily hidden, the stable inset will still provide the inset
435 * associated with the status bar being shown.</p>
436 *
437 * @return The right stable inset
Adrian Roosfa104232014-06-20 16:10:14 -0700438 */
439 public int getStableInsetRight() {
440 return mStableInsets.right;
441 }
442
443 /**
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700444 * Returns the bottom stable inset in pixels.
445 *
446 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
447 * partially or fully obscured by the system UI elements. This value does not change
448 * based on the visibility state of those elements; for example, if the status bar is
449 * normally shown, but temporarily hidden, the stable inset will still provide the inset
450 * associated with the status bar being shown.</p>
451 *
452 * @return The bottom stable inset
Adrian Roosfa104232014-06-20 16:10:14 -0700453 */
454 public int getStableInsetBottom() {
455 return mStableInsets.bottom;
456 }
457
458 /**
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700459 * Returns true if this WindowInsets has nonzero stable insets.
460 *
461 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
462 * partially or fully obscured by the system UI elements. This value does not change
463 * based on the visibility state of those elements; for example, if the status bar is
464 * normally shown, but temporarily hidden, the stable inset will still provide the inset
465 * associated with the status bar being shown.</p>
466 *
467 * @return true if any of the stable inset values are nonzero
Adrian Roosfa104232014-06-20 16:10:14 -0700468 */
469 public boolean hasStableInsets() {
470 return mStableInsets.top != 0 || mStableInsets.left != 0 || mStableInsets.right != 0
471 || mStableInsets.bottom != 0;
472 }
473
474 /**
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700475 * Returns a copy of this WindowInsets with the stable insets fully consumed.
476 *
477 * @return A modified copy of this WindowInsets
Adrian Roosfa104232014-06-20 16:10:14 -0700478 */
479 public WindowInsets consumeStableInsets() {
480 final WindowInsets result = new WindowInsets(this);
481 result.mStableInsets = EMPTY_RECT;
482 result.mStableInsetsConsumed = true;
483 return result;
484 }
485
Jorim Jaggi0ffd49c2016-02-12 15:04:21 -0800486 /**
487 * @hide
488 */
489 public boolean shouldAlwaysConsumeNavBar() {
490 return mAlwaysConsumeNavBar;
491 }
492
Adam Powell50d7bfd2014-02-03 10:16:49 -0800493 @Override
494 public String toString() {
Adrian Roosfa104232014-06-20 16:10:14 -0700495 return "WindowInsets{systemWindowInsets=" + mSystemWindowInsets
496 + " windowDecorInsets=" + mWindowDecorInsets
497 + " stableInsets=" + mStableInsets +
498 (isRound() ? " round}" : "}");
Adam Powell50d7bfd2014-02-03 10:16:49 -0800499 }
500}