diff options
author | Jason Monk <jmonk@google.com> | 2015-06-17 12:45:16 -0400 |
---|---|---|
committer | Jason Monk <jmonk@google.com> | 2015-06-18 13:26:27 -0400 |
commit | bfaa53e0b09b255e1ba44017052041e435c6f5e0 (patch) | |
tree | f5dbd673d7491620a0e86a48fc4e484cdb794746 /src/com | |
parent | d8cb9a81bbd71737149a3fe3fba8bb13c05439c3 (diff) | |
download | android_packages_apps_PackageInstaller-bfaa53e0b09b255e1ba44017052041e435c6f5e0.tar.gz android_packages_apps_PackageInstaller-bfaa53e0b09b255e1ba44017052041e435c6f5e0.tar.bz2 android_packages_apps_PackageInstaller-bfaa53e0b09b255e1ba44017052041e435c6f5e0.zip |
Fix animating between very different heights
- Expand ViewHeightController so it can expand up or down
- Control the height of all containers in the hierarchy
- Intercept touch events and compensate for any top offset
on the root view, since we expand upwards
- Remove the current description from the description container
so that it can shrink in relayout if necessary.
Bug: 21879037
Bug: 21784297
Change-Id: I3ad562158013b75c5e9150cbd91c96c6ff4941c9
Diffstat (limited to 'src/com')
3 files changed, 82 insertions, 22 deletions
diff --git a/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java b/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java index ba2a4cd9..98773f54 100644 --- a/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java +++ b/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java @@ -37,6 +37,8 @@ import android.text.style.ForegroundColorSpan; import android.util.ArrayMap; import android.util.Log; import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; import android.view.Window; import android.view.WindowManager; @@ -146,6 +148,16 @@ public class GrantPermissionsActivity extends Activity } @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + View rootView = getWindow().getDecorView(); + if (rootView.getTop() != 0) { + // We are animating the top view, need to compensate for that in motion events. + ev.setLocation(ev.getX(), ev.getY() - rootView.getTop()); + } + return super.dispatchTouchEvent(ev); + } + + @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); mViewHandler.saveInstanceState(outState); diff --git a/src/com/android/packageinstaller/permission/ui/GrantPermissionsDefaultViewHandler.java b/src/com/android/packageinstaller/permission/ui/GrantPermissionsDefaultViewHandler.java index d755feeb..1f95352d 100644 --- a/src/com/android/packageinstaller/permission/ui/GrantPermissionsDefaultViewHandler.java +++ b/src/com/android/packageinstaller/permission/ui/GrantPermissionsDefaultViewHandler.java @@ -28,6 +28,8 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLayoutChangeListener; import android.view.ViewGroup; +import android.view.ViewParent; +import android.view.ViewRootImpl; import android.view.WindowManager.LayoutParams; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; @@ -38,6 +40,8 @@ import android.widget.TextView; import com.android.packageinstaller.R; +import java.util.ArrayList; + final class GrantPermissionsDefaultViewHandler implements GrantPermissionsViewHandler, OnClickListener { @@ -76,7 +80,7 @@ final class GrantPermissionsDefaultViewHandler private CheckBox mDoNotAskCheckbox; private Button mAllowButton; - private ViewHeightController mRootViewHeightController; + private ArrayList<ViewHeightController> mHeightControllers; private ManualLayoutFrame mRootView; // Needed for animation @@ -144,18 +148,29 @@ final class GrantPermissionsDefaultViewHandler updateGroup(); } } - updateDoNotAskCheckBox(); + } private void animateToPermission() { - if (mRootViewHeightController == null) { - // Allow height control of the real root view, not the root of what we inflate. - // Need to do it on the root view so that the background drawable of the dialog - // moves with the animation. - View realRootView = mRootView.getViewRootImpl().getView(); - mRootViewHeightController = new ViewHeightController(realRootView); - mRootViewHeightController.setHeight(realRootView.getHeight()); + if (mHeightControllers == null) { + // We need to manually control the height of any views heigher than the root that + // we inflate. Find all the views up to the root and create ViewHeightControllers for + // them. + mHeightControllers = new ArrayList<>(); + ViewRootImpl viewRoot = mRootView.getViewRootImpl(); + ViewParent v = mRootView.getParent(); + addHeightController(mDialogContainer); + addHeightController(mRootView); + while (v != viewRoot) { + addHeightController((View) v); + v = v.getParent(); + } + // On the heighest level view, we want to setTop rather than setBottom to control the + // height, this way the dialog will grow up rather than down. + ViewHeightController realRootView = + mHeightControllers.get(mHeightControllers.size() - 1); + realRootView.setControlTop(true); } // Grab the current height/y positions, then wait for the layout to change, @@ -205,7 +220,14 @@ final class GrantPermissionsDefaultViewHandler int width = mDescContainer.getRootView().getWidth(); mDescContainer.addView(mNextDesc); mNextDesc.setTranslationX(width); + final View oldDesc = mCurrentDesc; + // Remove the old view from the description, so that we can shrink if necessary. + mDescContainer.removeView(oldDesc); + oldDesc.setPadding(mDescContainer.getLeft(), mDescContainer.getTop(), + mRootView.getRight() - mDescContainer.getRight(), 0); + mRootView.addView(oldDesc); + mCurrentDesc = mNextDesc; mNextDesc.animate() .translationX(0) @@ -217,12 +239,18 @@ final class GrantPermissionsDefaultViewHandler @Override public void onAnimationEnd(Animator animation) { // This is the longest animation, when it finishes, we are done. - mDescContainer.removeView(oldDesc); + mRootView.removeView(oldDesc); } }) .start(); } + private void addHeightController(View v) { + ViewHeightController heightController = new ViewHeightController(v); + heightController.setHeight(v.getHeight()); + mHeightControllers.add(heightController); + } + private SparseArray<Float> getViewPositions() { SparseArray<Float> locMap = new SparseArray<>(); final int N = mDialogContainer.getChildCount(); @@ -254,7 +282,9 @@ final class GrantPermissionsDefaultViewHandler .start(); } } - mRootViewHeightController.animateAddHeight(heightDiff); + for (int i = 0; i < mHeightControllers.size(); i++) { + mHeightControllers.get(i).animateAddHeight(heightDiff); + } } @Override @@ -344,38 +374,53 @@ final class GrantPermissionsDefaultViewHandler private static final class ViewHeightController implements OnLayoutChangeListener { private final View mView; private int mHeight; + private int mNextHeight; + private boolean mControlTop; + private ObjectAnimator mAnimator; public ViewHeightController(View view) { mView = view; mView.addOnLayoutChangeListener(this); } + public void setControlTop(boolean controlTop) { + mControlTop = controlTop; + } + public void animateAddHeight(int heightDiff) { if (heightDiff != 0) { - final int startHeight = mHeight; - final int endHeight = startHeight + heightDiff; - ObjectAnimator animator = ObjectAnimator.ofInt(this, "height", - startHeight, endHeight); - animator.setStartDelay(SIZE_START_DELAY); - animator.setDuration(SIZE_START_LENGTH); - animator.start(); + if (mNextHeight == 0) { + mNextHeight = mHeight; + } + mNextHeight += heightDiff; + if (mAnimator != null) { + mAnimator.cancel(); + } + mAnimator = ObjectAnimator.ofInt(this, "height", mHeight, mNextHeight); + mAnimator.setStartDelay(SIZE_START_DELAY); + mAnimator.setDuration(SIZE_START_LENGTH); + mAnimator.start(); } } public void setHeight(int height) { mHeight = height; - updateTop(); + updateHeight(); } @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { // Ensure that the height never changes. - updateTop(); + updateHeight(); } - private void updateTop() { - mView.setTop(mView.getBottom() - mHeight); + private void updateHeight() { + if (mControlTop) { + mView.setTop(mView.getBottom() - mHeight); + } else { + mView.setBottom(mView.getTop() + mHeight); + } } } } diff --git a/src/com/android/packageinstaller/permission/ui/ManualLayoutFrame.java b/src/com/android/packageinstaller/permission/ui/ManualLayoutFrame.java index 97049df8..99a74e75 100644 --- a/src/com/android/packageinstaller/permission/ui/ManualLayoutFrame.java +++ b/src/com/android/packageinstaller/permission/ui/ManualLayoutFrame.java @@ -17,6 +17,7 @@ package com.android.packageinstaller.permission.ui; import android.content.Context; import android.util.AttributeSet; +import android.view.View; import android.widget.FrameLayout; /** @@ -30,6 +31,8 @@ public class ManualLayoutFrame extends FrameLayout { private int mDesiredHeight; private int mHeight; + private View mOffsetView; + public ManualLayoutFrame(Context context, AttributeSet attrs) { super(context, attrs); setClipChildren(false); |