ViewPositionObserver.java revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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 5package org.chromium.content.browser; 6 7import android.view.View; 8import android.view.ViewTreeObserver; 9 10import java.util.ArrayList; 11 12/** 13 * Used to register listeners that can be notified of changes to the position of a view. 14 */ 15public 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 */ 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 public int getPositionX() { 43 // The stored position may be out-of-date. Get the real current position. 44 updatePosition(); 45 return mPosition[0]; 46 } 47 48 /** 49 * @return The current y position of the observed view. 50 */ 51 public int getPositionY() { 52 // The stored position may be out-of-date. Get the real current position. 53 updatePosition(); 54 return mPosition[1]; 55 } 56 57 /** 58 * Register a listener to be called when the position of the underlying view changes. 59 */ 60 public void addListener(Listener listener) { 61 if (mListeners.contains(listener)) return; 62 63 if (mListeners.isEmpty()) { 64 mView.getViewTreeObserver().addOnPreDrawListener(mPreDrawListener); 65 updatePosition(); 66 } 67 68 mListeners.add(listener); 69 } 70 71 /** 72 * Remove a previously installed listener. 73 */ 74 public void removeListener(Listener listener) { 75 if (!mListeners.contains(listener)) return; 76 77 mListeners.remove(listener); 78 79 if (mListeners.isEmpty()) { 80 mView.getViewTreeObserver().removeOnPreDrawListener(mPreDrawListener); 81 } 82 } 83 84 private void notifyListeners() { 85 for (int i = 0; i < mListeners.size(); i++) { 86 mListeners.get(i).onPositionChanged(mPosition[0], mPosition[1]); 87 } 88 } 89 90 private void updatePosition() { 91 int previousPositionX = mPosition[0]; 92 int previousPositionY = mPosition[1]; 93 mView.getLocationInWindow(mPosition); 94 if (mPosition[0] != previousPositionX || mPosition[1] != previousPositionY) { 95 notifyListeners(); 96 } 97 } 98} 99 100