title: Confusing with getGlobalVisibleRect, different values
body: <p>I'm try to zoom a FrameLayout with the following example from der android developers site: <a href="http://developer.android.com/training/animation/zoom.html" rel="nofollow">http://developer.android.com/training/animation/zoom.html</a></p>
  
  <p>My concrete Problem, in the first time the animation is right, is expand from the thumbView, in the second time the animation comes from 'somewhere' (middle/top to the center).</p>
  
  <p>i have nearly the same, the differents are, i have an Framelayout instead an ImageView and i extract the function to minimize the View back in an extra Method. now thats looks like so:</p>
  
  <pre><code>private void zoomImageFromThumb(final View thumbView) {
  
      if (mCurrentAnimator != null) {
          mCurrentAnimator.cancel();
      }
  
      // here i building my custome layout
  
      startBounds = new Rect();
      final Rect finalBounds = new Rect();
      final Point globalOffset = new Point();
  
      thumbView.getGlobalVisibleRect(startBounds);
      findViewById(R.id.container)
              .getGlobalVisibleRect(finalBounds, globalOffset);
      startBounds.offset(-globalOffset.x, -globalOffset.y);
      finalBounds.offset(-globalOffset.x + 15, -globalOffset.y + 60);
  
      float startScale;
      if ((float) finalBounds.width() / finalBounds.height()
              &gt; (float) startBounds.width() / startBounds.height()) {
  
          startScale = (float) startBounds.height() / finalBounds.height();
          float startWidth = startScale * finalBounds.width();
          float deltaWidth = (startWidth - startBounds.width()) / 2;
          startBounds.left -= deltaWidth;
          startBounds.right += deltaWidth;
      } else {
  
          startScale = (float) startBounds.width() / finalBounds.width();
          float startHeight = startScale * finalBounds.height();
          float deltaHeight = (startHeight - startBounds.height()) / 2;
          startBounds.top -= deltaHeight;
          startBounds.bottom += deltaHeight;
      }
  
      thumbView.setAlpha(0f);
      expandedImageView.setVisibility(View.VISIBLE);
  
      expandedImageView.setPivotX(0f);
      expandedImageView.setPivotY(0f);
  
      AnimatorSet set = new AnimatorSet();
      set
              .play(ObjectAnimator.ofFloat(expandedImageView, View.X,
                      startBounds.left, finalBounds.left))
              .with(ObjectAnimator.ofFloat(expandedImageView, View.Y,
                      startBounds.top, finalBounds.top))
              .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X,
              startScale, 1f)).with(ObjectAnimator.ofFloat(expandedImageView,
                      View.SCALE_Y, startScale, 1f));
      set.setDuration(mShortAnimationDuration);
      set.setInterpolator(new DecelerateInterpolator());
      set.addListener(new AnimatorListenerAdapter() {
          @Override
          public void onAnimationEnd(Animator animation) {
              mCurrentAnimator = null;
          }
  
          @Override
          public void onAnimationCancel(Animator animation) {
              mCurrentAnimator = null;
          }
      });
      set.start();
      mCurrentAnimator = set;
  }
  </code></pre>
  
  <p>the startBounds Variable is global, cause i need this to know where the position is for the minimize process. Here the minimize Method:</p>
  
  <pre><code>    private void minimizeViewFromThumb(final View thumbView) {
      if (mCurrentAnimator != null) {
                      mCurrentAnimator.cancel();
                  }
  
                  AnimatorSet set = new AnimatorSet();
                  set.play(ObjectAnimator
                              .ofFloat(expandedImageView, View.X, startBounds.left))
                              .with(ObjectAnimator
                                      .ofFloat(expandedImageView, 
                                              View.Y,startBounds.top))
                              .with(ObjectAnimator
                                      .ofFloat(expandedImageView, 
                                              View.SCALE_X, startScaleFinal))
                              .with(ObjectAnimator
                                      .ofFloat(expandedImageView, 
                                              View.SCALE_Y, startScaleFinal));
                  set.setDuration(mShortAnimationDuration);
                  set.setInterpolator(new DecelerateInterpolator());
                  set.addListener(new AnimatorListenerAdapter() {
                      @Override
                      public void onAnimationEnd(Animator animation) {
  
  
                  thumbView.setAlpha(1f);
                      expandedImageView.setVisibility(View.GONE);
                      mCurrentAnimator = null;
                  }
  
                  @Override
                  public void onAnimationCancel(Animator animation) {
                      thumbView.setAlpha(1f);
                      expandedImageView.setVisibility(View.GONE);
                      mCurrentAnimator = null;
                  }
              });
              set.start();
              mCurrentAnimator = set;
  }
  </code></pre>
  
  <p>if i debug this whole process i can see that the method getGlobalVisibleRect from the method zoomViewFromThumb give me another value.</p>
  
  <p>if i debug the line </p>
  
  <pre><code>finalBounds.offset(-globalOffset.x, -globalOffset.y);
  </code></pre>
  
  <p>in the first time the two parameters are 0 and -60 and in the second time (after minimize and recreate there are 15 and 360.</p>
  
  <p>i have no idea why thats happen.</p>
  
  <p>i have try to set the View.X and View.Y parameter append from the given thumbView, i have try to work with constant Values for the View.X, View.Y parameter in the ObjectAnimator but nothing fix my problem.</p>
  
  <p>now please help me.</p>
  
  <p>Greets Manu</p>
  
  <p><strong>1. EDIT:</strong> the fail is on Android Version 4.1.2 i have test it in the emulator with Android 4.0 and there it works fine</p>
  
  <p><strong>2. EDIT:</strong> Here are the xml files, the first one is the xml File that representing my main Activity (with the animation), the second one represent the TableLayout what i push in the FrameLayout of the main xml. (Please notice, currently I'm at work and i have no access to the original, now these xml files are good as far I can remember)</p>
  
  <p>the first</p>
  
  <pre><code>&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:id="@+id/relZoom"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical" &gt;
  
      &lt;FrameLayout
          android:id="@+id/frameZoomOne"
          android:layout_width="160dp"
          android:layout_height="215dp"
          android:layout_alignParentBottom="true"
          android:layout_alignParentLeft="true"
          android:layout_marginBottom="10dp"
          android:layout_marginLeft="10dp" &gt;
      &lt;/FrameLayout&gt;
  
      &lt;FrameLayout
          android:id="@+id/frameZoomTwo"
          android:layout_width="160dp"
          android:layout_height="215dp"
          android:layout_alignParentRight="true"
          android:layout_alignParentTop="true"
          android:layout_marginRight="10dp"
          android:layout_marginTop="10dp" &gt;
      &lt;/FrameLayout&gt;
  
      &lt;FrameLayout
          android:id="@+id/container"
          android:layout_width="300dp"
          android:layout_height="408dp"
          android:visibility="invisible" &gt;
      &lt;/FrameLayout&gt;
  
      &lt;FrameLayout
          android:id="@+id/containerTwo"
          android:layout_width="300dp"
          android:layout_height="408dp"
          android:visibility="invisible" &gt;
      &lt;/FrameLayout&gt;
  
  &lt;/RelativeLayout&gt;
  </code></pre>
  
  <p>the second</p>
  
  <pre><code>    &lt;?xml version="1.0" encoding="utf-8"?&gt;
      &lt;TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/tableLayout1"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent" &gt;
          &lt;TableRow
          android:id="@+id/tableRow1"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:padding="5dip" &gt;
  
          &lt;TextView
              android:id="@+id/textView1"
              android:text="Column 1"
              android:textAppearance="?android:attr/textAppearanceLarge" /&gt;
  
           &lt;TextView
              android:id="@+id/textView2"
              android:text="Column 2"
              android:textAppearance="?android:attr/textAppearanceLarge" /&gt;
      &lt;/TableRow&gt;
      &lt;TableRow
          android:id="@+id/tableRow2"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:padding="5dip" &gt;
  
          &lt;ImageView
              android:id="@+id/imgView1"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:src="@drawable/android" /&gt;
      &lt;/TableRow&gt;
      &lt;TableRow
          android:id="@+id/tableRow3"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:padding="5dip" &gt;
  
          &lt;TextView
              android:id="@+id/textView3"
              android:text="Column 3"
              android:textAppearance="?android:attr/textAppearanceLarge" /&gt;
  
           &lt;TextView
              android:id="@+id/textView4"
              android:text="Column 4"
              android:textAppearance="?android:attr/textAppearanceLarge" /&gt;
      &lt;/TableRow&gt;
  &lt;/TableLayout&gt;
  </code></pre>
  
  <p><strong>3. EDIT:</strong> correct the xml file and now adding the Activity:</p>
  
  <pre><code>public class SinglePlayerSp extends Activity implements OnClickListener
  {
      private final Context mContext = this;
      private boolean mBackZoomOne = false;
      private FrameLayout frameZoomOne;
      private FrameLayout frameZoomTwo;
      private static Animator mCurrentAnimatorOne;
      private int mShortAnimationDuration;
      private float startScaleOne;
      private static Animator mCurrentAnimatorTwo;
      private float startScaleTwo;
      private Rect startBoundsOne;
      private Rect startBoundsTwo;
      private static View lastViewOne;
      private static View lastViewTwo;
  
      @Override
      protected void onCreate(Bundle savedInstanceState)
      {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_zoom);
  
          frameZoomOne = (FrameLayout) findViewById(R.id.frameZoomOne);
          frameZoomTwo = (FrameLayout) findViewById(R.id.frameZoomTwo);
          frameZoomOne.setOnClickListener(this);
          frameZoomTwo.setOnClickListener(this);
  
          mShortAnimationDuration = getResources().getInteger(android.R.integer.config_mediumAnimTime);
  
          cardItems = getIntent().getParcelableArrayListExtra(CARD_ITEMS);
  
          java.util.Collections.shuffle(cardItems);
  
      }
  
  private void flipCard(boolean playerOneDeck, final int selectionFromPlayer, final boolean result)
      {
          Card cardItemOne = null;
  
              if (oneCards.get(0) != null)
              {
                  cardItemOne = oneCards.get(0);
              }
  
              if (!mBackZoomOne)
              {
                  getFragmentManager().beginTransaction().setCustomAnimations(R.animator.card_flip_right_in,
                          R.animator.card_flip_right_out, R.animator.card_flip_left_in, R.animator.card_flip_left_out).replace(
                          R.id.frameZoomOne, new CardBackFragment()).commit();
                  mBackZoomOne = true;
              }
              else
              {
                  getFragmentManager().beginTransaction().setCustomAnimations(R.animator.card_flip_right_in,
                          R.animator.card_flip_right_out, R.animator.card_flip_left_in, R.animator.card_flip_left_out).replace(
                          R.id.frameZoomOne,
                          CardFrontFragment.newInstance(cardItemPlayerOne, selectionFromPlayer, playerOneDeck)).commit();
                  mBackZoomOne = false;
  
                  zoomViewOneFromThumb(frameZoomOne, cardItemOne);
              }
      }
  
  private void zoomViewOneFromThumb(final View thumbView, final Card cardItem)
      {
          if (mCurrentAnimatorOne != null)
          {
              mCurrentAnimatorOne.cancel();
          }
  
          lastViewOne = thumbView;
          View.getDefaultSize(0, 0);
          final FrameLayout expandFrameLayout = (FrameLayout) findViewById(R.id.container);
  
          LayoutInflater inflater =
                  (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          View layout = inflater.inflate(R.layout.fragment_card_front_clickable, null);
  
          TableRow rowOne = (TableRow) layout.findViewById(R.id.tableRow1);
          rowOne.setOnClickListener(this);
  
          TextView cardone = (TextView) layout.findViewById(R.id.textView1);
          TextView cardtwo = (TextView) layout.findViewById(R.id.textView2);
          TextView cardthree = (TextView) layout.findViewById(R.id.textView3);
          TextView cardfour = (TextView) layout.findViewById(R.id.textView4);
  
          Locale locale = getApplicationContext().getResources().getConfiguration().locale;
  
          cardone.setText(cardItem.TextOne());
          cardtwo.setText(cardItem.getTextTwo());
          cardthree.setText(cardItem.getTextThree());
          cardfour.setText(cardItem.TextFour());
  
          expandFrameLayout.addView(layout);
  
          startBoundsOne = new Rect();
          final Rect finalBounds = new Rect();
          final Point globalOffset = new Point();
  
          thumbView.getGlobalVisibleRect(startBoundsOne);
          findViewById(R.id.containerSp).getGlobalVisibleRect(finalBounds, globalOffset);
          startBoundsOne.offset(-globalOffset.x, -globalOffset.y);
          finalBounds.offset(-globalOffset.x + 15, -globalOffset.y + 50);
  
          if ((float) finalBounds.width() / finalBounds.height() &gt; (float) startBoundsOne.width()
                  / startBoundsOne.height())
          {
              startScaleOne = (float) startBoundsOne.height() / finalBounds.height();
              float startWidth = startScaleOne * finalBounds.width();
              float deltaWidth = (startWidth - startBoundsOne.width()) / 2;
              startBoundsOne.left -= deltaWidth;
              startBoundsOne.right += deltaWidth;
          }
          else
          {
              startScaleOne = (float) startBoundsOne.width() / finalBounds.width();
              float startHeight = startScaleOne * finalBounds.height();
              float deltaHeight = (startHeight - startBoundsOne.height()) / 2;
              startBoundsOne.top -= deltaHeight;
              startBoundsOne.bottom += deltaHeight;
          }
  
          thumbView.setAlpha(0f);
          expandFrameLayout.setVisibility(View.VISIBLE);
  
          expandFrameLayout.setPivotX(0f);
          expandFrameLayout.setPivotY(0f);
  
          AnimatorSet set = new AnimatorSet();
          set.play(ObjectAnimator.ofFloat(expandFrameLayout, View.X, startBoundsOne.left, finalBounds.left)).with(
                  ObjectAnimator.ofFloat(expandFrameLayout, View.Y, startBoundsOne.top, finalBounds.top)).with(
                  ObjectAnimator.ofFloat(expandFrameLayout, View.SCALE_X, startScaleOne, 1f)).with(
                  ObjectAnimator.ofFloat(expandFrameLayout, View.SCALE_Y, startScaleOne, 1f));
          set.setDuration(mShortAnimationDuration);
          set.setInterpolator(new DecelerateInterpolator());
          set.addListener(new AnimatorListenerAdapter()
          {
              @Override
              public void onAnimationEnd(Animator animation)
              {
                  mCurrentAnimatorOne = null;
              }
  
              @Override
              public void onAnimationCancel(Animator animation)
              {
                  mCurrentAnimatorOne = null;
              }
          });
          set.start();
          mCurrentAnimatorOne = set;
          startScaleFinal = startScaleOne; // with this or without this, i have the same problem
      }
  
  private void minimizeViewOne(final View expandFrameLayout)
      {
          AnimatorSet set = new AnimatorSet();
          set.play(ObjectAnimator.ofFloat(expandFrameLayout, View.X, startBoundsOne.left)).with(
                  ObjectAnimator.ofFloat(expandFrameLayout, View.Y, startBoundsOne.top)).with(
                  ObjectAnimator.ofFloat(expandFrameLayout, View.SCALE_X, startScaleFinal)).with(
                  ObjectAnimator.ofFloat(expandFrameLayout, View.SCALE_Y, startScaleFinal));
          set.setDuration(mShortAnimationDuration);
          set.setInterpolator(new DecelerateInterpolator());
          set.addListener(new AnimatorListenerAdapter()
          {
              @Override
              public void onAnimationEnd(Animator animation)
              {
                  lastViewOne.setAlpha(1f);
                  expandFrameLayout.setVisibility(View.GONE);
                  mCurrentAnimatorOne = null;
              }
  
              @Override
              public void onAnimationCancel(Animator animation)
              {
                  lastViewOne.setAlpha(1f);
                  expandFrameLayout.setVisibility(View.GONE);
                  mCurrentAnimatorOne = null;
              }
          });
          set.start();
          mCurrentAnimatorOne = set;
      }
  }
  </code></pre>
  
  <p>OK that's now the full code. At the End is an onClick Method, in there I receive user actions. from there I call the minimizeView Method, then some checks, after this I call the flipCard. That's all.</p>