• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.content.browser;
6 
7 import android.view.View;
8 import android.view.ViewTreeObserver;
9 
10 import java.util.ArrayList;
11 
12 /**
13  * Used to register listeners that can be notified of changes to the position of a view.
14  */
15 public class ViewPositionObserver implements PositionObserver {
16     private View mView;
17     // Absolute position of the container view relative to its parent window.
18     private final int[] mPosition = new int[2];
19 
20     private final ArrayList<Listener> mListeners;
21     private ViewTreeObserver.OnPreDrawListener mPreDrawListener;
22 
23     /**
24      * @param view The view to observe.
25      */
ViewPositionObserver(View view)26     public ViewPositionObserver(View view) {
27         mView = view;
28         mListeners = new ArrayList<Listener>();
29         updatePosition();
30         mPreDrawListener = new ViewTreeObserver.OnPreDrawListener() {
31             @Override
32             public boolean onPreDraw() {
33                 updatePosition();
34                 return true;
35             }
36         };
37     }
38 
39     /**
40      * @return The current x position of the observed view.
41      */
42     @Override
getPositionX()43     public int getPositionX() {
44         // The stored position may be out-of-date. Get the real current position.
45         updatePosition();
46         return mPosition[0];
47     }
48 
49     /**
50      * @return The current y position of the observed view.
51      */
52     @Override
getPositionY()53     public int getPositionY() {
54         // The stored position may be out-of-date. Get the real current position.
55         updatePosition();
56         return mPosition[1];
57     }
58 
59     /**
60      * Register a listener to be called when the position of the underlying view changes.
61      */
62     @Override
addListener(Listener listener)63     public void addListener(Listener listener) {
64         if (mListeners.contains(listener)) return;
65 
66         if (mListeners.isEmpty()) {
67             mView.getViewTreeObserver().addOnPreDrawListener(mPreDrawListener);
68             updatePosition();
69         }
70 
71         mListeners.add(listener);
72     }
73 
74     /**
75      * Remove a previously installed listener.
76      */
77     @Override
removeListener(Listener listener)78     public void removeListener(Listener listener) {
79         if (!mListeners.contains(listener)) return;
80 
81         mListeners.remove(listener);
82 
83         if (mListeners.isEmpty()) {
84             mView.getViewTreeObserver().removeOnPreDrawListener(mPreDrawListener);
85         }
86     }
87 
notifyListeners()88     private void notifyListeners() {
89         for (int i = 0; i < mListeners.size(); i++) {
90             mListeners.get(i).onPositionChanged(mPosition[0], mPosition[1]);
91         }
92     }
93 
updatePosition()94     private void updatePosition() {
95         int previousPositionX = mPosition[0];
96         int previousPositionY = mPosition[1];
97         mView.getLocationInWindow(mPosition);
98         if (mPosition[0] != previousPositionX || mPosition[1] != previousPositionY) {
99             notifyListeners();
100         }
101     }
102 
103     /**
104      * Clears installed listener(s).
105      */
106     @Override
clearListener()107     public void clearListener() {
108         mListeners.clear();
109     }
110 }
111 
112