Making the self always follow the vertical progress without any min height limit.
After a certain height, the self fades out, but keeps following the vertical progress. Eventually the fade-out can be decoupled from vertical progress and tied to the state Bug: 109829614 Change-Id: I9808ed3fa1730b938196bc6d3518a6d096a13f4c
This commit is contained in:
parent
808e7cae66
commit
0f3af75eb0
|
@ -54,4 +54,6 @@
|
||||||
<dimen name="clear_all_container_width">168dp</dimen>
|
<dimen name="clear_all_container_width">168dp</dimen>
|
||||||
|
|
||||||
<dimen name="shelf_surface_radius">16dp</dimen>
|
<dimen name="shelf_surface_radius">16dp</dimen>
|
||||||
|
<!-- same as vertical_drag_handle_size -->
|
||||||
|
<dimen name="shelf_surface_offset">24dp</dimen>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -15,11 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package com.android.quickstep.views;
|
package com.android.quickstep.views;
|
||||||
|
|
||||||
import static android.support.v4.graphics.ColorUtils.compositeColors;
|
|
||||||
import static android.support.v4.graphics.ColorUtils.setAlphaComponent;
|
import static android.support.v4.graphics.ColorUtils.setAlphaComponent;
|
||||||
|
|
||||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||||
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
|
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||||
|
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
|
@ -32,7 +32,7 @@ import android.util.AttributeSet;
|
||||||
|
|
||||||
import com.android.launcher3.DeviceProfile;
|
import com.android.launcher3.DeviceProfile;
|
||||||
import com.android.launcher3.R;
|
import com.android.launcher3.R;
|
||||||
import com.android.launcher3.uioverrides.OverviewState;
|
import com.android.launcher3.Utilities;
|
||||||
import com.android.launcher3.util.Themes;
|
import com.android.launcher3.util.Themes;
|
||||||
import com.android.launcher3.views.ScrimView;
|
import com.android.launcher3.views.ScrimView;
|
||||||
|
|
||||||
|
@ -45,22 +45,30 @@ import com.android.launcher3.views.ScrimView;
|
||||||
*/
|
*/
|
||||||
public class ShelfScrimView extends ScrimView {
|
public class ShelfScrimView extends ScrimView {
|
||||||
|
|
||||||
|
// If the progress is more than this, shelf follows the finger, otherwise it moves faster to
|
||||||
|
// cover the whole screen
|
||||||
|
private static final float SCRIM_CATCHUP_THRESHOLD = 0.2f;
|
||||||
|
|
||||||
// In transposed layout, we simply draw a flat color.
|
// In transposed layout, we simply draw a flat color.
|
||||||
private boolean mDrawingFlatColor;
|
private boolean mDrawingFlatColor;
|
||||||
|
|
||||||
// For shelf mode
|
// For shelf mode
|
||||||
private final int mEndAlpha;
|
private final int mEndAlpha;
|
||||||
private final int mThresholdAlpha;
|
|
||||||
private final float mRadius;
|
private final float mRadius;
|
||||||
private final float mMaxScrimAlpha;
|
private final float mMaxScrimAlpha;
|
||||||
private final Paint mPaint;
|
private final Paint mPaint;
|
||||||
|
|
||||||
// Max vertical progress after which the scrim stops moving.
|
// Mid point where the alpha changes
|
||||||
private float mMoveThreshold;
|
private int mMidAlpha;
|
||||||
// Minimum visible size of the scrim.
|
private float mMidProgress;
|
||||||
private int mMinSize;
|
|
||||||
|
private float mShiftRange;
|
||||||
|
|
||||||
|
private final float mShelfOffset;
|
||||||
|
private float mTopOffset;
|
||||||
|
private float mShelfTop;
|
||||||
|
private float mShelfTopAtThreshold;
|
||||||
|
|
||||||
private float mScrimMoveFactor = 0;
|
|
||||||
private int mShelfColor;
|
private int mShelfColor;
|
||||||
private int mRemainingScreenColor;
|
private int mRemainingScreenColor;
|
||||||
|
|
||||||
|
@ -73,10 +81,10 @@ public class ShelfScrimView extends ScrimView {
|
||||||
mMaxScrimAlpha = OVERVIEW.getWorkspaceScrimAlpha(mLauncher);
|
mMaxScrimAlpha = OVERVIEW.getWorkspaceScrimAlpha(mLauncher);
|
||||||
|
|
||||||
mEndAlpha = Color.alpha(mEndScrim);
|
mEndAlpha = Color.alpha(mEndScrim);
|
||||||
mThresholdAlpha = Themes.getAttrInteger(context, R.attr.allAppsInterimScrimAlpha);
|
|
||||||
mRadius = mLauncher.getResources().getDimension(R.dimen.shelf_surface_radius);
|
mRadius = mLauncher.getResources().getDimension(R.dimen.shelf_surface_radius);
|
||||||
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
|
||||||
|
mShelfOffset = context.getResources().getDimension(R.dimen.shelf_surface_offset);
|
||||||
// Just assume the easiest UI for now, until we have the proper layout information.
|
// Just assume the easiest UI for now, until we have the proper layout information.
|
||||||
mDrawingFlatColor = true;
|
mDrawingFlatColor = true;
|
||||||
}
|
}
|
||||||
|
@ -93,10 +101,15 @@ public class ShelfScrimView extends ScrimView {
|
||||||
mDrawingFlatColor = dp.isVerticalBarLayout();
|
mDrawingFlatColor = dp.isVerticalBarLayout();
|
||||||
|
|
||||||
if (!mDrawingFlatColor) {
|
if (!mDrawingFlatColor) {
|
||||||
float swipeLength = OverviewState.getDefaultSwipeHeight(mLauncher);
|
|
||||||
mMoveThreshold = 1 - swipeLength / mLauncher.getAllAppsController().getShiftRange();
|
|
||||||
mMinSize = dp.hotseatBarSizePx + dp.getInsets().bottom;
|
|
||||||
mRemainingScreenPathValid = false;
|
mRemainingScreenPathValid = false;
|
||||||
|
mShiftRange = mLauncher.getAllAppsController().getShiftRange();
|
||||||
|
|
||||||
|
mMidProgress = OVERVIEW.getVerticalProgress(mLauncher);
|
||||||
|
mMidAlpha = mMidProgress >= 1 ? 0
|
||||||
|
: Themes.getAttrInteger(getContext(), R.attr.allAppsInterimScrimAlpha);
|
||||||
|
|
||||||
|
mTopOffset = dp.getInsets().top - mShelfOffset;
|
||||||
|
mShelfTopAtThreshold = mShiftRange * SCRIM_CATCHUP_THRESHOLD + mTopOffset;
|
||||||
updateColors();
|
updateColors();
|
||||||
}
|
}
|
||||||
updateDragHandleAlpha();
|
updateDragHandleAlpha();
|
||||||
|
@ -107,82 +120,79 @@ public class ShelfScrimView extends ScrimView {
|
||||||
public void updateColors() {
|
public void updateColors() {
|
||||||
super.updateColors();
|
super.updateColors();
|
||||||
if (mDrawingFlatColor) {
|
if (mDrawingFlatColor) {
|
||||||
|
mDragHandleOffset = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mProgress >= mMoveThreshold) {
|
mDragHandleOffset = mShelfOffset - mDragHandleSize;
|
||||||
mScrimMoveFactor = 1;
|
if (mProgress >= SCRIM_CATCHUP_THRESHOLD) {
|
||||||
|
mShelfTop = mShiftRange * mProgress + mTopOffset;
|
||||||
if (mProgress >= 1) {
|
|
||||||
mShelfColor = 0;
|
|
||||||
} else {
|
|
||||||
int alpha = Math.round(mThresholdAlpha * ACCEL_2.getInterpolation(
|
|
||||||
(1 - mProgress) / (1 - mMoveThreshold)));
|
|
||||||
mShelfColor = setAlphaComponent(mEndScrim, alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
mRemainingScreenColor = 0;
|
|
||||||
} else if (mProgress <= 0) {
|
|
||||||
mScrimMoveFactor = 0;
|
|
||||||
mShelfColor = mCurrentFlatColor;
|
|
||||||
mRemainingScreenColor = 0;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
mScrimMoveFactor = mProgress / mMoveThreshold;
|
mShelfTop = Utilities.mapRange(mProgress / SCRIM_CATCHUP_THRESHOLD, -mRadius,
|
||||||
mRemainingScreenColor = setAlphaComponent(mScrimColor,
|
mShelfTopAtThreshold);
|
||||||
Math.round((1 - mScrimMoveFactor) * mMaxScrimAlpha * 255));
|
}
|
||||||
|
|
||||||
// Merge the remainingScreenColor and shelfColor in one to avoid overdraw.
|
if (mProgress >= 1) {
|
||||||
int alpha = mEndAlpha - Math.round((mEndAlpha - mThresholdAlpha) * mScrimMoveFactor);
|
mRemainingScreenColor = 0;
|
||||||
mShelfColor = compositeColors(setAlphaComponent(mEndScrim, alpha),
|
mShelfColor = 0;
|
||||||
mRemainingScreenColor);
|
} else if (mProgress >= mMidProgress) {
|
||||||
|
mRemainingScreenColor = 0;
|
||||||
|
|
||||||
|
int alpha = Math.round(Utilities.mapToRange(
|
||||||
|
mProgress, mMidProgress, 1, mMidAlpha, 0, ACCEL));
|
||||||
|
mShelfColor = setAlphaComponent(mEndScrim, alpha);
|
||||||
|
} else {
|
||||||
|
mDragHandleOffset += mShiftRange * (mMidProgress - mProgress);
|
||||||
|
|
||||||
|
int alpha = Math.round(
|
||||||
|
Utilities.mapToRange(mProgress, (float) 0, mMidProgress, (float) mEndAlpha,
|
||||||
|
(float) mMidAlpha, LINEAR));
|
||||||
|
mShelfColor = setAlphaComponent(mEndScrim, alpha);
|
||||||
|
|
||||||
|
int remainingScrimAlpha = Math.round(
|
||||||
|
Utilities.mapToRange(mProgress, (float) 0, mMidProgress, mMaxScrimAlpha,
|
||||||
|
(float) 0, LINEAR));
|
||||||
|
mRemainingScreenColor = setAlphaComponent(mScrimColor, remainingScrimAlpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas canvas) {
|
protected void onDraw(Canvas canvas) {
|
||||||
float translate = drawBackground(canvas);
|
drawBackground(canvas);
|
||||||
|
drawDragHandle(canvas);
|
||||||
if (mDragHandle != null) {
|
|
||||||
canvas.translate(0, -translate);
|
|
||||||
mDragHandle.draw(canvas);
|
|
||||||
canvas.translate(0, translate);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private float drawBackground(Canvas canvas) {
|
private void drawBackground(Canvas canvas) {
|
||||||
if (mDrawingFlatColor) {
|
if (mDrawingFlatColor) {
|
||||||
if (mCurrentFlatColor != 0) {
|
if (mCurrentFlatColor != 0) {
|
||||||
canvas.drawColor(mCurrentFlatColor);
|
canvas.drawColor(mCurrentFlatColor);
|
||||||
}
|
}
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mShelfColor == 0) {
|
if (Color.alpha(mShelfColor) == 0) {
|
||||||
return 0;
|
return;
|
||||||
} else if (mScrimMoveFactor <= 0) {
|
} else if (mProgress <= 0) {
|
||||||
canvas.drawColor(mShelfColor);
|
canvas.drawColor(mShelfColor);
|
||||||
return getHeight();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float minTop = getHeight() - mMinSize;
|
int height = getHeight();
|
||||||
float top = minTop * mScrimMoveFactor - mDragHandleSize;
|
int width = getWidth();
|
||||||
|
|
||||||
// Draw the scrim over the remaining screen if needed.
|
// Draw the scrim over the remaining screen if needed.
|
||||||
if (mRemainingScreenColor != 0) {
|
if (mRemainingScreenColor != 0) {
|
||||||
if (!mRemainingScreenPathValid) {
|
if (!mRemainingScreenPathValid) {
|
||||||
mTempPath.reset();
|
mTempPath.reset();
|
||||||
// Using a arbitrary '+10' in the bottom to avoid any left-overs at the
|
// Using a arbitrary '+10' in the bottom to avoid any left-overs at the
|
||||||
// corners due to rounding issues.
|
// corners due to rounding issues.
|
||||||
mTempPath.addRoundRect(0, minTop, getWidth(), getHeight() + mRadius + 10,
|
mTempPath.addRoundRect(0, height - mRadius, width, height + mRadius + 10,
|
||||||
mRadius, mRadius, Direction.CW);
|
mRadius, mRadius, Direction.CW);
|
||||||
|
|
||||||
mRemainingScreenPath.reset();
|
mRemainingScreenPath.reset();
|
||||||
mRemainingScreenPath.addRect(0, 0, getWidth(), getHeight(), Direction.CW);
|
mRemainingScreenPath.addRect(0, 0, width, height, Direction.CW);
|
||||||
mRemainingScreenPath.op(mTempPath, Op.DIFFERENCE);
|
mRemainingScreenPath.op(mTempPath, Op.DIFFERENCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
float offset = minTop - top;
|
float offset = height - mRadius - mShelfTop;
|
||||||
canvas.translate(0, -offset);
|
canvas.translate(0, -offset);
|
||||||
mPaint.setColor(mRemainingScreenColor);
|
mPaint.setColor(mRemainingScreenColor);
|
||||||
canvas.drawPath(mRemainingScreenPath, mPaint);
|
canvas.drawPath(mRemainingScreenPath, mPaint);
|
||||||
|
@ -190,8 +200,6 @@ public class ShelfScrimView extends ScrimView {
|
||||||
}
|
}
|
||||||
|
|
||||||
mPaint.setColor(mShelfColor);
|
mPaint.setColor(mShelfColor);
|
||||||
canvas.drawRoundRect(0, top, getWidth(), getHeight() + mRadius,
|
canvas.drawRoundRect(0, mShelfTop, width, height + mRadius, mRadius, mRadius, mPaint);
|
||||||
mRadius, mRadius, mPaint);
|
|
||||||
return minTop - mDragHandleSize - top;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.animation.Interpolator;
|
||||||
|
|
||||||
import com.android.launcher3.config.FeatureFlags;
|
import com.android.launcher3.config.FeatureFlags;
|
||||||
|
|
||||||
|
@ -281,13 +282,14 @@ public final class Utilities {
|
||||||
* @param toMax The upper bound of the range that t is being mapped to.
|
* @param toMax The upper bound of the range that t is being mapped to.
|
||||||
* @return The mapped value of t.
|
* @return The mapped value of t.
|
||||||
*/
|
*/
|
||||||
public static float mapToRange(float t, float fromMin, float fromMax, float toMin, float toMax) {
|
public static float mapToRange(float t, float fromMin, float fromMax, float toMin, float toMax,
|
||||||
|
Interpolator interpolator) {
|
||||||
if (fromMin == fromMax || toMin == toMax) {
|
if (fromMin == fromMax || toMin == toMax) {
|
||||||
Log.e(TAG, "mapToRange: range has 0 length");
|
Log.e(TAG, "mapToRange: range has 0 length");
|
||||||
return toMin;
|
return toMin;
|
||||||
}
|
}
|
||||||
float progress = Math.abs(t - fromMin) / Math.abs(fromMax - fromMin);
|
float progress = Math.abs(t - fromMin) / Math.abs(fromMax - fromMin);
|
||||||
return mapRange(progress, toMin, toMax);
|
return mapRange(interpolator.getInterpolation(progress), toMin, toMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float mapRange(float value, float min, float max) {
|
public static float mapRange(float value, float min, float max) {
|
||||||
|
|
|
@ -158,7 +158,6 @@ public class Interpolators {
|
||||||
*/
|
*/
|
||||||
public static Interpolator mapToProgress(Interpolator interpolator, float lowerBound,
|
public static Interpolator mapToProgress(Interpolator interpolator, float lowerBound,
|
||||||
float upperBound) {
|
float upperBound) {
|
||||||
return t -> Utilities.mapToRange(interpolator.getInterpolation(t), 0, 1,
|
return t -> Utilities.mapRange(interpolator.getInterpolation(t), lowerBound, upperBound);
|
||||||
lowerBound, upperBound);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -109,6 +109,7 @@ public class ScrimView extends View implements Insettable, OnChangeListener,
|
||||||
protected int mEndFlatColorAlpha;
|
protected int mEndFlatColorAlpha;
|
||||||
|
|
||||||
protected final int mDragHandleSize;
|
protected final int mDragHandleSize;
|
||||||
|
protected float mDragHandleOffset;
|
||||||
private final Rect mDragHandleBounds;
|
private final Rect mDragHandleBounds;
|
||||||
private final RectF mHitRect = new RectF();
|
private final RectF mHitRect = new RectF();
|
||||||
|
|
||||||
|
@ -223,8 +224,14 @@ public class ScrimView extends View implements Insettable, OnChangeListener,
|
||||||
if (mCurrentFlatColor != 0) {
|
if (mCurrentFlatColor != 0) {
|
||||||
canvas.drawColor(mCurrentFlatColor);
|
canvas.drawColor(mCurrentFlatColor);
|
||||||
}
|
}
|
||||||
|
drawDragHandle(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void drawDragHandle(Canvas canvas) {
|
||||||
if (mDragHandle != null) {
|
if (mDragHandle != null) {
|
||||||
|
canvas.translate(0, -mDragHandleOffset);
|
||||||
mDragHandle.draw(canvas);
|
mDragHandle.draw(canvas);
|
||||||
|
canvas.translate(0, mDragHandleOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,20 +244,23 @@ public class ScrimView extends View implements Insettable, OnChangeListener,
|
||||||
|
|
||||||
final Drawable drawable = mDragHandle;
|
final Drawable drawable = mDragHandle;
|
||||||
mDragHandle = null;
|
mDragHandle = null;
|
||||||
drawable.setBounds(mDragHandleBounds);
|
|
||||||
|
|
||||||
Rect topBounds = new Rect(mDragHandleBounds);
|
Rect bounds = new Rect(mDragHandleBounds);
|
||||||
topBounds.offset(0, -mDragHandleBounds.height() / 2);
|
bounds.offset(0, -(int) mDragHandleOffset);
|
||||||
|
drawable.setBounds(bounds);
|
||||||
|
|
||||||
Rect invalidateRegion = new Rect(mDragHandleBounds);
|
Rect topBounds = new Rect(bounds);
|
||||||
|
topBounds.offset(0, -bounds.height() / 2);
|
||||||
|
|
||||||
|
Rect invalidateRegion = new Rect(bounds);
|
||||||
invalidateRegion.top = topBounds.top;
|
invalidateRegion.top = topBounds.top;
|
||||||
|
|
||||||
Keyframe frameTop = Keyframe.ofObject(0.6f, topBounds);
|
Keyframe frameTop = Keyframe.ofObject(0.6f, topBounds);
|
||||||
frameTop.setInterpolator(DEACCEL);
|
frameTop.setInterpolator(DEACCEL);
|
||||||
Keyframe frameBot = Keyframe.ofObject(1, mDragHandleBounds);
|
Keyframe frameBot = Keyframe.ofObject(1, bounds);
|
||||||
frameBot.setInterpolator(ACCEL);
|
frameBot.setInterpolator(ACCEL);
|
||||||
PropertyValuesHolder holder = PropertyValuesHolder .ofKeyframe("bounds",
|
PropertyValuesHolder holder = PropertyValuesHolder .ofKeyframe("bounds",
|
||||||
Keyframe.ofObject(0, mDragHandleBounds), frameTop, frameBot);
|
Keyframe.ofObject(0, bounds), frameTop, frameBot);
|
||||||
holder.setEvaluator(new RectEvaluator());
|
holder.setEvaluator(new RectEvaluator());
|
||||||
|
|
||||||
ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(drawable, holder);
|
ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(drawable, holder);
|
||||||
|
|
Loading…
Reference in New Issue