diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2019-10-28 19:54:57 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2019-10-28 19:54:57 +0000 |
commit | 7bcd90e2242cf8be3e48f8138a88b17d17e0e93b (patch) | |
tree | 0d8c70eb3fa9cdcaa7449527578f7a6b31e0e00c | |
parent | 6751e9436edb2224b36c05871bcb8dd88538b0e6 (diff) | |
parent | cf08568adc4e38b98329533b9b5246d172f04868 (diff) | |
download | support-7bcd90e2242cf8be3e48f8138a88b17d17e0e93b.tar.gz |
Merge "Fix fragment transition epicenter calculation" into androidx-master-dev
-rw-r--r-- | fragment/fragment/src/main/java/androidx/fragment/app/FragmentTransitionImpl.java | 31 | ||||
-rw-r--r-- | transition/transition/src/androidTest/java/androidx/transition/EpicenterTest.kt | 102 |
2 files changed, 130 insertions, 3 deletions
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentTransitionImpl.java b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentTransitionImpl.java index 4cb1f3462bd..4e4a7f75879 100644 --- a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentTransitionImpl.java +++ b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentTransitionImpl.java @@ -20,8 +20,10 @@ import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX; import android.annotation.SuppressLint; import android.graphics.Rect; +import android.graphics.RectF; import android.view.View; import android.view.ViewGroup; +import android.view.ViewParent; import androidx.annotation.NonNull; import androidx.annotation.RestrictTo; @@ -77,9 +79,32 @@ public abstract class FragmentTransitionImpl { * containing the bounds relative to the screen that the view is in. */ protected void getBoundsOnScreen(View view, Rect epicenter) { - int[] loc = new int[2]; - view.getLocationOnScreen(loc); - epicenter.set(loc[0], loc[1], loc[0] + view.getWidth(), loc[1] + view.getHeight()); + if (!ViewCompat.isAttachedToWindow(view)) { + return; + } + + final RectF rect = new RectF(); + rect.set(0, 0, view.getWidth(), view.getHeight()); + + view.getMatrix().mapRect(rect); + rect.offset(view.getLeft(), view.getTop()); + + ViewParent parent = view.getParent(); + while (parent instanceof View) { + View parentView = (View) parent; + + rect.offset(-parentView.getScrollX(), -parentView.getScrollY()); + parentView.getMatrix().mapRect(rect); + rect.offset(parentView.getLeft(), parentView.getTop()); + + parent = parentView.getParent(); + } + + final int[] loc = new int[2]; + view.getRootView().getLocationOnScreen(loc); + rect.offset(loc[0], loc[1]); + epicenter.set(Math.round(rect.left), Math.round(rect.top), Math.round(rect.right), + Math.round(rect.bottom)); } /** diff --git a/transition/transition/src/androidTest/java/androidx/transition/EpicenterTest.kt b/transition/transition/src/androidTest/java/androidx/transition/EpicenterTest.kt new file mode 100644 index 00000000000..9360122a8f3 --- /dev/null +++ b/transition/transition/src/androidTest/java/androidx/transition/EpicenterTest.kt @@ -0,0 +1,102 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.transition + +import android.graphics.Rect +import android.graphics.RectF +import android.view.View +import android.view.ViewGroup +import android.widget.FrameLayout +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import androidx.test.platform.app.InstrumentationRegistry +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +class EpicenterTest : BaseTest() { + + @Test + fun defaultEpicenter() { + testViewEpicenter {} + } + + @Test + fun rotatedViewEpicenter() { + testViewEpicenter { + rotation = 180f + } + } + + @Test + fun scaledPivotEpicenter() { + testViewEpicenter { + pivotX = width.toFloat() + pivotY = height.toFloat() + scaleX = 0.5f + scaleY = 0.5f + } + } + + private fun testViewEpicenter(viewSetup: View.() -> Unit) { + val view = setupTestView() + view.viewSetup() + val transitionSupport = FragmentTransitionSupport() + + val transition = AutoTransition() + transitionSupport.setEpicenter(transition, view) + + val rect = RectF(0f, 0f, view.width.toFloat(), view.height.toFloat()) + view.matrix.mapRect(rect) + + rect.offset(view.left.toFloat(), view.top.toFloat()) + val (parentX, parentY) = IntArray(2).apply { + (view.parent as View).getLocationOnScreen(this) + } + rect.offset(parentX.toFloat(), parentY.toFloat()) + + val expected = Rect().also { + rect.round(it) + } + + assertThat(transition.epicenter).isEqualTo(expected) + InstrumentationRegistry.getInstrumentation().runOnMainSync { + (view.parent as ViewGroup).removeView(view) + } + } + + /** + * Returns a view of size 100x100 located at (50, 50) + */ + private fun setupTestView(): View { + val view = View(rule.activity) + InstrumentationRegistry.getInstrumentation().runOnMainSync { + rule.activity.root.addView(view, FrameLayout.LayoutParams(100, 100) + .apply { + leftMargin = 50 + topMargin = 50 + }) + view.left = 50 + view.top = 50 + view.right = 150 + view.bottom = 150 + } + return view + } +}
\ No newline at end of file |