blob: 750931ab661c2fc3e76f44b4ca639a2b08cc439c [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;
Jorim Jaggie5638a62016-03-25 22:57:01 -070094 mAlwaysConsumeNavBar = src.mAlwaysConsumeNavBar;
Adam Powell50d7bfd2014-02-03 10:16:49 -080095 }
96
97 /** @hide */
98 public WindowInsets(Rect systemWindowInsets) {
Jorim Jaggi0ffd49c2016-02-12 15:04:21 -080099 this(systemWindowInsets, null, null, false, false);
Adam Powell50d7bfd2014-02-03 10:16:49 -0800100 }
101
102 /**
103 * Used to provide a safe copy of the system window insets to pass through
104 * to the existing fitSystemWindows method and other similar internals.
105 * @hide
106 */
107 public Rect getSystemWindowInsets() {
108 if (mTempRect == null) {
109 mTempRect = new Rect();
110 }
Justin Koheba87822014-06-06 12:13:16 -0700111 if (mSystemWindowInsets != null) {
112 mTempRect.set(mSystemWindowInsets);
113 } else {
114 // If there were no system window insets, this is just empty.
115 mTempRect.setEmpty();
116 }
Adam Powell50d7bfd2014-02-03 10:16:49 -0800117 return mTempRect;
118 }
119
120 /**
121 * Returns the left system window inset in pixels.
122 *
123 * <p>The system window inset represents the area of a full-screen window that is
124 * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
125 * </p>
126 *
127 * @return The left system window inset
128 */
129 public int getSystemWindowInsetLeft() {
130 return mSystemWindowInsets.left;
131 }
132
133 /**
134 * Returns the top system window inset in pixels.
135 *
136 * <p>The system window inset represents the area of a full-screen window that is
137 * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
138 * </p>
139 *
140 * @return The top system window inset
141 */
142 public int getSystemWindowInsetTop() {
143 return mSystemWindowInsets.top;
144 }
145
146 /**
147 * Returns the right system window inset in pixels.
148 *
149 * <p>The system window inset represents the area of a full-screen window that is
150 * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
151 * </p>
152 *
153 * @return The right system window inset
154 */
155 public int getSystemWindowInsetRight() {
156 return mSystemWindowInsets.right;
157 }
158
159 /**
160 * Returns the bottom system window inset in pixels.
161 *
162 * <p>The system window inset represents the area of a full-screen window that is
163 * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
164 * </p>
165 *
166 * @return The bottom system window inset
167 */
168 public int getSystemWindowInsetBottom() {
169 return mSystemWindowInsets.bottom;
170 }
171
172 /**
173 * Returns the left window decor inset in pixels.
174 *
175 * <p>The window decor inset represents the area of the window content area that is
176 * partially or fully obscured by decorations within the window provided by the framework.
177 * This can include action bars, title bars, toolbars, etc.</p>
178 *
179 * @return The left window decor inset
Adam Powellf4a39412014-05-05 17:29:17 -0700180 * @hide pending API
Adam Powell50d7bfd2014-02-03 10:16:49 -0800181 */
182 public int getWindowDecorInsetLeft() {
183 return mWindowDecorInsets.left;
184 }
185
186 /**
187 * Returns the top window decor inset in pixels.
188 *
189 * <p>The window decor inset represents the area of the window content area that is
190 * partially or fully obscured by decorations within the window provided by the framework.
191 * This can include action bars, title bars, toolbars, etc.</p>
192 *
193 * @return The top window decor inset
Adam Powellf4a39412014-05-05 17:29:17 -0700194 * @hide pending API
Adam Powell50d7bfd2014-02-03 10:16:49 -0800195 */
196 public int getWindowDecorInsetTop() {
197 return mWindowDecorInsets.top;
198 }
199
200 /**
201 * Returns the right window decor inset in pixels.
202 *
203 * <p>The window decor inset represents the area of the window content area that is
204 * partially or fully obscured by decorations within the window provided by the framework.
205 * This can include action bars, title bars, toolbars, etc.</p>
206 *
207 * @return The right window decor inset
Adam Powellf4a39412014-05-05 17:29:17 -0700208 * @hide pending API
Adam Powell50d7bfd2014-02-03 10:16:49 -0800209 */
210 public int getWindowDecorInsetRight() {
211 return mWindowDecorInsets.right;
212 }
213
214 /**
215 * Returns the bottom window decor inset in pixels.
216 *
217 * <p>The window decor inset represents the area of the window content area that is
218 * partially or fully obscured by decorations within the window provided by the framework.
219 * This can include action bars, title bars, toolbars, etc.</p>
220 *
221 * @return The bottom window decor inset
Adam Powellf4a39412014-05-05 17:29:17 -0700222 * @hide pending API
Adam Powell50d7bfd2014-02-03 10:16:49 -0800223 */
224 public int getWindowDecorInsetBottom() {
225 return mWindowDecorInsets.bottom;
226 }
227
228 /**
229 * Returns true if this WindowInsets has nonzero system window insets.
230 *
231 * <p>The system window inset represents the area of a full-screen window that is
232 * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
233 * </p>
234 *
235 * @return true if any of the system window inset values are nonzero
236 */
237 public boolean hasSystemWindowInsets() {
238 return mSystemWindowInsets.left != 0 || mSystemWindowInsets.top != 0 ||
239 mSystemWindowInsets.right != 0 || mSystemWindowInsets.bottom != 0;
240 }
241
242 /**
243 * Returns true if this WindowInsets has nonzero window decor insets.
244 *
245 * <p>The window decor inset represents the area of the window content area that is
246 * partially or fully obscured by decorations within the window provided by the framework.
247 * This can include action bars, title bars, toolbars, etc.</p>
248 *
249 * @return true if any of the window decor inset values are nonzero
Adam Powellf4a39412014-05-05 17:29:17 -0700250 * @hide pending API
Adam Powell50d7bfd2014-02-03 10:16:49 -0800251 */
252 public boolean hasWindowDecorInsets() {
253 return mWindowDecorInsets.left != 0 || mWindowDecorInsets.top != 0 ||
254 mWindowDecorInsets.right != 0 || mWindowDecorInsets.bottom != 0;
255 }
256
257 /**
258 * Returns true if this WindowInsets has any nonzero insets.
259 *
260 * @return true if any inset values are nonzero
261 */
262 public boolean hasInsets() {
Adam Powell05e967822015-06-04 12:38:13 -0700263 return hasSystemWindowInsets() || hasWindowDecorInsets() || hasStableInsets();
Adam Powell50d7bfd2014-02-03 10:16:49 -0800264 }
265
Adam Powell973ddaa2014-04-15 17:38:54 -0700266 /**
Adam Powell0d9fdba2014-06-11 15:33:08 -0700267 * Check if these insets have been fully consumed.
268 *
269 * <p>Insets are considered "consumed" if the applicable <code>consume*</code> methods
270 * have been called such that all insets have been set to zero. This affects propagation of
271 * insets through the view hierarchy; insets that have not been fully consumed will continue
272 * to propagate down to child views.</p>
273 *
274 * <p>The result of this method is equivalent to the return value of
275 * {@link View#fitSystemWindows(android.graphics.Rect)}.</p>
276 *
277 * @return true if the insets have been fully consumed.
Adam Powell0d9fdba2014-06-11 15:33:08 -0700278 */
279 public boolean isConsumed() {
Adrian Roosfa104232014-06-20 16:10:14 -0700280 return mSystemWindowInsetsConsumed && mWindowDecorInsetsConsumed && mStableInsetsConsumed;
Adam Powell0d9fdba2014-06-11 15:33:08 -0700281 }
282
283 /**
Adam Powell973ddaa2014-04-15 17:38:54 -0700284 * Returns true if the associated window has a round shape.
285 *
286 * <p>A round window's left, top, right and bottom edges reach all the way to the
287 * associated edges of the window but the corners may not be visible. Views responding
288 * to round insets should take care to not lay out critical elements within the corners
289 * where they may not be accessible.</p>
290 *
291 * @return True if the window is round
292 */
293 public boolean isRound() {
294 return mIsRound;
295 }
296
Adam Powellf4a39412014-05-05 17:29:17 -0700297 /**
298 * Returns a copy of this WindowInsets with the system window insets fully consumed.
299 *
300 * @return A modified copy of this WindowInsets
301 */
302 public WindowInsets consumeSystemWindowInsets() {
Adam Powell50d7bfd2014-02-03 10:16:49 -0800303 final WindowInsets result = new WindowInsets(this);
Adam Powell0d9fdba2014-06-11 15:33:08 -0700304 result.mSystemWindowInsets = EMPTY_RECT;
305 result.mSystemWindowInsetsConsumed = true;
Adam Powell50d7bfd2014-02-03 10:16:49 -0800306 return result;
307 }
308
Adam Powellf4a39412014-05-05 17:29:17 -0700309 /**
310 * Returns a copy of this WindowInsets with selected system window insets fully consumed.
311 *
312 * @param left true to consume the left system window inset
313 * @param top true to consume the top system window inset
314 * @param right true to consume the right system window inset
315 * @param bottom true to consume the bottom system window inset
316 * @return A modified copy of this WindowInsets
317 * @hide pending API
318 */
319 public WindowInsets consumeSystemWindowInsets(boolean left, boolean top,
Adam Powell50d7bfd2014-02-03 10:16:49 -0800320 boolean right, boolean bottom) {
321 if (left || top || right || bottom) {
322 final WindowInsets result = new WindowInsets(this);
Adam Powell0d9fdba2014-06-11 15:33:08 -0700323 result.mSystemWindowInsets = new Rect(
324 left ? 0 : mSystemWindowInsets.left,
Adam Powell50d7bfd2014-02-03 10:16:49 -0800325 top ? 0 : mSystemWindowInsets.top,
326 right ? 0 : mSystemWindowInsets.right,
327 bottom ? 0 : mSystemWindowInsets.bottom);
328 return result;
329 }
330 return this;
331 }
332
Adam Powellf4a39412014-05-05 17:29:17 -0700333 /**
334 * Returns a copy of this WindowInsets with selected system window insets replaced
335 * with new values.
336 *
337 * @param left New left inset in pixels
338 * @param top New top inset in pixels
339 * @param right New right inset in pixels
340 * @param bottom New bottom inset in pixels
341 * @return A modified copy of this WindowInsets
342 */
343 public WindowInsets replaceSystemWindowInsets(int left, int top,
344 int right, int bottom) {
Adam Powell50d7bfd2014-02-03 10:16:49 -0800345 final WindowInsets result = new WindowInsets(this);
346 result.mSystemWindowInsets = new Rect(left, top, right, bottom);
347 return result;
348 }
349
Adam Powellf4a39412014-05-05 17:29:17 -0700350 /**
Adam Powelld72068b2014-09-12 14:42:25 -0700351 * Returns a copy of this WindowInsets with selected system window insets replaced
352 * with new values.
353 *
354 * @param systemWindowInsets New system window insets. Each field is the inset in pixels
355 * for that edge
356 * @return A modified copy of this WindowInsets
357 */
358 public WindowInsets replaceSystemWindowInsets(Rect systemWindowInsets) {
359 final WindowInsets result = new WindowInsets(this);
360 result.mSystemWindowInsets = new Rect(systemWindowInsets);
Adam Powelld72068b2014-09-12 14:42:25 -0700361 return result;
362 }
363
364 /**
Adam Powellf4a39412014-05-05 17:29:17 -0700365 * @hide
366 */
367 public WindowInsets consumeWindowDecorInsets() {
Adam Powell50d7bfd2014-02-03 10:16:49 -0800368 final WindowInsets result = new WindowInsets(this);
369 result.mWindowDecorInsets.set(0, 0, 0, 0);
Adam Powell0d9fdba2014-06-11 15:33:08 -0700370 result.mWindowDecorInsetsConsumed = true;
Adam Powell50d7bfd2014-02-03 10:16:49 -0800371 return result;
372 }
373
Adam Powellf4a39412014-05-05 17:29:17 -0700374 /**
375 * @hide
376 */
377 public WindowInsets consumeWindowDecorInsets(boolean left, boolean top,
Adam Powell50d7bfd2014-02-03 10:16:49 -0800378 boolean right, boolean bottom) {
379 if (left || top || right || bottom) {
380 final WindowInsets result = new WindowInsets(this);
381 result.mWindowDecorInsets = new Rect(left ? 0 : mWindowDecorInsets.left,
382 top ? 0 : mWindowDecorInsets.top,
383 right ? 0 : mWindowDecorInsets.right,
384 bottom ? 0 : mWindowDecorInsets.bottom);
385 return result;
386 }
387 return this;
388 }
389
Adam Powellf4a39412014-05-05 17:29:17 -0700390 /**
391 * @hide
392 */
393 public WindowInsets replaceWindowDecorInsets(int left, int top, int right, int bottom) {
Adam Powell50d7bfd2014-02-03 10:16:49 -0800394 final WindowInsets result = new WindowInsets(this);
395 result.mWindowDecorInsets = new Rect(left, top, right, bottom);
396 return result;
397 }
398
Adrian Roosfa104232014-06-20 16:10:14 -0700399 /**
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700400 * Returns the top stable inset in pixels.
401 *
402 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
403 * partially or fully obscured by the system UI elements. This value does not change
404 * based on the visibility state of those elements; for example, if the status bar is
405 * normally shown, but temporarily hidden, the stable inset will still provide the inset
406 * associated with the status bar being shown.</p>
407 *
408 * @return The top stable inset
Adrian Roosfa104232014-06-20 16:10:14 -0700409 */
410 public int getStableInsetTop() {
411 return mStableInsets.top;
412 }
413
414 /**
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700415 * Returns the left stable inset in pixels.
416 *
417 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
418 * partially or fully obscured by the system UI elements. This value does not change
419 * based on the visibility state of those elements; for example, if the status bar is
420 * normally shown, but temporarily hidden, the stable inset will still provide the inset
421 * associated with the status bar being shown.</p>
422 *
423 * @return The left stable inset
Adrian Roosfa104232014-06-20 16:10:14 -0700424 */
425 public int getStableInsetLeft() {
426 return mStableInsets.left;
427 }
428
429 /**
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700430 * Returns the right stable inset in pixels.
431 *
432 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
433 * partially or fully obscured by the system UI elements. This value does not change
434 * based on the visibility state of those elements; for example, if the status bar is
435 * normally shown, but temporarily hidden, the stable inset will still provide the inset
436 * associated with the status bar being shown.</p>
437 *
438 * @return The right stable inset
Adrian Roosfa104232014-06-20 16:10:14 -0700439 */
440 public int getStableInsetRight() {
441 return mStableInsets.right;
442 }
443
444 /**
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700445 * Returns the bottom stable inset in pixels.
446 *
447 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
448 * partially or fully obscured by the system UI elements. This value does not change
449 * based on the visibility state of those elements; for example, if the status bar is
450 * normally shown, but temporarily hidden, the stable inset will still provide the inset
451 * associated with the status bar being shown.</p>
452 *
453 * @return The bottom stable inset
Adrian Roosfa104232014-06-20 16:10:14 -0700454 */
455 public int getStableInsetBottom() {
456 return mStableInsets.bottom;
457 }
458
459 /**
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700460 * Returns true if this WindowInsets has nonzero stable insets.
461 *
462 * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
463 * partially or fully obscured by the system UI elements. This value does not change
464 * based on the visibility state of those elements; for example, if the status bar is
465 * normally shown, but temporarily hidden, the stable inset will still provide the inset
466 * associated with the status bar being shown.</p>
467 *
468 * @return true if any of the stable inset values are nonzero
Adrian Roosfa104232014-06-20 16:10:14 -0700469 */
470 public boolean hasStableInsets() {
471 return mStableInsets.top != 0 || mStableInsets.left != 0 || mStableInsets.right != 0
472 || mStableInsets.bottom != 0;
473 }
474
475 /**
Dianne Hackborn067e5f62014-09-07 23:14:30 -0700476 * Returns a copy of this WindowInsets with the stable insets fully consumed.
477 *
478 * @return A modified copy of this WindowInsets
Adrian Roosfa104232014-06-20 16:10:14 -0700479 */
480 public WindowInsets consumeStableInsets() {
481 final WindowInsets result = new WindowInsets(this);
482 result.mStableInsets = EMPTY_RECT;
483 result.mStableInsetsConsumed = true;
484 return result;
485 }
486
Jorim Jaggi0ffd49c2016-02-12 15:04:21 -0800487 /**
488 * @hide
489 */
490 public boolean shouldAlwaysConsumeNavBar() {
491 return mAlwaysConsumeNavBar;
492 }
493
Adam Powell50d7bfd2014-02-03 10:16:49 -0800494 @Override
495 public String toString() {
Adrian Roosfa104232014-06-20 16:10:14 -0700496 return "WindowInsets{systemWindowInsets=" + mSystemWindowInsets
497 + " windowDecorInsets=" + mWindowDecorInsets
498 + " stableInsets=" + mStableInsets +
499 (isRound() ? " round}" : "}");
Adam Powell50d7bfd2014-02-03 10:16:49 -0800500 }
501}