// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. package org.chromium.content.browser; import android.view.View; import android.view.ViewTreeObserver; import java.util.ArrayList; /** * Used to register listeners that can be notified of changes to the position of a view. */ public class ViewPositionObserver implements PositionObserver { private View mView; // Absolute position of the container view relative to its parent window. private final int[] mPosition = new int[2]; private final ArrayList<Listener> mListeners; private ViewTreeObserver.OnPreDrawListener mPreDrawListener; /** * @param view The view to observe. */ public ViewPositionObserver(View view) { mView = view; mListeners = new ArrayList<Listener>(); updatePosition(); mPreDrawListener = new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { updatePosition(); return true; } }; } /** * @return The current x position of the observed view. */ @Override public int getPositionX() { // The stored position may be out-of-date. Get the real current position. updatePosition(); return mPosition[0]; } /** * @return The current y position of the observed view. */ @Override public int getPositionY() { // The stored position may be out-of-date. Get the real current position. updatePosition(); return mPosition[1]; } /** * Register a listener to be called when the position of the underlying view changes. */ @Override public void addListener(Listener listener) { if (mListeners.contains(listener)) return; if (mListeners.isEmpty()) { mView.getViewTreeObserver().addOnPreDrawListener(mPreDrawListener); updatePosition(); } mListeners.add(listener); } /** * Remove a previously installed listener. */ @Override public void removeListener(Listener listener) { if (!mListeners.contains(listener)) return; mListeners.remove(listener); if (mListeners.isEmpty()) { mView.getViewTreeObserver().removeOnPreDrawListener(mPreDrawListener); } } private void notifyListeners() { for (int i = 0; i < mListeners.size(); i++) { mListeners.get(i).onPositionChanged(mPosition[0], mPosition[1]); } } private void updatePosition() { int previousPositionX = mPosition[0]; int previousPositionY = mPosition[1]; mView.getLocationInWindow(mPosition); if (mPosition[0] != previousPositionX || mPosition[1] != previousPositionY) { notifyListeners(); } } }