diff options
5 files changed, 170 insertions, 42 deletions
diff --git a/packages/SystemUI/res/drawable/docked_divider_handle.xml b/packages/SystemUI/res/drawable/docked_divider_handle.xml deleted file mode 100644 index 84c0343185ac..000000000000 --- a/packages/SystemUI/res/drawable/docked_divider_handle.xml +++ /dev/null @@ -1,22 +0,0 @@ -<!-- -Copyright (C) 2015 The Android Open Source Project - - Licensed under the Apache License, Version 2 (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. ---> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle"> - <size android:height="@dimen/docked_divider_handle_height" - android:width="@dimen/docked_divider_handle_width" /> - <corners android:radius="1dp" /> - <solid android:color="@color/docked_divider_handle" /> -</shape>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/docked_stack_divider.xml b/packages/SystemUI/res/layout/docked_stack_divider.xml index 22ed216de570..7ea5027b78f4 100644 --- a/packages/SystemUI/res/layout/docked_stack_divider.xml +++ b/packages/SystemUI/res/layout/docked_stack_divider.xml @@ -24,10 +24,9 @@ android:id="@+id/docked_divider_background" android:background="@color/docked_divider_background"/> - <ImageButton + <com.android.systemui.stackdivider.DividerHandleView style="@style/DockedDividerHandle" android:id="@+id/docked_divider_handle" - android:background="@null" - android:src="@drawable/docked_divider_handle"/> + android:background="@null"/> </com.android.systemui.stackdivider.DividerView> diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java new file mode 100644 index 000000000000..5ef56f3312dd --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2015 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 com.android.systemui.stackdivider; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.annotation.Nullable; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.util.AttributeSet; +import android.util.Property; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; +import android.widget.ImageButton; + +import com.android.systemui.R; + +/** + * View for the handle in the docked stack divider. + */ +public class DividerHandleView extends ImageButton { + + private final static Property<DividerHandleView, Integer> WIDTH_PROPERTY + = new Property<DividerHandleView, Integer>(Integer.class, "width") { + + @Override + public Integer get(DividerHandleView object) { + return object.mCurrentWidth; + } + + @Override + public void set(DividerHandleView object, Integer value) { + object.mCurrentWidth = value; + object.invalidate(); + } + }; + + private final static Property<DividerHandleView, Integer> HEIGHT_PROPERTY + = new Property<DividerHandleView, Integer>(Integer.class, "height") { + + @Override + public Integer get(DividerHandleView object) { + return object.mCurrentHeight; + } + + @Override + public void set(DividerHandleView object, Integer value) { + object.mCurrentHeight = value; + object.invalidate(); + } + }; + + private final Paint mPaint = new Paint(); + private final int mWidth; + private final int mHeight; + private final int mCircleDiameter; + private final Interpolator mFastOutSlowInInterpolator; + private int mCurrentWidth; + private int mCurrentHeight; + private AnimatorSet mAnimator; + + public DividerHandleView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + mPaint.setColor(getResources().getColor(R.color.docked_divider_handle, null)); + mPaint.setAntiAlias(true); + mWidth = getResources().getDimensionPixelSize(R.dimen.docked_divider_handle_width); + mHeight = getResources().getDimensionPixelSize(R.dimen.docked_divider_handle_height); + mCurrentWidth = mWidth; + mCurrentHeight = mHeight; + mCircleDiameter = (mWidth + mHeight) / 3; + mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(), + android.R.interpolator.fast_out_slow_in); + } + + public void setTouching(boolean touching, boolean animate) { + if (mAnimator != null) { + mAnimator.cancel(); + mAnimator = null; + } + if (!animate) { + if (touching) { + mCurrentWidth = mCircleDiameter; + mCurrentHeight = mCircleDiameter; + } else { + mCurrentWidth = mWidth; + mCurrentHeight = mHeight; + } + invalidate(); + } else { + animateToTarget(touching ? mCircleDiameter : mWidth, + touching ? mCircleDiameter : mHeight, touching); + } + } + + private void animateToTarget(int targetWidth, int targetHeight, boolean touching) { + ObjectAnimator widthAnimator = ObjectAnimator.ofInt(this, WIDTH_PROPERTY, + mCurrentWidth, targetWidth); + ObjectAnimator heightAnimator = ObjectAnimator.ofInt(this, HEIGHT_PROPERTY, + mCurrentHeight, targetHeight); + mAnimator = new AnimatorSet(); + mAnimator.playTogether(widthAnimator, heightAnimator); + mAnimator.setDuration(touching + ? DividerView.TOUCH_ANIMATION_DURATION + : DividerView.TOUCH_RELEASE_ANIMATION_DURATION); + mAnimator.setInterpolator(touching + ? DividerView.TOUCH_RESPONSE_INTERPOLATOR + : mFastOutSlowInInterpolator); + mAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mAnimator = null; + } + }); + mAnimator.start(); + } + + @Override + protected void onDraw(Canvas canvas) { + int left = getWidth() / 2 - mCurrentWidth / 2; + int top = getHeight() / 2 - mCurrentHeight / 2; + int radius = Math.min(mCurrentWidth, mCurrentHeight) / 2; + canvas.drawRoundRect(left, top, left + mCurrentWidth, top + mCurrentHeight, + radius, radius, mPaint); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 3b4c59615bea..4c83b51e32a0 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -60,6 +60,11 @@ import static android.view.PointerIcon.STYLE_VERTICAL_DOUBLE_ARROW; public class DividerView extends FrameLayout implements OnTouchListener, OnComputeInternalInsetsListener { + static final long TOUCH_ANIMATION_DURATION = 150; + static final long TOUCH_RELEASE_ANIMATION_DURATION = 200; + static final Interpolator TOUCH_RESPONSE_INTERPOLATOR = + new PathInterpolator(0.3f, 0f, 0.1f, 1f); + private static final String TAG = "DividerView"; private static final int TASK_POSITION_SAME = Integer.MAX_VALUE; @@ -69,7 +74,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, private static final PathInterpolator SLOWDOWN_INTERPOLATOR = new PathInterpolator(0.5f, 1f, 0.5f, 1f); - private ImageButton mHandle; + private DividerHandleView mHandle; private View mBackground; private int mStartX; private int mStartY; @@ -93,8 +98,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, private final Rect mLastResizeRect = new Rect(); private final WindowManagerProxy mWindowManagerProxy = WindowManagerProxy.getInstance(); private Interpolator mFastOutSlowInInterpolator; - private final Interpolator mTouchResponseInterpolator = - new PathInterpolator(0.3f, 0f, 0.1f, 1f); private DividerWindowManager mWindowManager; private VelocityTracker mVelocityTracker; private FlingAnimationUtils mFlingAnimationUtils; @@ -121,7 +124,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, @Override protected void onFinishInflate() { super.onFinishInflate(); - mHandle = (ImageButton) findViewById(R.id.docked_divider_handle); + mHandle = (DividerHandleView) findViewById(R.id.docked_divider_handle); mBackground = findViewById(R.id.docked_divider_background); mHandle.setOnTouchListener(this); mDividerWindowWidth = getResources().getDimensionPixelSize( @@ -157,7 +160,8 @@ public class DividerView extends FrameLayout implements OnTouchListener, return mWindowManagerProxy; } - public boolean startDragging() { + public boolean startDragging(boolean animate) { + mHandle.setTouching(true, animate); mDockSide = mWindowManagerProxy.getDockSide(); mSnapAlgorithm = new DividerSnapAlgorithm(getContext(), mFlingAnimationUtils, mDisplayWidth, mDisplayHeight, mDividerSize, isHorizontalDivision(), mStableInsets); @@ -172,6 +176,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, } public void stopDragging(int position, float velocity) { + mHandle.setTouching(false, true /* animate */); fling(position, velocity); mWindowManager.setSlippery(true); releaseBackground(); @@ -192,7 +197,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, mStartX = (int) event.getX(); mStartY = (int) event.getY(); getLocationOnScreen(mTempInt2); - boolean result = startDragging(); + boolean result = startDragging(true /* animate */); if (isHorizontalDivision()) { mStartPosition = mTempInt2[1] + mDividerInsets; } else { @@ -282,29 +287,33 @@ public class DividerView extends FrameLayout implements OnTouchListener, mBackground.animate().scaleX(1.4f); } mBackground.animate() - .setInterpolator(mTouchResponseInterpolator) - .setDuration(150) - .translationZ(mTouchElevation); + .setInterpolator(TOUCH_RESPONSE_INTERPOLATOR) + .setDuration(TOUCH_ANIMATION_DURATION) + .translationZ(mTouchElevation) + .start(); // Lift handle as well so it doesn't get behind the background, even though it doesn't // cast shadow. mHandle.animate() - .setInterpolator(mTouchResponseInterpolator) - .setDuration(150) - .translationZ(mTouchElevation); + .setInterpolator(TOUCH_RESPONSE_INTERPOLATOR) + .setDuration(TOUCH_ANIMATION_DURATION) + .translationZ(mTouchElevation) + .start(); } private void releaseBackground() { mBackground.animate() .setInterpolator(mFastOutSlowInInterpolator) - .setDuration(200) + .setDuration(TOUCH_RELEASE_ANIMATION_DURATION) .translationZ(0) .scaleX(1f) - .scaleY(1f); + .scaleY(1f) + .start(); mHandle.animate() .setInterpolator(mFastOutSlowInInterpolator) - .setDuration(200) - .translationZ(0); + .setDuration(TOUCH_RELEASE_ANIMATION_DURATION) + .translationZ(0) + .start(); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java index 3a30f348daed..cc85d0fb8a25 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java @@ -191,7 +191,7 @@ public class NavigationBarGestureHelper extends GestureDetector.SimpleOnGestureL mRecentsComponent.dockTopTask(mDragMode == DRAG_MODE_RECENTS, createMode, initialBounds); if (mDragMode == DRAG_MODE_DIVIDER) { - mDivider.getView().startDragging(); + mDivider.getView().startDragging(false /* animate */); } mDockWindowTouchSlopExceeded = true; MetricsLogger.action(mContext, |