WindowInsetsCompat.java revision d739b48735e949e61654bd216e0dddebcb028287
1/*
2 * Copyright (C) 2016 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
17package android.support.v4.view;
18
19import android.graphics.Rect;
20import android.os.Build;
21
22/**
23 * Describes a set of insets for window content.
24 *
25 * <p>WindowInsetsCompats are immutable and may be expanded to include more inset types in the
26 * future. To adjust insets, use one of the supplied clone methods to obtain a new
27 * WindowInsetsCompat instance with the adjusted properties.</p>
28 */
29public class WindowInsetsCompat {
30    private interface WindowInsetsCompatImpl {
31        int getSystemWindowInsetLeft(Object insets);
32        int getSystemWindowInsetTop(Object insets);
33        int getSystemWindowInsetRight(Object insets);
34        int getSystemWindowInsetBottom(Object insets);
35        boolean hasSystemWindowInsets(Object insets);
36        boolean hasInsets(Object insets);
37        boolean isConsumed(Object insets);
38        boolean isRound(Object insets);
39        WindowInsetsCompat consumeSystemWindowInsets(Object insets);
40        WindowInsetsCompat replaceSystemWindowInsets(Object insets,
41                int left, int top, int right, int bottom);
42        WindowInsetsCompat replaceSystemWindowInsets(Object insets, Rect systemWindowInsets);
43        int getStableInsetTop(Object insets);
44        int getStableInsetLeft(Object insets);
45        int getStableInsetRight(Object insets);
46        int getStableInsetBottom(Object insets);
47        boolean hasStableInsets(Object insets);
48        WindowInsetsCompat consumeStableInsets(Object insets);
49        Object getSourceWindowInsets(Object src);
50    }
51
52    private static class WindowInsetsCompatBaseImpl implements WindowInsetsCompatImpl {
53        @Override
54        public int getSystemWindowInsetLeft(Object insets) {
55            return 0;
56        }
57
58        @Override
59        public int getSystemWindowInsetTop(Object insets) {
60            return 0;
61        }
62
63        @Override
64        public int getSystemWindowInsetRight(Object insets) {
65            return 0;
66        }
67
68        @Override
69        public int getSystemWindowInsetBottom(Object insets) {
70            return 0;
71        }
72
73        @Override
74        public boolean hasSystemWindowInsets(Object insets) {
75            return false;
76        }
77
78        @Override
79        public boolean hasInsets(Object insets) {
80            return false;
81        }
82
83        @Override
84        public boolean isConsumed(Object insets) {
85            return false;
86        }
87
88        @Override
89        public boolean isRound(Object insets) {
90            return false;
91        }
92
93        @Override
94        public WindowInsetsCompat consumeSystemWindowInsets(Object insets) {
95            return null;
96        }
97
98        @Override
99        public WindowInsetsCompat replaceSystemWindowInsets(Object insets, int left, int top, int right, int bottom) {
100            return null;
101        }
102
103        @Override
104        public WindowInsetsCompat replaceSystemWindowInsets(Object insets, Rect systemWindowInsets) {
105            return null;
106        }
107
108        @Override
109        public int getStableInsetTop(Object insets) {
110            return 0;
111        }
112
113        @Override
114        public int getStableInsetLeft(Object insets) {
115            return 0;
116        }
117
118        @Override
119        public int getStableInsetRight(Object insets) {
120            return 0;
121        }
122
123        @Override
124        public int getStableInsetBottom(Object insets) {
125            return 0;
126        }
127
128        @Override
129        public boolean hasStableInsets(Object insets) {
130            return false;
131        }
132
133        @Override
134        public WindowInsetsCompat consumeStableInsets(Object insets) {
135            return null;
136        }
137
138        @Override
139        public Object getSourceWindowInsets(Object src) {
140            return null;
141        }
142    }
143
144    private static class WindowInsetsCompatApi20Impl extends WindowInsetsCompatBaseImpl {
145        @Override
146        public WindowInsetsCompat consumeSystemWindowInsets(Object insets) {
147            return new WindowInsetsCompat(
148                    WindowInsetsCompatApi20.consumeSystemWindowInsets(insets));
149        }
150
151        @Override
152        public int getSystemWindowInsetBottom(Object insets) {
153            return WindowInsetsCompatApi20.getSystemWindowInsetBottom(insets);
154        }
155
156        @Override
157        public int getSystemWindowInsetLeft(Object insets) {
158            return WindowInsetsCompatApi20.getSystemWindowInsetLeft(insets);
159        }
160
161        @Override
162        public int getSystemWindowInsetRight(Object insets) {
163            return WindowInsetsCompatApi20.getSystemWindowInsetRight(insets);
164        }
165
166        @Override
167        public int getSystemWindowInsetTop(Object insets) {
168            return WindowInsetsCompatApi20.getSystemWindowInsetTop(insets);
169        }
170
171        @Override
172        public boolean hasInsets(Object insets) {
173            return WindowInsetsCompatApi20.hasInsets(insets);
174        }
175
176        @Override
177        public boolean hasSystemWindowInsets(Object insets) {
178            return WindowInsetsCompatApi20.hasSystemWindowInsets(insets);
179        }
180
181        @Override
182        public boolean isRound(Object insets) {
183            return WindowInsetsCompatApi20.isRound(insets);
184        }
185
186        @Override
187        public WindowInsetsCompat replaceSystemWindowInsets(Object insets, int left, int top,
188                int right, int bottom) {
189            return new WindowInsetsCompat(WindowInsetsCompatApi20.replaceSystemWindowInsets(insets,
190                    left, top, right, bottom));
191        }
192
193        @Override
194        public Object getSourceWindowInsets(Object src) {
195            return WindowInsetsCompatApi20.getSourceWindowInsets(src);
196        }
197    }
198
199    private static class WindowInsetsCompatApi21Impl extends WindowInsetsCompatApi20Impl {
200        @Override
201        public WindowInsetsCompat consumeStableInsets(Object insets) {
202            return new WindowInsetsCompat(WindowInsetsCompatApi21.consumeStableInsets(insets));
203        }
204
205        @Override
206        public int getStableInsetBottom(Object insets) {
207            return WindowInsetsCompatApi21.getStableInsetBottom(insets);
208        }
209
210        @Override
211        public int getStableInsetLeft(Object insets) {
212            return WindowInsetsCompatApi21.getStableInsetLeft(insets);
213        }
214
215        @Override
216        public int getStableInsetRight(Object insets) {
217            return WindowInsetsCompatApi21.getStableInsetRight(insets);
218        }
219
220        @Override
221        public int getStableInsetTop(Object insets) {
222            return WindowInsetsCompatApi21.getStableInsetTop(insets);
223        }
224
225        @Override
226        public boolean hasStableInsets(Object insets) {
227            return WindowInsetsCompatApi21.hasStableInsets(insets);
228        }
229
230        @Override
231        public boolean isConsumed(Object insets) {
232            return WindowInsetsCompatApi21.isConsumed(insets);
233        }
234
235        @Override
236        public WindowInsetsCompat replaceSystemWindowInsets(Object insets,
237                Rect systemWindowInsets) {
238            return new WindowInsetsCompat(WindowInsetsCompatApi21.replaceSystemWindowInsets(insets,
239                    systemWindowInsets));
240        }
241    }
242
243    private static final WindowInsetsCompatImpl IMPL;
244    static {
245        final int version = Build.VERSION.SDK_INT;
246        if (version >= 21) {
247            IMPL = new WindowInsetsCompatApi21Impl();
248        } else if (version >= 20) {
249            IMPL = new WindowInsetsCompatApi20Impl();
250        } else {
251            IMPL = new WindowInsetsCompatBaseImpl();
252        }
253    }
254
255    private final Object mInsets;
256
257    private WindowInsetsCompat(Object insets) {
258        mInsets = insets;
259    }
260
261    /**
262     * Constructs a new WindowInsetsCompat, copying all values from a source WindowInsetsCompat.
263     *
264     * @param src source from which values are copied
265     */
266    public WindowInsetsCompat(WindowInsetsCompat src) {
267        mInsets = src == null ? null : IMPL.getSourceWindowInsets(src.mInsets);
268    }
269
270    /**
271     * Returns the left system window inset in pixels.
272     *
273     * <p>The system window inset represents the area of a full-screen window that is
274     * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
275     * </p>
276     *
277     * @return The left system window inset
278     */
279    public int getSystemWindowInsetLeft() {
280        return IMPL.getSystemWindowInsetLeft(mInsets);
281    }
282
283    /**
284     * Returns the top system window inset in pixels.
285     *
286     * <p>The system window inset represents the area of a full-screen window that is
287     * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
288     * </p>
289     *
290     * @return The top system window inset
291     */
292    public int getSystemWindowInsetTop() {
293        return IMPL.getSystemWindowInsetTop(mInsets);
294    }
295
296    /**
297     * Returns the right system window inset in pixels.
298     *
299     * <p>The system window inset represents the area of a full-screen window that is
300     * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
301     * </p>
302     *
303     * @return The right system window inset
304     */
305    public int getSystemWindowInsetRight() {
306        return IMPL.getSystemWindowInsetRight(mInsets);
307    }
308
309    /**
310     * Returns the bottom system window inset in pixels.
311     *
312     * <p>The system window inset represents the area of a full-screen window that is
313     * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
314     * </p>
315     *
316     * @return The bottom system window inset
317     */
318    public int getSystemWindowInsetBottom() {
319        return IMPL.getSystemWindowInsetBottom(mInsets);
320    }
321
322    /**
323     * Returns true if this WindowInsets has nonzero system window insets.
324     *
325     * <p>The system window inset represents the area of a full-screen window that is
326     * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
327     * </p>
328     *
329     * @return true if any of the system window inset values are nonzero
330     */
331    public boolean hasSystemWindowInsets() {
332        return IMPL.hasSystemWindowInsets(mInsets);
333    }
334
335    /**
336     * Returns true if this WindowInsets has any nonzero insets.
337     *
338     * @return true if any inset values are nonzero
339     */
340    public boolean hasInsets() {
341        return IMPL.hasInsets(mInsets);
342    }
343
344    /**
345     * Check if these insets have been fully consumed.
346     *
347     * <p>Insets are considered "consumed" if the applicable <code>consume*</code> methods
348     * have been called such that all insets have been set to zero. This affects propagation of
349     * insets through the view hierarchy; insets that have not been fully consumed will continue
350     * to propagate down to child views.</p>
351     *
352     * <p>The result of this method is equivalent to the return value of
353     * {@link android.view.View#fitSystemWindows(android.graphics.Rect)}.</p>
354     *
355     * @return true if the insets have been fully consumed.
356     */
357    public boolean isConsumed() {
358        return IMPL.isConsumed(mInsets);
359    }
360
361    /**
362     * Returns true if the associated window has a round shape.
363     *
364     * <p>A round window's left, top, right and bottom edges reach all the way to the
365     * associated edges of the window but the corners may not be visible. Views responding
366     * to round insets should take care to not lay out critical elements within the corners
367     * where they may not be accessible.</p>
368     *
369     * @return True if the window is round
370     */
371    public boolean isRound() {
372        return IMPL.isRound(mInsets);
373    }
374
375    /**
376     * Returns a copy of this WindowInsets with the system window insets fully consumed.
377     *
378     * @return A modified copy of this WindowInsets
379     */
380    public WindowInsetsCompat consumeSystemWindowInsets() {
381        return IMPL.consumeSystemWindowInsets(mInsets);
382    }
383
384    /**
385     * Returns a copy of this WindowInsets with selected system window insets replaced
386     * with new values.
387     *
388     * @param left New left inset in pixels
389     * @param top New top inset in pixels
390     * @param right New right inset in pixels
391     * @param bottom New bottom inset in pixels
392     * @return A modified copy of this WindowInsets
393     */
394    public WindowInsetsCompat replaceSystemWindowInsets(int left, int top, int right, int bottom) {
395        return IMPL.replaceSystemWindowInsets(mInsets, left, top, right, bottom);
396    }
397
398    /**
399     * Returns a copy of this WindowInsets with selected system window insets replaced
400     * with new values.
401     *
402     * @param systemWindowInsets New system window insets. Each field is the inset in pixels
403     *                           for that edge
404     * @return A modified copy of this WindowInsets
405     */
406    public WindowInsetsCompat replaceSystemWindowInsets(Rect systemWindowInsets) {
407        return IMPL.replaceSystemWindowInsets(mInsets, systemWindowInsets);
408    }
409
410    /**
411     * Returns the top 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 top stable inset
420     */
421    public int getStableInsetTop() {
422        return IMPL.getStableInsetTop(mInsets);
423    }
424
425
426    /**
427     * Returns the left stable inset in pixels.
428     *
429     * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
430     * partially or fully obscured by the system UI elements.  This value does not change
431     * based on the visibility state of those elements; for example, if the status bar is
432     * normally shown, but temporarily hidden, the stable inset will still provide the inset
433     * associated with the status bar being shown.</p>
434     *
435     * @return The left stable inset
436     */
437    public int getStableInsetLeft() {
438        return IMPL.getStableInsetLeft(mInsets);
439    }
440
441    /**
442     * Returns the right stable inset in pixels.
443     *
444     * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
445     * partially or fully obscured by the system UI elements.  This value does not change
446     * based on the visibility state of those elements; for example, if the status bar is
447     * normally shown, but temporarily hidden, the stable inset will still provide the inset
448     * associated with the status bar being shown.</p>
449     *
450     * @return The right stable inset
451     */
452    public int getStableInsetRight() {
453        return IMPL.getStableInsetRight(mInsets);
454    }
455
456
457    /**
458     * Returns the bottom stable inset in pixels.
459     *
460     * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
461     * partially or fully obscured by the system UI elements.  This value does not change
462     * based on the visibility state of those elements; for example, if the status bar is
463     * normally shown, but temporarily hidden, the stable inset will still provide the inset
464     * associated with the status bar being shown.</p>
465     *
466     * @return The bottom stable inset
467     */
468    public int getStableInsetBottom() {
469        return IMPL.getStableInsetBottom(mInsets);
470    }
471
472    /**
473     * Returns true if this WindowInsets has nonzero stable insets.
474     *
475     * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
476     * partially or fully obscured by the system UI elements.  This value does not change
477     * based on the visibility state of those elements; for example, if the status bar is
478     * normally shown, but temporarily hidden, the stable inset will still provide the inset
479     * associated with the status bar being shown.</p>
480     *
481     * @return true if any of the stable inset values are nonzero
482     */
483    public boolean hasStableInsets() {
484        return IMPL.hasStableInsets(mInsets);
485    }
486
487    /**
488     * Returns a copy of this WindowInsets with the stable insets fully consumed.
489     *
490     * @return A modified copy of this WindowInsetsCompat
491     */
492    public WindowInsetsCompat consumeStableInsets() {
493        return IMPL.consumeStableInsets(mInsets);
494    }
495
496    @Override
497    public boolean equals(Object o) {
498        if (this == o) {
499            return true;
500        }
501        if (o == null || getClass() != o.getClass()) {
502            return false;
503        }
504        WindowInsetsCompat other = (WindowInsetsCompat) o;
505        return mInsets == null ? other.mInsets == null : mInsets.equals(other.mInsets);
506    }
507
508    @Override
509    public int hashCode() {
510        return mInsets == null ? 0 : mInsets.hashCode();
511    }
512
513    static WindowInsetsCompat wrap(Object insets) {
514        return insets == null ? null : new WindowInsetsCompat(insets);
515    }
516
517    static Object unwrap(WindowInsetsCompat insets) {
518        return insets == null ? null : insets.mInsets;
519    }
520}
521