blob: 4230afad7993c9610456d0edf84e10c33fc83255 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import android.graphics.Rect;
20
The Android Open Source Project10592532009-03-18 17:39:46 -070021import java.util.concurrent.CopyOnWriteArrayList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022
23/**
24 * A view tree observer is used to register listeners that can be notified of global
25 * changes in the view tree. Such global events include, but are not limited to,
26 * layout of the whole tree, beginning of the drawing pass, touch mode change....
27 *
28 * A ViewTreeObserver should never be instantiated by applications as it is provided
29 * by the views hierarchy. Refer to {@link android.view.View#getViewTreeObserver()}
30 * for more information.
31 */
32public final class ViewTreeObserver {
The Android Open Source Project10592532009-03-18 17:39:46 -070033 private CopyOnWriteArrayList<OnGlobalFocusChangeListener> mOnGlobalFocusListeners;
34 private CopyOnWriteArrayList<OnGlobalLayoutListener> mOnGlobalLayoutListeners;
35 private CopyOnWriteArrayList<OnPreDrawListener> mOnPreDrawListeners;
36 private CopyOnWriteArrayList<OnTouchModeChangeListener> mOnTouchModeChangeListeners;
37 private CopyOnWriteArrayList<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners;
38 private CopyOnWriteArrayList<OnScrollChangedListener> mOnScrollChangedListeners;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039
40 private boolean mAlive = true;
41
42 /**
43 * Interface definition for a callback to be invoked when the focus state within
44 * the view tree changes.
45 */
46 public interface OnGlobalFocusChangeListener {
47 /**
48 * Callback method to be invoked when the focus changes in the view tree. When
49 * the view tree transitions from touch mode to non-touch mode, oldFocus is null.
50 * When the view tree transitions from non-touch mode to touch mode, newFocus is
51 * null. When focus changes in non-touch mode (without transition from or to
52 * touch mode) either oldFocus or newFocus can be null.
53 *
54 * @param oldFocus The previously focused view, if any.
55 * @param newFocus The newly focused View, if any.
56 */
57 public void onGlobalFocusChanged(View oldFocus, View newFocus);
58 }
59
60 /**
61 * Interface definition for a callback to be invoked when the global layout state
62 * or the visibility of views within the view tree changes.
63 */
64 public interface OnGlobalLayoutListener {
65 /**
66 * Callback method to be invoked when the global layout state or the visibility of views
67 * within the view tree changes
68 */
69 public void onGlobalLayout();
70 }
71
72 /**
73 * Interface definition for a callback to be invoked when the view tree is about to be drawn.
74 */
75 public interface OnPreDrawListener {
76 /**
77 * Callback method to be invoked when the view tree is about to be drawn. At this point, all
78 * views in the tree have been measured and given a frame. Clients can use this to adjust
79 * their scroll bounds or even to request a new layout before drawing occurs.
80 *
81 * @return Return true to proceed with the current drawing pass, or false to cancel.
82 *
83 * @see android.view.View#onMeasure
84 * @see android.view.View#onLayout
85 * @see android.view.View#onDraw
86 */
87 public boolean onPreDraw();
88 }
89
90 /**
91 * Interface definition for a callback to be invoked when the touch mode changes.
92 */
93 public interface OnTouchModeChangeListener {
94 /**
95 * Callback method to be invoked when the touch mode changes.
96 *
97 * @param isInTouchMode True if the view hierarchy is now in touch mode, false otherwise.
98 */
99 public void onTouchModeChanged(boolean isInTouchMode);
100 }
101
102 /**
103 * Interface definition for a callback to be invoked when
104 * something in the view tree has been scrolled.
105 *
106 * @hide pending API council approval
107 */
108 public interface OnScrollChangedListener {
109 /**
110 * Callback method to be invoked when something in the view tree
111 * has been scrolled.
112 */
113 public void onScrollChanged();
114 }
115
116 /**
117 * Parameters used with OnComputeInternalInsetsListener.
118 * {@hide pending API Council approval}
119 */
120 public final static class InternalInsetsInfo {
121 /**
122 * Offsets from the frame of the window at which the content of
123 * windows behind it should be placed.
124 */
125 public final Rect contentInsets = new Rect();
126
127 /**
128 * Offsets from the fram of the window at which windows behind it
129 * are visible.
130 */
131 public final Rect visibleInsets = new Rect();
132
133 /**
134 * Option for {@link #setTouchableInsets(int)}: the entire window frame
135 * can be touched.
136 */
137 public static final int TOUCHABLE_INSETS_FRAME = 0;
138
139 /**
140 * Option for {@link #setTouchableInsets(int)}: the area inside of
141 * the content insets can be touched.
142 */
143 public static final int TOUCHABLE_INSETS_CONTENT = 1;
144
145 /**
146 * Option for {@link #setTouchableInsets(int)}: the area inside of
147 * the visible insets can be touched.
148 */
149 public static final int TOUCHABLE_INSETS_VISIBLE = 2;
150
151 /**
152 * Set which parts of the window can be touched: either
153 * {@link #TOUCHABLE_INSETS_FRAME}, {@link #TOUCHABLE_INSETS_CONTENT},
154 * or {@link #TOUCHABLE_INSETS_VISIBLE}.
155 */
156 public void setTouchableInsets(int val) {
157 mTouchableInsets = val;
158 }
159
160 public int getTouchableInsets() {
161 return mTouchableInsets;
162 }
163
164 int mTouchableInsets;
165
166 void reset() {
167 final Rect givenContent = contentInsets;
168 final Rect givenVisible = visibleInsets;
169 givenContent.left = givenContent.top = givenContent.right
170 = givenContent.bottom = givenVisible.left = givenVisible.top
171 = givenVisible.right = givenVisible.bottom = 0;
172 mTouchableInsets = TOUCHABLE_INSETS_FRAME;
173 }
174
175 @Override public boolean equals(Object o) {
176 try {
177 if (o == null) {
178 return false;
179 }
180 InternalInsetsInfo other = (InternalInsetsInfo)o;
181 if (!contentInsets.equals(other.contentInsets)) {
182 return false;
183 }
184 if (!visibleInsets.equals(other.visibleInsets)) {
185 return false;
186 }
187 return mTouchableInsets == other.mTouchableInsets;
188 } catch (ClassCastException e) {
189 return false;
190 }
191 }
192
193 void set(InternalInsetsInfo other) {
194 contentInsets.set(other.contentInsets);
195 visibleInsets.set(other.visibleInsets);
196 mTouchableInsets = other.mTouchableInsets;
197 }
198 }
199
200 /**
201 * Interface definition for a callback to be invoked when layout has
202 * completed and the client can compute its interior insets.
203 * {@hide pending API Council approval}
204 */
205 public interface OnComputeInternalInsetsListener {
206 /**
207 * Callback method to be invoked when layout has completed and the
208 * client can compute its interior insets.
209 *
210 * @param inoutInfo Should be filled in by the implementation with
211 * the information about the insets of the window. This is called
212 * with whatever values the previous OnComputeInternalInsetsListener
213 * returned, if there are multiple such listeners in the window.
214 */
215 public void onComputeInternalInsets(InternalInsetsInfo inoutInfo);
216 }
217
218 /**
219 * Creates a new ViewTreeObserver. This constructor should not be called
220 */
221 ViewTreeObserver() {
222 }
223
224 /**
225 * Merges all the listeners registered on the specified observer with the listeners
226 * registered on this object. After this method is invoked, the specified observer
227 * will return false in {@link #isAlive()} and should not be used anymore.
228 *
229 * @param observer The ViewTreeObserver whose listeners must be added to this observer
230 */
231 void merge(ViewTreeObserver observer) {
232 if (observer.mOnGlobalFocusListeners != null) {
233 if (mOnGlobalFocusListeners != null) {
234 mOnGlobalFocusListeners.addAll(observer.mOnGlobalFocusListeners);
235 } else {
236 mOnGlobalFocusListeners = observer.mOnGlobalFocusListeners;
237 }
238 }
239
240 if (observer.mOnGlobalLayoutListeners != null) {
241 if (mOnGlobalLayoutListeners != null) {
242 mOnGlobalLayoutListeners.addAll(observer.mOnGlobalLayoutListeners);
243 } else {
244 mOnGlobalLayoutListeners = observer.mOnGlobalLayoutListeners;
245 }
246 }
247
248 if (observer.mOnPreDrawListeners != null) {
249 if (mOnPreDrawListeners != null) {
250 mOnPreDrawListeners.addAll(observer.mOnPreDrawListeners);
251 } else {
252 mOnPreDrawListeners = observer.mOnPreDrawListeners;
253 }
254 }
255
256 if (observer.mOnTouchModeChangeListeners != null) {
257 if (mOnTouchModeChangeListeners != null) {
258 mOnTouchModeChangeListeners.addAll(observer.mOnTouchModeChangeListeners);
259 } else {
260 mOnTouchModeChangeListeners = observer.mOnTouchModeChangeListeners;
261 }
262 }
263
264 if (observer.mOnComputeInternalInsetsListeners != null) {
265 if (mOnComputeInternalInsetsListeners != null) {
266 mOnComputeInternalInsetsListeners.addAll(observer.mOnComputeInternalInsetsListeners);
267 } else {
268 mOnComputeInternalInsetsListeners = observer.mOnComputeInternalInsetsListeners;
269 }
270 }
271
272 observer.kill();
273 }
274
275 /**
276 * Register a callback to be invoked when the focus state within the view tree changes.
277 *
278 * @param listener The callback to add
279 *
280 * @throws IllegalStateException If {@link #isAlive()} returns false
281 */
282 public void addOnGlobalFocusChangeListener(OnGlobalFocusChangeListener listener) {
283 checkIsAlive();
284
285 if (mOnGlobalFocusListeners == null) {
The Android Open Source Project10592532009-03-18 17:39:46 -0700286 mOnGlobalFocusListeners = new CopyOnWriteArrayList<OnGlobalFocusChangeListener>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287 }
288
289 mOnGlobalFocusListeners.add(listener);
290 }
291
292 /**
293 * Remove a previously installed focus change callback.
294 *
295 * @param victim The callback to remove
296 *
297 * @throws IllegalStateException If {@link #isAlive()} returns false
298 *
299 * @see #addOnGlobalFocusChangeListener(OnGlobalFocusChangeListener)
300 */
301 public void removeOnGlobalFocusChangeListener(OnGlobalFocusChangeListener victim) {
302 checkIsAlive();
303 if (mOnGlobalFocusListeners == null) {
304 return;
305 }
306 mOnGlobalFocusListeners.remove(victim);
307 }
308
309 /**
310 * Register a callback to be invoked when the global layout state or the visibility of views
311 * within the view tree changes
312 *
313 * @param listener The callback to add
314 *
315 * @throws IllegalStateException If {@link #isAlive()} returns false
316 */
317 public void addOnGlobalLayoutListener(OnGlobalLayoutListener listener) {
318 checkIsAlive();
319
320 if (mOnGlobalLayoutListeners == null) {
The Android Open Source Project10592532009-03-18 17:39:46 -0700321 mOnGlobalLayoutListeners = new CopyOnWriteArrayList<OnGlobalLayoutListener>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800322 }
323
324 mOnGlobalLayoutListeners.add(listener);
325 }
326
327 /**
328 * Remove a previously installed global layout callback
329 *
330 * @param victim The callback to remove
331 *
332 * @throws IllegalStateException If {@link #isAlive()} returns false
333 *
334 * @see #addOnGlobalLayoutListener(OnGlobalLayoutListener)
335 */
336 public void removeGlobalOnLayoutListener(OnGlobalLayoutListener victim) {
337 checkIsAlive();
338 if (mOnGlobalLayoutListeners == null) {
339 return;
340 }
341 mOnGlobalLayoutListeners.remove(victim);
342 }
343
344 /**
345 * Register a callback to be invoked when the view tree is about to be drawn
346 *
347 * @param listener The callback to add
348 *
349 * @throws IllegalStateException If {@link #isAlive()} returns false
350 */
351 public void addOnPreDrawListener(OnPreDrawListener listener) {
352 checkIsAlive();
353
354 if (mOnPreDrawListeners == null) {
The Android Open Source Project10592532009-03-18 17:39:46 -0700355 mOnPreDrawListeners = new CopyOnWriteArrayList<OnPreDrawListener>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356 }
357
358 mOnPreDrawListeners.add(listener);
359 }
360
361 /**
362 * Remove a previously installed pre-draw callback
363 *
364 * @param victim The callback to remove
365 *
366 * @throws IllegalStateException If {@link #isAlive()} returns false
367 *
368 * @see #addOnPreDrawListener(OnPreDrawListener)
369 */
370 public void removeOnPreDrawListener(OnPreDrawListener victim) {
371 checkIsAlive();
372 if (mOnPreDrawListeners == null) {
373 return;
374 }
375 mOnPreDrawListeners.remove(victim);
376 }
377
378 /**
379 * Register a callback to be invoked when a view has been scrolled.
380 *
381 * @param listener The callback to add
382 *
383 * @throws IllegalStateException If {@link #isAlive()} returns false
384 *
385 * @hide pending API council approval
386 */
387 public void addOnScrollChangedListener(OnScrollChangedListener listener) {
388 checkIsAlive();
389
390 if (mOnScrollChangedListeners == null) {
The Android Open Source Project10592532009-03-18 17:39:46 -0700391 mOnScrollChangedListeners = new CopyOnWriteArrayList<OnScrollChangedListener>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 }
393
394 mOnScrollChangedListeners.add(listener);
395 }
396
397 /**
398 * Remove a previously installed scroll-changed callback
399 *
400 * @param victim The callback to remove
401 *
402 * @throws IllegalStateException If {@link #isAlive()} returns false
403 *
404 * @see #addOnScrollChangedListener(OnScrollChangedListener)
405 *
406 * @hide pending API council approval
407 */
408 public void removeOnScrollChangedListener(OnScrollChangedListener victim) {
409 checkIsAlive();
410 if (mOnScrollChangedListeners == null) {
411 return;
412 }
413 mOnScrollChangedListeners.remove(victim);
414 }
415
416 /**
417 * Register a callback to be invoked when the invoked when the touch mode changes.
418 *
419 * @param listener The callback to add
420 *
421 * @throws IllegalStateException If {@link #isAlive()} returns false
422 */
423 public void addOnTouchModeChangeListener(OnTouchModeChangeListener listener) {
424 checkIsAlive();
425
426 if (mOnTouchModeChangeListeners == null) {
The Android Open Source Project10592532009-03-18 17:39:46 -0700427 mOnTouchModeChangeListeners = new CopyOnWriteArrayList<OnTouchModeChangeListener>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 }
429
430 mOnTouchModeChangeListeners.add(listener);
431 }
432
433 /**
434 * Remove a previously installed touch mode change callback
435 *
436 * @param victim The callback to remove
437 *
438 * @throws IllegalStateException If {@link #isAlive()} returns false
439 *
440 * @see #addOnTouchModeChangeListener(OnTouchModeChangeListener)
441 */
442 public void removeOnTouchModeChangeListener(OnTouchModeChangeListener victim) {
443 checkIsAlive();
444 if (mOnTouchModeChangeListeners == null) {
445 return;
446 }
447 mOnTouchModeChangeListeners.remove(victim);
448 }
449
450 /**
451 * Register a callback to be invoked when the invoked when it is time to
452 * compute the window's internal insets.
453 *
454 * @param listener The callback to add
455 *
456 * @throws IllegalStateException If {@link #isAlive()} returns false
457 * {@hide pending API Council approval}
458 */
459 public void addOnComputeInternalInsetsListener(OnComputeInternalInsetsListener listener) {
460 checkIsAlive();
461
462 if (mOnComputeInternalInsetsListeners == null) {
The Android Open Source Project10592532009-03-18 17:39:46 -0700463 mOnComputeInternalInsetsListeners =
464 new CopyOnWriteArrayList<OnComputeInternalInsetsListener>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800465 }
466
467 mOnComputeInternalInsetsListeners.add(listener);
468 }
469
470 /**
471 * Remove a previously installed internal insets computation callback
472 *
473 * @param victim The callback to remove
474 *
475 * @throws IllegalStateException If {@link #isAlive()} returns false
476 *
477 * @see #addOnComputeInternalInsetsListener(OnComputeInternalInsetsListener)
478 * {@hide pending API Council approval}
479 */
480 public void removeOnComputeInternalInsetsListener(OnComputeInternalInsetsListener victim) {
481 checkIsAlive();
482 if (mOnComputeInternalInsetsListeners == null) {
483 return;
484 }
485 mOnComputeInternalInsetsListeners.remove(victim);
486 }
487
488 private void checkIsAlive() {
489 if (!mAlive) {
490 throw new IllegalStateException("This ViewTreeObserver is not alive, call "
491 + "getViewTreeObserver() again");
492 }
493 }
494
495 /**
496 * Indicates whether this ViewTreeObserver is alive. When an observer is not alive,
497 * any call to a method (except this one) will throw an exception.
498 *
499 * If an application keeps a long-lived reference to this ViewTreeObserver, it should
500 * always check for the result of this method before calling any other method.
501 *
502 * @return True if this object is alive and be used, false otherwise.
503 */
504 public boolean isAlive() {
505 return mAlive;
506 }
507
508 /**
509 * Marks this ViewTreeObserver as not alive. After invoking this method, invoking
510 * any other method but {@link #isAlive()} and {@link #kill()} will throw an Exception.
511 *
512 * @hide
513 */
514 private void kill() {
515 mAlive = false;
516 }
517
518 /**
519 * Notifies registered listeners that focus has changed.
520 */
521 final void dispatchOnGlobalFocusChange(View oldFocus, View newFocus) {
The Android Open Source Project10592532009-03-18 17:39:46 -0700522 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
523 // perform the dispatching. The iterator is a safe guard against listeners that
524 // could mutate the list by calling the various add/remove methods. This prevents
525 // the array from being modified while we iterate it.
526 final CopyOnWriteArrayList<OnGlobalFocusChangeListener> listeners = mOnGlobalFocusListeners;
527 if (listeners != null) {
528 for (OnGlobalFocusChangeListener listener : listeners) {
529 listener.onGlobalFocusChanged(oldFocus, newFocus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800530 }
531 }
532 }
533
534 /**
535 * Notifies registered listeners that a global layout happened. This can be called
536 * manually if you are forcing a layout on a View or a hierarchy of Views that are
537 * not attached to a Window or in the GONE state.
538 */
539 public final void dispatchOnGlobalLayout() {
The Android Open Source Project10592532009-03-18 17:39:46 -0700540 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
541 // perform the dispatching. The iterator is a safe guard against listeners that
542 // could mutate the list by calling the various add/remove methods. This prevents
543 // the array from being modified while we iterate it.
544 final CopyOnWriteArrayList<OnGlobalLayoutListener> listeners = mOnGlobalLayoutListeners;
545 if (listeners != null) {
546 for (OnGlobalLayoutListener listener : listeners) {
547 listener.onGlobalLayout();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800548 }
549 }
550 }
551
552 /**
553 * Notifies registered listeners that the drawing pass is about to start. If a
554 * listener returns true, then the drawing pass is canceled and rescheduled. This can
555 * be called manually if you are forcing the drawing on a View or a hierarchy of Views
556 * that are not attached to a Window or in the GONE state.
557 *
558 * @return True if the current draw should be canceled and resceduled, false otherwise.
559 */
560 public final boolean dispatchOnPreDraw() {
The Android Open Source Project10592532009-03-18 17:39:46 -0700561 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
562 // perform the dispatching. The iterator is a safe guard against listeners that
563 // could mutate the list by calling the various add/remove methods. This prevents
564 // the array from being modified while we iterate it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800565 boolean cancelDraw = false;
The Android Open Source Project10592532009-03-18 17:39:46 -0700566 final CopyOnWriteArrayList<OnPreDrawListener> listeners = mOnPreDrawListeners;
567 if (listeners != null) {
568 for (OnPreDrawListener listener : listeners) {
569 cancelDraw |= !listener.onPreDraw();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570 }
571 }
572 return cancelDraw;
573 }
574
575 /**
576 * Notifies registered listeners that the touch mode has changed.
577 *
578 * @param inTouchMode True if the touch mode is now enabled, false otherwise.
579 */
580 final void dispatchOnTouchModeChanged(boolean inTouchMode) {
The Android Open Source Project10592532009-03-18 17:39:46 -0700581 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
582 // perform the dispatching. The iterator is a safe guard against listeners that
583 // could mutate the list by calling the various add/remove methods. This prevents
584 // the array from being modified while we iterate it.
585 final CopyOnWriteArrayList<OnTouchModeChangeListener> listeners =
586 mOnTouchModeChangeListeners;
587 if (listeners != null) {
588 for (OnTouchModeChangeListener listener : listeners) {
589 listener.onTouchModeChanged(inTouchMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800590 }
591 }
592 }
593
594 /**
595 * Notifies registered listeners that something has scrolled.
596 */
597 final void dispatchOnScrollChanged() {
The Android Open Source Project10592532009-03-18 17:39:46 -0700598 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
599 // perform the dispatching. The iterator is a safe guard against listeners that
600 // could mutate the list by calling the various add/remove methods. This prevents
601 // the array from being modified while we iterate it.
602 final CopyOnWriteArrayList<OnScrollChangedListener> listeners = mOnScrollChangedListeners;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800603 if (listeners != null) {
The Android Open Source Project10592532009-03-18 17:39:46 -0700604 for (OnScrollChangedListener listener : listeners) {
605 listener.onScrollChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800606 }
607 }
608 }
609
610 /**
611 * Returns whether there are listeners for computing internal insets.
612 */
613 final boolean hasComputeInternalInsetsListeners() {
The Android Open Source Project10592532009-03-18 17:39:46 -0700614 final CopyOnWriteArrayList<OnComputeInternalInsetsListener> listeners =
615 mOnComputeInternalInsetsListeners;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616 return (listeners != null && listeners.size() > 0);
617 }
618
619 /**
620 * Calls all listeners to compute the current insets.
621 */
622 final void dispatchOnComputeInternalInsets(InternalInsetsInfo inoutInfo) {
The Android Open Source Project10592532009-03-18 17:39:46 -0700623 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
624 // perform the dispatching. The iterator is a safe guard against listeners that
625 // could mutate the list by calling the various add/remove methods. This prevents
626 // the array from being modified while we iterate it.
627 final CopyOnWriteArrayList<OnComputeInternalInsetsListener> listeners =
628 mOnComputeInternalInsetsListeners;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800629 if (listeners != null) {
The Android Open Source Project10592532009-03-18 17:39:46 -0700630 for (OnComputeInternalInsetsListener listener : listeners) {
631 listener.onComputeInternalInsets(inoutInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800632 }
633 }
634 }
635}