• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
18 package android.view;
19 
20 import 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  */
32 public 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     /**
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 
47     private boolean mSystemWindowInsetsConsumed = false;
48     private boolean mWindowDecorInsetsConsumed = false;
49     private boolean mStableInsetsConsumed = false;
50 
51     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      */
59     public static final WindowInsets CONSUMED;
60 
61     static {
62         CONSUMED = new WindowInsets(null, null, null, false, false);
63     }
64 
65     /** @hide */
WindowInsets(Rect systemWindowInsets, Rect windowDecorInsets, Rect stableInsets, boolean isRound, boolean alwaysConsumeNavBar)66     public WindowInsets(Rect systemWindowInsets, Rect windowDecorInsets, Rect stableInsets,
67             boolean isRound, boolean alwaysConsumeNavBar) {
68         mSystemWindowInsetsConsumed = systemWindowInsets == null;
69         mSystemWindowInsets = mSystemWindowInsetsConsumed ? EMPTY_RECT : systemWindowInsets;
70 
71         mWindowDecorInsetsConsumed = windowDecorInsets == null;
72         mWindowDecorInsets = mWindowDecorInsetsConsumed ? EMPTY_RECT : windowDecorInsets;
73 
74         mStableInsetsConsumed = stableInsets == null;
75         mStableInsets = mStableInsetsConsumed ? EMPTY_RECT : stableInsets;
76 
77         mIsRound = isRound;
78         mAlwaysConsumeNavBar = alwaysConsumeNavBar;
79     }
80 
81     /**
82      * Construct a new WindowInsets, copying all values from a source WindowInsets.
83      *
84      * @param src Source to copy insets from
85      */
WindowInsets(WindowInsets src)86     public WindowInsets(WindowInsets src) {
87         mSystemWindowInsets = src.mSystemWindowInsets;
88         mWindowDecorInsets = src.mWindowDecorInsets;
89         mStableInsets = src.mStableInsets;
90         mSystemWindowInsetsConsumed = src.mSystemWindowInsetsConsumed;
91         mWindowDecorInsetsConsumed = src.mWindowDecorInsetsConsumed;
92         mStableInsetsConsumed = src.mStableInsetsConsumed;
93         mIsRound = src.mIsRound;
94         mAlwaysConsumeNavBar = src.mAlwaysConsumeNavBar;
95     }
96 
97     /** @hide */
WindowInsets(Rect systemWindowInsets)98     public WindowInsets(Rect systemWindowInsets) {
99         this(systemWindowInsets, null, null, false, false);
100     }
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      */
getSystemWindowInsets()107     public Rect getSystemWindowInsets() {
108         if (mTempRect == null) {
109             mTempRect = new Rect();
110         }
111         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         }
117         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      */
getSystemWindowInsetLeft()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      */
getSystemWindowInsetTop()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      */
getSystemWindowInsetRight()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      */
getSystemWindowInsetBottom()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
180      * @hide pending API
181      */
getWindowDecorInsetLeft()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
194      * @hide pending API
195      */
getWindowDecorInsetTop()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
208      * @hide pending API
209      */
getWindowDecorInsetRight()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
222      * @hide pending API
223      */
getWindowDecorInsetBottom()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      */
hasSystemWindowInsets()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
250      * @hide pending API
251      */
hasWindowDecorInsets()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      */
hasInsets()262     public boolean hasInsets() {
263         return hasSystemWindowInsets() || hasWindowDecorInsets() || hasStableInsets();
264     }
265 
266     /**
267      * 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.
278      */
isConsumed()279     public boolean isConsumed() {
280         return mSystemWindowInsetsConsumed && mWindowDecorInsetsConsumed && mStableInsetsConsumed;
281     }
282 
283     /**
284      * 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      */
isRound()293     public boolean isRound() {
294         return mIsRound;
295     }
296 
297     /**
298      * Returns a copy of this WindowInsets with the system window insets fully consumed.
299      *
300      * @return A modified copy of this WindowInsets
301      */
consumeSystemWindowInsets()302     public WindowInsets consumeSystemWindowInsets() {
303         final WindowInsets result = new WindowInsets(this);
304         result.mSystemWindowInsets = EMPTY_RECT;
305         result.mSystemWindowInsetsConsumed = true;
306         return result;
307     }
308 
309     /**
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      */
consumeSystemWindowInsets(boolean left, boolean top, boolean right, boolean bottom)319     public WindowInsets consumeSystemWindowInsets(boolean left, boolean top,
320             boolean right, boolean bottom) {
321         if (left || top || right || bottom) {
322             final WindowInsets result = new WindowInsets(this);
323             result.mSystemWindowInsets = new Rect(
324                     left ? 0 : mSystemWindowInsets.left,
325                     top ? 0 : mSystemWindowInsets.top,
326                     right ? 0 : mSystemWindowInsets.right,
327                     bottom ? 0 : mSystemWindowInsets.bottom);
328             return result;
329         }
330         return this;
331     }
332 
333     /**
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      */
replaceSystemWindowInsets(int left, int top, int right, int bottom)343     public WindowInsets replaceSystemWindowInsets(int left, int top,
344             int right, int bottom) {
345         final WindowInsets result = new WindowInsets(this);
346         result.mSystemWindowInsets = new Rect(left, top, right, bottom);
347         return result;
348     }
349 
350     /**
351      * 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      */
replaceSystemWindowInsets(Rect systemWindowInsets)358     public WindowInsets replaceSystemWindowInsets(Rect systemWindowInsets) {
359         final WindowInsets result = new WindowInsets(this);
360         result.mSystemWindowInsets = new Rect(systemWindowInsets);
361         return result;
362     }
363 
364     /**
365      * @hide
366      */
consumeWindowDecorInsets()367     public WindowInsets consumeWindowDecorInsets() {
368         final WindowInsets result = new WindowInsets(this);
369         result.mWindowDecorInsets.set(0, 0, 0, 0);
370         result.mWindowDecorInsetsConsumed = true;
371         return result;
372     }
373 
374     /**
375      * @hide
376      */
consumeWindowDecorInsets(boolean left, boolean top, boolean right, boolean bottom)377     public WindowInsets consumeWindowDecorInsets(boolean left, boolean top,
378             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 
390     /**
391      * @hide
392      */
replaceWindowDecorInsets(int left, int top, int right, int bottom)393     public WindowInsets replaceWindowDecorInsets(int left, int top, int right, int bottom) {
394         final WindowInsets result = new WindowInsets(this);
395         result.mWindowDecorInsets = new Rect(left, top, right, bottom);
396         return result;
397     }
398 
399     /**
400      * 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
409      */
getStableInsetTop()410     public int getStableInsetTop() {
411         return mStableInsets.top;
412     }
413 
414     /**
415      * 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
424      */
getStableInsetLeft()425     public int getStableInsetLeft() {
426         return mStableInsets.left;
427     }
428 
429     /**
430      * 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
439      */
getStableInsetRight()440     public int getStableInsetRight() {
441         return mStableInsets.right;
442     }
443 
444     /**
445      * 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
454      */
getStableInsetBottom()455     public int getStableInsetBottom() {
456         return mStableInsets.bottom;
457     }
458 
459     /**
460      * 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
469      */
hasStableInsets()470     public boolean hasStableInsets() {
471         return mStableInsets.top != 0 || mStableInsets.left != 0 || mStableInsets.right != 0
472                 || mStableInsets.bottom != 0;
473     }
474 
475     /**
476      * Returns a copy of this WindowInsets with the stable insets fully consumed.
477      *
478      * @return A modified copy of this WindowInsets
479      */
consumeStableInsets()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 
487     /**
488      * @hide
489      */
shouldAlwaysConsumeNavBar()490     public boolean shouldAlwaysConsumeNavBar() {
491         return mAlwaysConsumeNavBar;
492     }
493 
494     @Override
toString()495     public String toString() {
496         return "WindowInsets{systemWindowInsets=" + mSystemWindowInsets
497                 + " windowDecorInsets=" + mWindowDecorInsets
498                 + " stableInsets=" + mStableInsets +
499                 (isRound() ? " round}" : "}");
500     }
501 }
502