19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.view;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect;
20fbf097732137a32930d151f7ba6816a5b870c32aJeff Brownimport android.graphics.Region;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
226e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haaseimport java.util.ArrayList;
230f8ffd83745f718a476564f35a2f7fd4637275bcChet Haaseimport java.util.concurrent.CopyOnWriteArrayList;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A view tree observer is used to register listeners that can be notified of global
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * changes in the view tree. Such global events include, but are not limited to,
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * layout of the whole tree, beginning of the drawing pass, touch mode change....
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A ViewTreeObserver should never be instantiated by applications as it is provided
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * by the views hierarchy. Refer to {@link android.view.View#getViewTreeObserver()}
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for more information.
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic final class ViewTreeObserver {
35c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    // Recursive listeners use CopyOnWriteArrayList
36961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    private CopyOnWriteArrayList<OnWindowFocusChangeListener> mOnWindowFocusListeners;
37961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    private CopyOnWriteArrayList<OnWindowAttachListener> mOnWindowAttachListeners;
380f8ffd83745f718a476564f35a2f7fd4637275bcChet Haase    private CopyOnWriteArrayList<OnGlobalFocusChangeListener> mOnGlobalFocusListeners;
390f8ffd83745f718a476564f35a2f7fd4637275bcChet Haase    private CopyOnWriteArrayList<OnTouchModeChangeListener> mOnTouchModeChangeListeners;
40c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
41c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    // Non-recursive listeners use CopyOnWriteArray
42c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    // Any listener invoked from ViewRootImpl.performTraversals() should not be recursive
43c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    private CopyOnWriteArray<OnGlobalLayoutListener> mOnGlobalLayoutListeners;
44c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    private CopyOnWriteArray<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners;
45c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    private CopyOnWriteArray<OnScrollChangedListener> mOnScrollChangedListeners;
46c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    private CopyOnWriteArray<OnPreDrawListener> mOnPreDrawListeners;
47c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
48c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    // These listeners cannot be mutated during dispatch
4925eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    private ArrayList<OnDrawListener> mOnDrawListeners;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mAlive = true;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
54961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     * Interface definition for a callback to be invoked when the view hierarchy is
55961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     * attached to and detached from its window.
56961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     */
57961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    public interface OnWindowAttachListener {
58961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        /**
59961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn         * Callback method to be invoked when the view hierarchy is attached to a window
60961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn         */
61961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        public void onWindowAttached();
62961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn
63961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        /**
64961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn         * Callback method to be invoked when the view hierarchy is detached from a window
65961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn         */
66961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        public void onWindowDetached();
67961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    }
68961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn
69961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    /**
70961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     * Interface definition for a callback to be invoked when the view hierarchy's window
71961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     * focus state changes.
72961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     */
73961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    public interface OnWindowFocusChangeListener {
74961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        /**
75961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn         * Callback method to be invoked when the window focus changes in the view tree.
76961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn         *
77961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn         * @param hasFocus Set to true if the window is gaining focus, false if it is
78961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn         * losing focus.
79961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn         */
80961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        public void onWindowFocusChanged(boolean hasFocus);
81961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    }
82961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn
83961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    /**
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Interface definition for a callback to be invoked when the focus state within
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the view tree changes.
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface OnGlobalFocusChangeListener {
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Callback method to be invoked when the focus changes in the view tree. When
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the view tree transitions from touch mode to non-touch mode, oldFocus is null.
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * When the view tree transitions from non-touch mode to touch mode, newFocus is
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * null. When focus changes in non-touch mode (without transition from or to
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * touch mode) either oldFocus or newFocus can be null.
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param oldFocus The previously focused view, if any.
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param newFocus The newly focused View, if any.
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onGlobalFocusChanged(View oldFocus, View newFocus);
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Interface definition for a callback to be invoked when the global layout state
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or the visibility of views within the view tree changes.
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface OnGlobalLayoutListener {
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Callback method to be invoked when the global layout state or the visibility of views
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * within the view tree changes
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onGlobalLayout();
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Interface definition for a callback to be invoked when the view tree is about to be drawn.
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface OnPreDrawListener {
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Callback method to be invoked when the view tree is about to be drawn. At this point, all
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * views in the tree have been measured and given a frame. Clients can use this to adjust
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * their scroll bounds or even to request a new layout before drawing occurs.
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @return Return true to proceed with the current drawing pass, or false to cancel.
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @see android.view.View#onMeasure
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @see android.view.View#onLayout
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @see android.view.View#onDraw
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean onPreDraw();
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * Interface definition for a callback to be invoked when the view tree is about to be drawn.
13325eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     */
13425eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    public interface OnDrawListener {
13525eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        /**
13625eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         * <p>Callback method to be invoked when the view tree is about to be drawn. At this point,
13725eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         * views cannot be modified in any way.</p>
13825eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         *
13925eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         * <p>Unlike with {@link OnPreDrawListener}, this method cannot be used to cancel the
14025eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         * current drawing pass.</p>
14125eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         *
14225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         * <p>An {@link OnDrawListener} listener <strong>cannot be added or removed</strong>
14325eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         * from this method.</p>
14425eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         *
14525eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         * @see android.view.View#onMeasure
14625eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         * @see android.view.View#onLayout
14725eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         * @see android.view.View#onDraw
14825eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy         */
14925eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        public void onDraw();
15025eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    }
15125eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
15225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    /**
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Interface definition for a callback to be invoked when the touch mode changes.
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface OnTouchModeChangeListener {
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Callback method to be invoked when the touch mode changes.
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param isInTouchMode True if the view hierarchy is now in touch mode, false  otherwise.
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onTouchModeChanged(boolean isInTouchMode);
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Interface definition for a callback to be invoked when
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * something in the view tree has been scrolled.
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface OnScrollChangedListener {
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Callback method to be invoked when something in the view tree
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * has been scrolled.
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onScrollChanged();
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Parameters used with OnComputeInternalInsetsListener.
178935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     *
179935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     * We are not yet ready to commit to this API and support it, so
180935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     * @hide
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final static class InternalInsetsInfo {
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Offsets from the frame of the window at which the content of
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * windows behind it should be placed.
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final Rect contentInsets = new Rect();
188c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
190fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * Offsets from the frame of the window at which windows behind it
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * are visible.
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public final Rect visibleInsets = new Rect();
194fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown
195fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        /**
196fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * Touchable region defined relative to the origin of the frame of the window.
197fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * Only used when {@link #setTouchableInsets(int)} is called with
198fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * the option {@link #TOUCHABLE_INSETS_REGION}.
199fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         */
200fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        public final Region touchableRegion = new Region();
201fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Option for {@link #setTouchableInsets(int)}: the entire window frame
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * can be touched.
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static final int TOUCHABLE_INSETS_FRAME = 0;
207c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Option for {@link #setTouchableInsets(int)}: the area inside of
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the content insets can be touched.
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static final int TOUCHABLE_INSETS_CONTENT = 1;
213c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Option for {@link #setTouchableInsets(int)}: the area inside of
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the visible insets can be touched.
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public static final int TOUCHABLE_INSETS_VISIBLE = 2;
219fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown
220fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        /**
221fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * Option for {@link #setTouchableInsets(int)}: the area inside of
222fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * the provided touchable region in {@link #touchableRegion} can be touched.
223fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         */
224fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown        public static final int TOUCHABLE_INSETS_REGION = 3;
225fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Set which parts of the window can be touched: either
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * {@link #TOUCHABLE_INSETS_FRAME}, {@link #TOUCHABLE_INSETS_CONTENT},
229fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown         * {@link #TOUCHABLE_INSETS_VISIBLE}, or {@link #TOUCHABLE_INSETS_REGION}.
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void setTouchableInsets(int val) {
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTouchableInsets = val;
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23425eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int mTouchableInsets;
236c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void reset() {
238fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown            contentInsets.setEmpty();
239fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown            visibleInsets.setEmpty();
240fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown            touchableRegion.setEmpty();
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTouchableInsets = TOUCHABLE_INSETS_FRAME;
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
24325eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
2442e05ec3235150a93a3459cd260be45f02dadbe84Jeff Brown        boolean isEmpty() {
2452e05ec3235150a93a3459cd260be45f02dadbe84Jeff Brown            return contentInsets.isEmpty()
2462e05ec3235150a93a3459cd260be45f02dadbe84Jeff Brown                    && visibleInsets.isEmpty()
2472e05ec3235150a93a3459cd260be45f02dadbe84Jeff Brown                    && touchableRegion.isEmpty()
2482e05ec3235150a93a3459cd260be45f02dadbe84Jeff Brown                    && mTouchableInsets == TOUCHABLE_INSETS_FRAME;
2492e05ec3235150a93a3459cd260be45f02dadbe84Jeff Brown        }
2502e05ec3235150a93a3459cd260be45f02dadbe84Jeff Brown
25125eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        @Override
25225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        public int hashCode() {
25321f4230274f858bf156441374f0bae84e7334d7aRomain Guy            int result = contentInsets.hashCode();
25421f4230274f858bf156441374f0bae84e7334d7aRomain Guy            result = 31 * result + visibleInsets.hashCode();
25521f4230274f858bf156441374f0bae84e7334d7aRomain Guy            result = 31 * result + touchableRegion.hashCode();
25625eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            result = 31 * result + mTouchableInsets;
25725eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            return result;
25825eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        }
25925eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
2601e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy        @Override
2611e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy        public boolean equals(Object o) {
26225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            if (this == o) return true;
26325eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            if (o == null || getClass() != o.getClass()) return false;
26425eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
26525eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            InternalInsetsInfo other = (InternalInsetsInfo)o;
26625eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            return mTouchableInsets == other.mTouchableInsets &&
26725eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy                    contentInsets.equals(other.contentInsets) &&
26825eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy                    visibleInsets.equals(other.visibleInsets) &&
26925eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy                    touchableRegion.equals(other.touchableRegion);
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
27125eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        void set(InternalInsetsInfo other) {
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            contentInsets.set(other.contentInsets);
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            visibleInsets.set(other.visibleInsets);
275fbf097732137a32930d151f7ba6816a5b870c32aJeff Brown            touchableRegion.set(other.touchableRegion);
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTouchableInsets = other.mTouchableInsets;
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
279c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Interface definition for a callback to be invoked when layout has
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * completed and the client can compute its interior insets.
283935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     *
284935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     * We are not yet ready to commit to this API and support it, so
285935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     * @hide
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface OnComputeInternalInsetsListener {
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Callback method to be invoked when layout has completed and the
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * client can compute its interior insets.
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param inoutInfo Should be filled in by the implementation with
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * the information about the insets of the window.  This is called
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * with whatever values the previous OnComputeInternalInsetsListener
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * returned, if there are multiple such listeners in the window.
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onComputeInternalInsets(InternalInsetsInfo inoutInfo);
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Creates a new ViewTreeObserver. This constructor should not be called
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ViewTreeObserver() {
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Merges all the listeners registered on the specified observer with the listeners
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * registered on this object. After this method is invoked, the specified observer
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * will return false in {@link #isAlive()} and should not be used anymore.
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param observer The ViewTreeObserver whose listeners must be added to this observer
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void merge(ViewTreeObserver observer) {
314961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        if (observer.mOnWindowAttachListeners != null) {
315961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn            if (mOnWindowAttachListeners != null) {
316961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn                mOnWindowAttachListeners.addAll(observer.mOnWindowAttachListeners);
317961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn            } else {
318961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn                mOnWindowAttachListeners = observer.mOnWindowAttachListeners;
319961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn            }
320961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        }
321961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn
322961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        if (observer.mOnWindowFocusListeners != null) {
323961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn            if (mOnWindowFocusListeners != null) {
324961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn                mOnWindowFocusListeners.addAll(observer.mOnWindowFocusListeners);
325961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn            } else {
326961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn                mOnWindowFocusListeners = observer.mOnWindowFocusListeners;
327961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn            }
328961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        }
329961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (observer.mOnGlobalFocusListeners != null) {
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mOnGlobalFocusListeners != null) {
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOnGlobalFocusListeners.addAll(observer.mOnGlobalFocusListeners);
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOnGlobalFocusListeners = observer.mOnGlobalFocusListeners;
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (observer.mOnGlobalLayoutListeners != null) {
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mOnGlobalLayoutListeners != null) {
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOnGlobalLayoutListeners.addAll(observer.mOnGlobalLayoutListeners);
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOnGlobalLayoutListeners = observer.mOnGlobalLayoutListeners;
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (observer.mOnPreDrawListeners != null) {
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mOnPreDrawListeners != null) {
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOnPreDrawListeners.addAll(observer.mOnPreDrawListeners);
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOnPreDrawListeners = observer.mOnPreDrawListeners;
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (observer.mOnTouchModeChangeListeners != null) {
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mOnTouchModeChangeListeners != null) {
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOnTouchModeChangeListeners.addAll(observer.mOnTouchModeChangeListeners);
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOnTouchModeChangeListeners = observer.mOnTouchModeChangeListeners;
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (observer.mOnComputeInternalInsetsListeners != null) {
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mOnComputeInternalInsetsListeners != null) {
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOnComputeInternalInsetsListeners.addAll(observer.mOnComputeInternalInsetsListeners);
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mOnComputeInternalInsetsListeners = observer.mOnComputeInternalInsetsListeners;
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
370757c697f73561ef4cfae9e3da64e9b2894d24147Mark Brophy        if (observer.mOnScrollChangedListeners != null) {
371757c697f73561ef4cfae9e3da64e9b2894d24147Mark Brophy            if (mOnScrollChangedListeners != null) {
372757c697f73561ef4cfae9e3da64e9b2894d24147Mark Brophy                mOnScrollChangedListeners.addAll(observer.mOnScrollChangedListeners);
373757c697f73561ef4cfae9e3da64e9b2894d24147Mark Brophy            } else {
374757c697f73561ef4cfae9e3da64e9b2894d24147Mark Brophy                mOnScrollChangedListeners = observer.mOnScrollChangedListeners;
375757c697f73561ef4cfae9e3da64e9b2894d24147Mark Brophy            }
376757c697f73561ef4cfae9e3da64e9b2894d24147Mark Brophy        }
377757c697f73561ef4cfae9e3da64e9b2894d24147Mark Brophy
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        observer.kill();
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
382961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     * Register a callback to be invoked when the view hierarchy is attached to a window.
383961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     *
384961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     * @param listener The callback to add
385961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     *
386961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     * @throws IllegalStateException If {@link #isAlive()} returns false
387961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     */
388961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    public void addOnWindowAttachListener(OnWindowAttachListener listener) {
389961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        checkIsAlive();
390961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn
391961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        if (mOnWindowAttachListeners == null) {
392961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn            mOnWindowAttachListeners
393961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn                    = new CopyOnWriteArrayList<OnWindowAttachListener>();
394961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        }
395961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn
396961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        mOnWindowAttachListeners.add(listener);
397961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    }
398961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn
399961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    /**
400961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     * Remove a previously installed window attach callback.
401961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     *
402961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     * @param victim The callback to remove
403961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     *
404961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     * @throws IllegalStateException If {@link #isAlive()} returns false
405961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     *
406961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     * @see #addOnWindowAttachListener(android.view.ViewTreeObserver.OnWindowAttachListener)
407961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     */
408961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    public void removeOnWindowAttachListener(OnWindowAttachListener victim) {
409961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        checkIsAlive();
410961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        if (mOnWindowAttachListeners == null) {
411961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn            return;
412961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        }
413961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        mOnWindowAttachListeners.remove(victim);
414961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    }
415961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn
416961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    /**
417961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     * Register a callback to be invoked when the window focus state within the view tree changes.
418961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     *
419961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     * @param listener The callback to add
420961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     *
421961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     * @throws IllegalStateException If {@link #isAlive()} returns false
422961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     */
423961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    public void addOnWindowFocusChangeListener(OnWindowFocusChangeListener listener) {
424961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        checkIsAlive();
425961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn
426961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        if (mOnWindowFocusListeners == null) {
427961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn            mOnWindowFocusListeners
428961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn                    = new CopyOnWriteArrayList<OnWindowFocusChangeListener>();
429961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        }
430961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn
431961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        mOnWindowFocusListeners.add(listener);
432961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    }
433961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn
434961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    /**
435961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     * Remove a previously installed window focus change callback.
436961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     *
437961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     * @param victim The callback to remove
438961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     *
439961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     * @throws IllegalStateException If {@link #isAlive()} returns false
440961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     *
441961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     * @see #addOnWindowFocusChangeListener(android.view.ViewTreeObserver.OnWindowFocusChangeListener)
442961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     */
443961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    public void removeOnWindowFocusChangeListener(OnWindowFocusChangeListener victim) {
444961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        checkIsAlive();
445961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        if (mOnWindowFocusListeners == null) {
446961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn            return;
447961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        }
448961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        mOnWindowFocusListeners.remove(victim);
449961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    }
450961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn
451961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    /**
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Register a callback to be invoked when the focus state within the view tree changes.
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener The callback to add
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addOnGlobalFocusChangeListener(OnGlobalFocusChangeListener listener) {
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnGlobalFocusListeners == null) {
4620f8ffd83745f718a476564f35a2f7fd4637275bcChet Haase            mOnGlobalFocusListeners = new CopyOnWriteArrayList<OnGlobalFocusChangeListener>();
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnGlobalFocusListeners.add(listener);
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove a previously installed focus change callback.
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param victim The callback to remove
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #addOnGlobalFocusChangeListener(OnGlobalFocusChangeListener)
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeOnGlobalFocusChangeListener(OnGlobalFocusChangeListener victim) {
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnGlobalFocusListeners == null) {
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnGlobalFocusListeners.remove(victim);
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Register a callback to be invoked when the global layout state or the visibility of views
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * within the view tree changes
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener The callback to add
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addOnGlobalLayoutListener(OnGlobalLayoutListener listener) {
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnGlobalLayoutListeners == null) {
497c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            mOnGlobalLayoutListeners = new CopyOnWriteArray<OnGlobalLayoutListener>();
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnGlobalLayoutListeners.add(listener);
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove a previously installed global layout callback
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param victim The callback to remove
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
5091e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy     *
5101e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy     * @deprecated Use #removeOnGlobalLayoutListener instead
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #addOnGlobalLayoutListener(OnGlobalLayoutListener)
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5141e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy    @Deprecated
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeGlobalOnLayoutListener(OnGlobalLayoutListener victim) {
5161e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy        removeOnGlobalLayoutListener(victim);
5171e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy    }
5181e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy
5191e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy    /**
5201e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy     * Remove a previously installed global layout callback
5211e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy     *
5221e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy     * @param victim The callback to remove
5231e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy     *
5241e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy     * @throws IllegalStateException If {@link #isAlive()} returns false
5251e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy     *
5261e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy     * @see #addOnGlobalLayoutListener(OnGlobalLayoutListener)
5271e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy     */
5281e878d2ff506e7e96bbdb9d06afea43561445b7aRomain Guy    public void removeOnGlobalLayoutListener(OnGlobalLayoutListener victim) {
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnGlobalLayoutListeners == null) {
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnGlobalLayoutListeners.remove(victim);
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Register a callback to be invoked when the view tree is about to be drawn
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener The callback to add
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addOnPreDrawListener(OnPreDrawListener listener) {
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnPreDrawListeners == null) {
547c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            mOnPreDrawListeners = new CopyOnWriteArray<OnPreDrawListener>();
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnPreDrawListeners.add(listener);
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove a previously installed pre-draw callback
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param victim The callback to remove
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #addOnPreDrawListener(OnPreDrawListener)
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeOnPreDrawListener(OnPreDrawListener victim) {
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnPreDrawListeners == null) {
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnPreDrawListeners.remove(victim);
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
57125eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * <p>Register a callback to be invoked when the view tree is about to be drawn.</p>
57225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * <p><strong>Note:</strong> this method <strong>cannot</strong> be invoked from
57325eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * {@link android.view.ViewTreeObserver.OnDrawListener#onDraw()}.</p>
57425eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     *
57525eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * @param listener The callback to add
57625eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     *
57725eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * @throws IllegalStateException If {@link #isAlive()} returns false
57825eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     */
57925eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    public void addOnDrawListener(OnDrawListener listener) {
58025eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        checkIsAlive();
58125eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
58225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        if (mOnDrawListeners == null) {
58325eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            mOnDrawListeners = new ArrayList<OnDrawListener>();
58425eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        }
58525eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
58625eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        mOnDrawListeners.add(listener);
58725eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    }
58825eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
58925eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    /**
59025eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * <p>Remove a previously installed pre-draw callback.</p>
59125eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * <p><strong>Note:</strong> this method <strong>cannot</strong> be invoked from
59225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * {@link android.view.ViewTreeObserver.OnDrawListener#onDraw()}.</p>
59325eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     *
59425eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * @param victim The callback to remove
59525eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     *
59625eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * @throws IllegalStateException If {@link #isAlive()} returns false
59725eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     *
59825eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * @see #addOnDrawListener(OnDrawListener)
59925eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     */
60025eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    public void removeOnDrawListener(OnDrawListener victim) {
60125eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        checkIsAlive();
60225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        if (mOnDrawListeners == null) {
60325eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            return;
60425eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        }
60525eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        mOnDrawListeners.remove(victim);
60625eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    }
60725eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
60825eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    /**
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Register a callback to be invoked when a view has been scrolled.
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener The callback to add
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addOnScrollChangedListener(OnScrollChangedListener listener) {
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnScrollChangedListeners == null) {
619c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            mOnScrollChangedListeners = new CopyOnWriteArray<OnScrollChangedListener>();
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnScrollChangedListeners.add(listener);
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove a previously installed scroll-changed callback
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param victim The callback to remove
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #addOnScrollChangedListener(OnScrollChangedListener)
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeOnScrollChangedListener(OnScrollChangedListener victim) {
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnScrollChangedListeners == null) {
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnScrollChangedListeners.remove(victim);
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Register a callback to be invoked when the invoked when the touch mode changes.
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener The callback to add
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addOnTouchModeChangeListener(OnTouchModeChangeListener listener) {
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnTouchModeChangeListeners == null) {
6530f8ffd83745f718a476564f35a2f7fd4637275bcChet Haase            mOnTouchModeChangeListeners = new CopyOnWriteArrayList<OnTouchModeChangeListener>();
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnTouchModeChangeListeners.add(listener);
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove a previously installed touch mode change callback
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param victim The callback to remove
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #addOnTouchModeChangeListener(OnTouchModeChangeListener)
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeOnTouchModeChangeListener(OnTouchModeChangeListener victim) {
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnTouchModeChangeListeners == null) {
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnTouchModeChangeListeners.remove(victim);
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Register a callback to be invoked when the invoked when it is time to
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * compute the window's internal insets.
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param listener The callback to add
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
683935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     *
684935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     * We are not yet ready to commit to this API and support it, so
685935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     * @hide
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addOnComputeInternalInsetsListener(OnComputeInternalInsetsListener listener) {
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnComputeInternalInsetsListeners == null) {
691105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mOnComputeInternalInsetsListeners =
692c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                    new CopyOnWriteArray<OnComputeInternalInsetsListener>();
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnComputeInternalInsetsListeners.add(listener);
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove a previously installed internal insets computation callback
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param victim The callback to remove
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException If {@link #isAlive()} returns false
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #addOnComputeInternalInsetsListener(OnComputeInternalInsetsListener)
706935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     *
707935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     * We are not yet ready to commit to this API and support it, so
708935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn     * @hide
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeOnComputeInternalInsetsListener(OnComputeInternalInsetsListener victim) {
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkIsAlive();
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mOnComputeInternalInsetsListeners == null) {
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnComputeInternalInsetsListeners.remove(victim);
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void checkIsAlive() {
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mAlive) {
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("This ViewTreeObserver is not alive, call "
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + "getViewTreeObserver() again");
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Indicates whether this ViewTreeObserver is alive. When an observer is not alive,
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * any call to a method (except this one) will throw an exception.
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If an application keeps a long-lived reference to this ViewTreeObserver, it should
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * always check for the result of this method before calling any other method.
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return True if this object is alive and be used, false otherwise.
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isAlive() {
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAlive;
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Marks this ViewTreeObserver as not alive. After invoking this method, invoking
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * any other method but {@link #isAlive()} and {@link #kill()} will throw an Exception.
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void kill() {
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAlive = false;
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
749961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     * Notifies registered listeners that window has been attached/detached.
750961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     */
751961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    final void dispatchOnWindowAttachedChange(boolean attached) {
752961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
753961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        // perform the dispatching. The iterator is a safe guard against listeners that
754961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        // could mutate the list by calling the various add/remove methods. This prevents
755961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        // the array from being modified while we iterate it.
756961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        final CopyOnWriteArrayList<OnWindowAttachListener> listeners
757961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn                = mOnWindowAttachListeners;
758961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        if (listeners != null && listeners.size() > 0) {
759961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn            for (OnWindowAttachListener listener : listeners) {
760961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn                if (attached) listener.onWindowAttached();
761961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn                else listener.onWindowDetached();
762961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn            }
763961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        }
764961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    }
765961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn
766961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    /**
767961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     * Notifies registered listeners that window focus has changed.
768961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn     */
769961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    final void dispatchOnWindowFocusChange(boolean hasFocus) {
770961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
771961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        // perform the dispatching. The iterator is a safe guard against listeners that
772961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        // could mutate the list by calling the various add/remove methods. This prevents
773961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        // the array from being modified while we iterate it.
774961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        final CopyOnWriteArrayList<OnWindowFocusChangeListener> listeners
775961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn                = mOnWindowFocusListeners;
776961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        if (listeners != null && listeners.size() > 0) {
777961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn            for (OnWindowFocusChangeListener listener : listeners) {
778961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn                listener.onWindowFocusChanged(hasFocus);
779961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn            }
780961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn        }
781961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    }
782961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn
783961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn    /**
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Notifies registered listeners that focus has changed.
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final void dispatchOnGlobalFocusChange(View oldFocus, View newFocus) {
787105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
788105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // perform the dispatching. The iterator is a safe guard against listeners that
789105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // could mutate the list by calling the various add/remove methods. This prevents
790105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // the array from being modified while we iterate it.
7910f8ffd83745f718a476564f35a2f7fd4637275bcChet Haase        final CopyOnWriteArrayList<OnGlobalFocusChangeListener> listeners = mOnGlobalFocusListeners;
7926e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase        if (listeners != null && listeners.size() > 0) {
7930f8ffd83745f718a476564f35a2f7fd4637275bcChet Haase            for (OnGlobalFocusChangeListener listener : listeners) {
7940f8ffd83745f718a476564f35a2f7fd4637275bcChet Haase                listener.onGlobalFocusChanged(oldFocus, newFocus);
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Notifies registered listeners that a global layout happened. This can be called
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * manually if you are forcing a layout on a View or a hierarchy of Views that are
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * not attached to a Window or in the GONE state.
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final void dispatchOnGlobalLayout() {
805105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
806105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // perform the dispatching. The iterator is a safe guard against listeners that
807105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // could mutate the list by calling the various add/remove methods. This prevents
808105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // the array from being modified while we iterate it.
809c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        final CopyOnWriteArray<OnGlobalLayoutListener> listeners = mOnGlobalLayoutListeners;
8106e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase        if (listeners != null && listeners.size() > 0) {
811c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            CopyOnWriteArray.Access<OnGlobalLayoutListener> access = listeners.start();
812c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            try {
813c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                int count = access.size();
814c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                for (int i = 0; i < count; i++) {
815c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                    access.get(i).onGlobalLayout();
816c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                }
817c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            } finally {
818c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                listeners.end();
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
82421f4230274f858bf156441374f0bae84e7334d7aRomain Guy     * Returns whether there are listeners for on pre-draw events.
82521f4230274f858bf156441374f0bae84e7334d7aRomain Guy     */
82621f4230274f858bf156441374f0bae84e7334d7aRomain Guy    final boolean hasOnPreDrawListeners() {
82721f4230274f858bf156441374f0bae84e7334d7aRomain Guy        return mOnPreDrawListeners != null && mOnPreDrawListeners.size() > 0;
82821f4230274f858bf156441374f0bae84e7334d7aRomain Guy    }
82921f4230274f858bf156441374f0bae84e7334d7aRomain Guy
83021f4230274f858bf156441374f0bae84e7334d7aRomain Guy    /**
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Notifies registered listeners that the drawing pass is about to start. If a
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * listener returns true, then the drawing pass is canceled and rescheduled. This can
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be called manually if you are forcing the drawing on a View or a hierarchy of Views
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that are not attached to a Window or in the GONE state.
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return True if the current draw should be canceled and resceduled, false otherwise.
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
83825eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    @SuppressWarnings("unchecked")
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final boolean dispatchOnPreDraw() {
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean cancelDraw = false;
841c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        final CopyOnWriteArray<OnPreDrawListener> listeners = mOnPreDrawListeners;
842c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        if (listeners != null && listeners.size() > 0) {
843c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            CopyOnWriteArray.Access<OnPreDrawListener> access = listeners.start();
844c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            try {
845c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                int count = access.size();
846c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                for (int i = 0; i < count; i++) {
847c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                    cancelDraw |= !(access.get(i).onPreDraw());
848c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                }
849c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            } finally {
850c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                listeners.end();
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return cancelDraw;
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
85725eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     * Notifies registered listeners that the drawing pass is about to start.
85825eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy     */
85925eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    public final void dispatchOnDraw() {
86025eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        if (mOnDrawListeners != null) {
86125eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            final ArrayList<OnDrawListener> listeners = mOnDrawListeners;
86225eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            int numListeners = listeners.size();
86325eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            for (int i = 0; i < numListeners; ++i) {
86425eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy                listeners.get(i).onDraw();
86525eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy            }
86625eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy        }
86725eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    }
86825eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy
86925eba5c5029bd91ff7e396b2cca0e4ce024124edRomain Guy    /**
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Notifies registered listeners that the touch mode has changed.
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param inTouchMode True if the touch mode is now enabled, false otherwise.
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final void dispatchOnTouchModeChanged(boolean inTouchMode) {
8750f8ffd83745f718a476564f35a2f7fd4637275bcChet Haase        final CopyOnWriteArrayList<OnTouchModeChangeListener> listeners =
876105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mOnTouchModeChangeListeners;
8776e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase        if (listeners != null && listeners.size() > 0) {
8780f8ffd83745f718a476564f35a2f7fd4637275bcChet Haase            for (OnTouchModeChangeListener listener : listeners) {
8790f8ffd83745f718a476564f35a2f7fd4637275bcChet Haase                listener.onTouchModeChanged(inTouchMode);
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Notifies registered listeners that something has scrolled.
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final void dispatchOnScrollChanged() {
888105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
889105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // perform the dispatching. The iterator is a safe guard against listeners that
890105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // could mutate the list by calling the various add/remove methods. This prevents
891105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // the array from being modified while we iterate it.
892c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        final CopyOnWriteArray<OnScrollChangedListener> listeners = mOnScrollChangedListeners;
8936e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase        if (listeners != null && listeners.size() > 0) {
894c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            CopyOnWriteArray.Access<OnScrollChangedListener> access = listeners.start();
895c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            try {
896c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                int count = access.size();
897c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                for (int i = 0; i < count; i++) {
898c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                    access.get(i).onScrollChanged();
899c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                }
900c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            } finally {
901c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                listeners.end();
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns whether there are listeners for computing internal insets.
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final boolean hasComputeInternalInsetsListeners() {
910c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        final CopyOnWriteArray<OnComputeInternalInsetsListener> listeners =
911105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mOnComputeInternalInsetsListeners;
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (listeners != null && listeners.size() > 0);
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
914c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Calls all listeners to compute the current insets.
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final void dispatchOnComputeInternalInsets(InternalInsetsInfo inoutInfo) {
919105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
920105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // perform the dispatching. The iterator is a safe guard against listeners that
921105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // could mutate the list by calling the various add/remove methods. This prevents
922105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        // the array from being modified while we iterate it.
923c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        final CopyOnWriteArray<OnComputeInternalInsetsListener> listeners =
924105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mOnComputeInternalInsetsListeners;
9256e0ecb4eed5cd2e1f15766d7028467129974a12dChet Haase        if (listeners != null && listeners.size() > 0) {
926c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            CopyOnWriteArray.Access<OnComputeInternalInsetsListener> access = listeners.start();
927c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            try {
928c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                int count = access.size();
929c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                for (int i = 0; i < count; i++) {
930c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                    access.get(i).onComputeInternalInsets(inoutInfo);
931c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                }
932c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            } finally {
933c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                listeners.end();
934c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            }
935c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        }
936c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    }
937c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
938c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    /**
939c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     * Copy on write array. This array is not thread safe, and only one loop can
940c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     * iterate over this array at any given time. This class avoids allocations
941c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     * until a concurrent modification happens.
942c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     *
943c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     * Usage:
944c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     *
945c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     * CopyOnWriteArray.Access<MyData> access = array.start();
946c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     * try {
947c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     *     for (int i = 0; i < access.size(); i++) {
948c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     *         MyData d = access.get(i);
949c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     *     }
950c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     * } finally {
951c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     *     access.end();
952c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     * }
953c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy     */
954c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy    static class CopyOnWriteArray<T> {
955c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        private ArrayList<T> mData = new ArrayList<T>();
956c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        private ArrayList<T> mDataCopy;
957c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
958c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        private final Access<T> mAccess = new Access<T>();
959c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
960c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        private boolean mStart;
961c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
962c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        static class Access<T> {
963c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            private ArrayList<T> mData;
964c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            private int mSize;
965c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
966c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            T get(int index) {
967c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                return mData.get(index);
968c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            }
969c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
970c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            int size() {
971c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                return mSize;
972c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            }
973c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        }
974c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
975c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        CopyOnWriteArray() {
976c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        }
977c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
978c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        private ArrayList<T> getArray() {
979c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            if (mStart) {
980c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                if (mDataCopy == null) mDataCopy = new ArrayList<T>(mData);
981c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                return mDataCopy;
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
983c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            return mData;
984c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        }
985c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
986c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        Access<T> start() {
987c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            if (mStart) throw new IllegalStateException("Iteration already started");
988c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            mStart = true;
989c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            mDataCopy = null;
990c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            mAccess.mData = mData;
991c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            mAccess.mSize = mData.size();
992c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            return mAccess;
993c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        }
994c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
995c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        void end() {
996c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            if (!mStart) throw new IllegalStateException("Iteration not started");
997c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            mStart = false;
998c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            if (mDataCopy != null) {
999c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy                mData = mDataCopy;
1000fc343967c8310a425d2df2aefd01fbe60bf3ef3aChet Haase                mAccess.mData.clear();
1001fc343967c8310a425d2df2aefd01fbe60bf3ef3aChet Haase                mAccess.mSize = 0;
1002c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            }
1003c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            mDataCopy = null;
1004c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        }
1005c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
1006c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        int size() {
1007c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            return getArray().size();
1008c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        }
1009c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
1010c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        void add(T item) {
1011c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            getArray().add(item);
1012c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        }
1013c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
1014c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        void addAll(CopyOnWriteArray<T> array) {
1015c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            getArray().addAll(array.mData);
1016c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        }
1017c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
1018c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        void remove(T item) {
1019c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            getArray().remove(item);
1020c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        }
1021c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy
1022c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy        void clear() {
1023c39ed4a6e54f5b11a2eb07e9aeb58597bd8c78edRomain Guy            getArray().clear();
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1027