Merge "Improved the behavior of overscroll" into sc-dev am: 2b10a16208
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14807585 Change-Id: Ie0b9a88a15384863e68ac34c2fdbe2d99fb1285b
This commit is contained in:
@@ -311,6 +311,13 @@ public class FlingAnimationUtils {
|
|||||||
return mMinVelocityPxPerSecond;
|
return mMinVelocityPxPerSecond;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a velocity considered fast
|
||||||
|
*/
|
||||||
|
public float getHighVelocityPxPerSecond() {
|
||||||
|
return mHighVelocityPxPerSecond;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interpolator which interpolates two interpolators with an interpolator.
|
* An interpolator which interpolates two interpolators with an interpolator.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -93,6 +93,16 @@ public class Interpolators {
|
|||||||
(float) (1.0f - Math.exp(-b * progress)) * (overshootAmount + 1.0f));
|
(float) (1.0f - Math.exp(-b * progress)) * (overshootAmount + 1.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to {@link #getOvershootInterpolation(float, float, float)} but the overshoot
|
||||||
|
* starts immediately here, instead of first having a section of non-overshooting
|
||||||
|
*
|
||||||
|
* @param progress a progress value going from 0 to 1
|
||||||
|
*/
|
||||||
|
public static float getOvershootInterpolation(float progress) {
|
||||||
|
return MathUtils.max(0.0f, (float) (1.0f - Math.exp(-4 * progress)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interpolate alpha for notifications background scrim during shade expansion.
|
* Interpolate alpha for notifications background scrim during shade expansion.
|
||||||
* @param fraction Shade expansion fraction
|
* @param fraction Shade expansion fraction
|
||||||
|
|||||||
@@ -771,6 +771,9 @@
|
|||||||
<!-- Move distance for the unlock hint animation on the lockscreen -->
|
<!-- Move distance for the unlock hint animation on the lockscreen -->
|
||||||
<dimen name="hint_move_distance">75dp</dimen>
|
<dimen name="hint_move_distance">75dp</dimen>
|
||||||
|
|
||||||
|
<!-- The overshoot amount when the panel flings open -->
|
||||||
|
<dimen name="panel_overshoot_amount">16dp</dimen>
|
||||||
|
|
||||||
<!-- The width of the region on the left/right edge of the screen for performing the camera/
|
<!-- The width of the region on the left/right edge of the screen for performing the camera/
|
||||||
phone hints. -->
|
phone hints. -->
|
||||||
<dimen name="edge_tap_area_width">48dp</dimen>
|
<dimen name="edge_tap_area_width">48dp</dimen>
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ public class AmbientState {
|
|||||||
private ExpandableNotificationRow mTrackedHeadsUpRow;
|
private ExpandableNotificationRow mTrackedHeadsUpRow;
|
||||||
private float mAppearFraction;
|
private float mAppearFraction;
|
||||||
private boolean mIsShadeOpening;
|
private boolean mIsShadeOpening;
|
||||||
private float mSectionPadding;
|
private float mOverExpansion;
|
||||||
|
|
||||||
/** Distance of top of notifications panel from top of screen. */
|
/** Distance of top of notifications panel from top of screen. */
|
||||||
private float mStackY = 0;
|
private float mStackY = 0;
|
||||||
@@ -182,12 +182,12 @@ public class AmbientState {
|
|||||||
return mIsShadeOpening;
|
return mIsShadeOpening;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSectionPadding(float padding) {
|
void setOverExpansion(float overExpansion) {
|
||||||
mSectionPadding = padding;
|
mOverExpansion = overExpansion;
|
||||||
}
|
}
|
||||||
|
|
||||||
float getSectionPadding() {
|
float getOverExpansion() {
|
||||||
return mSectionPadding;
|
return mOverExpansion;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getZDistanceBetweenElements(Context context) {
|
private static int getZDistanceBetweenElements(Context context) {
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ import java.util.Comparator;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
@@ -470,6 +471,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private Consumer<Integer> mScrollListener;
|
||||||
private final ScrollAdapter mScrollAdapter = new ScrollAdapter() {
|
private final ScrollAdapter mScrollAdapter = new ScrollAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public boolean isScrolledToTop() {
|
public boolean isScrolledToTop() {
|
||||||
@@ -552,8 +554,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSectionPadding(float margin) {
|
/**
|
||||||
mAmbientState.setSectionPadding(margin);
|
* Set the overexpansion of the panel to be applied to the view.
|
||||||
|
*/
|
||||||
|
void setOverExpansion(float margin) {
|
||||||
|
mAmbientState.setOverExpansion(margin);
|
||||||
|
updateStackPosition();
|
||||||
requestChildrenUpdate();
|
requestChildrenUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1136,7 +1142,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
*/
|
*/
|
||||||
private void updateStackPosition() {
|
private void updateStackPosition() {
|
||||||
// Consider interpolating from an mExpansionStartY for use on lockscreen and AOD
|
// Consider interpolating from an mExpansionStartY for use on lockscreen and AOD
|
||||||
float endTopPosition = mTopPadding + mExtraTopInsetForFullShadeTransition;
|
float endTopPosition = mTopPadding + mExtraTopInsetForFullShadeTransition
|
||||||
|
+ mAmbientState.getOverExpansion();
|
||||||
final float fraction = mAmbientState.getExpansionFraction();
|
final float fraction = mAmbientState.getExpansionFraction();
|
||||||
final float stackY = MathUtils.lerp(0, endTopPosition, fraction);
|
final float stackY = MathUtils.lerp(0, endTopPosition, fraction);
|
||||||
mAmbientState.setStackY(stackY);
|
mAmbientState.setStackY(stackY);
|
||||||
@@ -1144,7 +1151,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
mOnStackYChanged.run();
|
mOnStackYChanged.run();
|
||||||
}
|
}
|
||||||
if (mQsExpansionFraction <= 0) {
|
if (mQsExpansionFraction <= 0) {
|
||||||
final float scrimTopPadding = mAmbientState.isOnKeyguard() ? 0 : mSidePaddings;
|
|
||||||
final float stackEndHeight = Math.max(0f,
|
final float stackEndHeight = Math.max(0f,
|
||||||
getHeight() - getEmptyBottomMargin() - mTopPadding);
|
getHeight() - getEmptyBottomMargin() - mTopPadding);
|
||||||
mAmbientState.setStackEndHeight(stackEndHeight);
|
mAmbientState.setStackEndHeight(stackEndHeight);
|
||||||
@@ -1166,7 +1172,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
|
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
|
||||||
public void setExpandedHeight(float height) {
|
public void setExpandedHeight(float height) {
|
||||||
final float shadeBottom = getHeight() - getEmptyBottomMargin();
|
final float shadeBottom = getHeight() - getEmptyBottomMargin();
|
||||||
final float expansionFraction = MathUtils.constrain(height / shadeBottom, 0f, 1f);
|
final float expansionFraction = MathUtils.saturate(height / shadeBottom);
|
||||||
mAmbientState.setExpansionFraction(expansionFraction);
|
mAmbientState.setExpansionFraction(expansionFraction);
|
||||||
updateStackPosition();
|
updateStackPosition();
|
||||||
|
|
||||||
@@ -2395,8 +2401,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
float topOverScroll = getCurrentOverScrollAmount(true);
|
float topOverScroll = getCurrentOverScrollAmount(true);
|
||||||
return mScrolledToTopOnFirstDown
|
return mScrolledToTopOnFirstDown
|
||||||
&& !mExpandedInThisMotion
|
&& !mExpandedInThisMotion
|
||||||
&& topOverScroll > mMinTopOverScrollToEscape
|
&& (initialVelocity > mMinimumVelocity
|
||||||
&& initialVelocity > 0;
|
|| (topOverScroll > mMinTopOverScrollToEscape && initialVelocity > 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -4552,6 +4558,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateOnScrollChange() {
|
private void updateOnScrollChange() {
|
||||||
|
if (mScrollListener != null) {
|
||||||
|
mScrollListener.accept(mOwnScrollY);
|
||||||
|
}
|
||||||
updateForwardAndBackwardScrollability();
|
updateForwardAndBackwardScrollability();
|
||||||
requestChildrenUpdate();
|
requestChildrenUpdate();
|
||||||
}
|
}
|
||||||
@@ -5162,6 +5171,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
requestChildrenUpdate();
|
requestChildrenUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a listener to when scrolling changes.
|
||||||
|
*/
|
||||||
|
public void setOnScrollListener(Consumer<Integer> listener) {
|
||||||
|
mScrollListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A listener that is notified when the empty space below the notifications is clicked on
|
* A listener that is notified when the empty space below the notifications is clicked on
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ import com.android.systemui.tuner.TunerService;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
@@ -302,8 +303,11 @@ public class NotificationStackScrollLayoutController {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public void setSectionPadding(float padding) {
|
/**
|
||||||
mView.setSectionPadding(padding);
|
* Set the overexpansion of the panel to be applied to the view.
|
||||||
|
*/
|
||||||
|
public void setOverExpansion(float overExpansion) {
|
||||||
|
mView.setOverExpansion(overExpansion);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final OnMenuEventListener mMenuEventListener = new OnMenuEventListener() {
|
private final OnMenuEventListener mMenuEventListener = new OnMenuEventListener() {
|
||||||
@@ -944,10 +948,6 @@ public class NotificationStackScrollLayoutController {
|
|||||||
mView.setOverScrollAmount(amount, onTop, animate);
|
mView.setOverScrollAmount(amount, onTop, animate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOverScrolledPixels(float numPixels, boolean onTop, boolean animate) {
|
|
||||||
mView.setOverScrolledPixels(numPixels, onTop, animate);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void resetScrollPosition() {
|
public void resetScrollPosition() {
|
||||||
mView.resetScrollPosition();
|
mView.resetScrollPosition();
|
||||||
}
|
}
|
||||||
@@ -1054,10 +1054,6 @@ public class NotificationStackScrollLayoutController {
|
|||||||
return mView.getCurrentOverScrollAmount(top);
|
return mView.getCurrentOverScrollAmount(top);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getCurrentOverScrolledPixels(boolean top) {
|
|
||||||
return mView.getCurrentOverScrolledPixels(top);
|
|
||||||
}
|
|
||||||
|
|
||||||
public float calculateAppearFraction(float height) {
|
public float calculateAppearFraction(float height) {
|
||||||
return mView.calculateAppearFraction(height);
|
return mView.calculateAppearFraction(height);
|
||||||
}
|
}
|
||||||
@@ -1430,6 +1426,13 @@ public class NotificationStackScrollLayoutController {
|
|||||||
mView.setExtraTopInsetForFullShadeTransition(extraTopInset);
|
mView.setExtraTopInsetForFullShadeTransition(extraTopInset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a listener to when scrolling changes.
|
||||||
|
*/
|
||||||
|
public void setOnScrollListener(Consumer<Integer> listener) {
|
||||||
|
mView.setOnScrollListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enum for UiEvent logged from this class
|
* Enum for UiEvent logged from this class
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -403,10 +403,6 @@ public class StackScrollAlgorithm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewState.yTranslation = algorithmState.mCurrentYPosition;
|
viewState.yTranslation = algorithmState.mCurrentYPosition;
|
||||||
if (view instanceof SectionHeaderView) {
|
|
||||||
// Add padding before sections for overscroll effect.
|
|
||||||
viewState.yTranslation += expansionFraction * ambientState.getSectionPadding();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (view instanceof FooterView) {
|
if (view instanceof FooterView) {
|
||||||
final boolean shadeClosed = !ambientState.isShadeExpanded();
|
final boolean shadeClosed = !ambientState.isShadeExpanded();
|
||||||
|
|||||||
@@ -510,7 +510,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
private boolean mShowingKeyguardHeadsUp;
|
private boolean mShowingKeyguardHeadsUp;
|
||||||
private boolean mAllowExpandForSmallExpansion;
|
private boolean mAllowExpandForSmallExpansion;
|
||||||
private Runnable mExpandAfterLayoutRunnable;
|
private Runnable mExpandAfterLayoutRunnable;
|
||||||
private float mSectionPadding;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The padding between the start of notifications and the qs boundary on the lockscreen.
|
* The padding between the start of notifications and the qs boundary on the lockscreen.
|
||||||
@@ -589,7 +588,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
private NotificationShelfController mNotificationShelfController;
|
private NotificationShelfController mNotificationShelfController;
|
||||||
private int mScrimCornerRadius;
|
private int mScrimCornerRadius;
|
||||||
private int mScreenCornerRadius;
|
private int mScreenCornerRadius;
|
||||||
private int mNotificationScrimPadding;
|
|
||||||
private boolean mQSAnimatingHiddenFromCollapsed;
|
private boolean mQSAnimatingHiddenFromCollapsed;
|
||||||
|
|
||||||
private final Executor mUiExecutor;
|
private final Executor mUiExecutor;
|
||||||
@@ -824,6 +822,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
mOnHeightChangedListener);
|
mOnHeightChangedListener);
|
||||||
mNotificationStackScrollLayoutController.setOverscrollTopChangedListener(
|
mNotificationStackScrollLayoutController.setOverscrollTopChangedListener(
|
||||||
mOnOverscrollTopChangedListener);
|
mOnOverscrollTopChangedListener);
|
||||||
|
mNotificationStackScrollLayoutController.setOnScrollListener(this::onNotificationScrolled);
|
||||||
mNotificationStackScrollLayoutController.setOnEmptySpaceClickListener(
|
mNotificationStackScrollLayoutController.setOnEmptySpaceClickListener(
|
||||||
mOnEmptySpaceClickListener);
|
mOnEmptySpaceClickListener);
|
||||||
addTrackingHeadsUpListener(mNotificationStackScrollLayoutController::setTrackingHeadsUp);
|
addTrackingHeadsUpListener(mNotificationStackScrollLayoutController::setTrackingHeadsUp);
|
||||||
@@ -908,8 +907,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
mScrimCornerRadius = mResources.getDimensionPixelSize(
|
mScrimCornerRadius = mResources.getDimensionPixelSize(
|
||||||
R.dimen.notification_scrim_corner_radius);
|
R.dimen.notification_scrim_corner_radius);
|
||||||
mScreenCornerRadius = (int) ScreenDecorationsUtils.getWindowCornerRadius(mResources);
|
mScreenCornerRadius = (int) ScreenDecorationsUtils.getWindowCornerRadius(mResources);
|
||||||
mNotificationScrimPadding = mResources.getDimensionPixelSize(
|
|
||||||
R.dimen.notification_side_paddings);
|
|
||||||
mLockscreenNotificationQSPadding = mResources.getDimensionPixelSize(
|
mLockscreenNotificationQSPadding = mResources.getDimensionPixelSize(
|
||||||
R.dimen.notification_side_paddings);
|
R.dimen.notification_side_paddings);
|
||||||
}
|
}
|
||||||
@@ -2190,6 +2187,22 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private void onNotificationScrolled(int newScrollPosition) {
|
||||||
|
// Since this is an overscroller, sometimes the scrollY can be temporarily negative
|
||||||
|
// (when overscrollng on the top and flinging). Let's
|
||||||
|
updateQSExpansionEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setIsShadeOpening(boolean opening) {
|
||||||
|
mAmbientState.setIsShadeOpening(opening);
|
||||||
|
updateQSExpansionEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateQSExpansionEnabled() {
|
||||||
|
setQsExpansionEnabled(mAmbientState.getScrollY() <= 0 && !mAmbientState.isShadeOpening());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates scrim bounds, QS clipping, and KSV clipping as well based on the bounds of the shade
|
* Updates scrim bounds, QS clipping, and KSV clipping as well based on the bounds of the shade
|
||||||
* and QS state.
|
* and QS state.
|
||||||
@@ -2203,7 +2216,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
final int qsPanelBottomY = calculateQsBottomPosition(computeQsExpansionFraction());
|
final int qsPanelBottomY = calculateQsBottomPosition(computeQsExpansionFraction());
|
||||||
final boolean visible = (computeQsExpansionFraction() > 0 || qsPanelBottomY > 0)
|
final boolean visible = (computeQsExpansionFraction() > 0 || qsPanelBottomY > 0)
|
||||||
&& !mShouldUseSplitNotificationShade;
|
&& !mShouldUseSplitNotificationShade;
|
||||||
setQsExpansionEnabled(mAmbientState.getScrollY() == 0 && !mAmbientState.isShadeOpening());
|
|
||||||
|
|
||||||
if (!mShouldUseSplitNotificationShade) {
|
if (!mShouldUseSplitNotificationShade) {
|
||||||
if (mTransitioningToFullShadeProgress > 0.0f) {
|
if (mTransitioningToFullShadeProgress > 0.0f) {
|
||||||
@@ -2315,8 +2327,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
qsBottomY = (int) MathUtils.lerp(
|
qsBottomY = (int) MathUtils.lerp(
|
||||||
qsBottomY, mQs.getDesiredHeight(), qsExpansionFraction);
|
qsBottomY, mQs.getDesiredHeight(), qsExpansionFraction);
|
||||||
}
|
}
|
||||||
// to account for shade overshooting animation, see setSectionPadding method
|
|
||||||
if (mSectionPadding > 0) qsBottomY += mSectionPadding;
|
|
||||||
return qsBottomY;
|
return qsBottomY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2632,7 +2642,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
int min = mStatusBarMinHeight;
|
int min = mStatusBarMinHeight;
|
||||||
if (!(mBarState == KEYGUARD)
|
if (!(mBarState == KEYGUARD)
|
||||||
&& mNotificationStackScrollLayoutController.getNotGoneChildCount() == 0) {
|
&& mNotificationStackScrollLayoutController.getNotGoneChildCount() == 0) {
|
||||||
int minHeight = (int) (mQsMinExpansionHeight + getOverExpansionAmount());
|
int minHeight = mQsMinExpansionHeight;
|
||||||
min = Math.max(min, minHeight);
|
min = Math.max(min, minHeight);
|
||||||
}
|
}
|
||||||
int maxHeight;
|
int maxHeight;
|
||||||
@@ -2644,8 +2654,8 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
}
|
}
|
||||||
maxHeight = Math.max(min, maxHeight);
|
maxHeight = Math.max(min, maxHeight);
|
||||||
if (maxHeight == 0 || isNaN(maxHeight)) {
|
if (maxHeight == 0 || isNaN(maxHeight)) {
|
||||||
Log.wtf(TAG, "maxPanelHeight is invalid. getOverExpansionAmount(): "
|
Log.wtf(TAG, "maxPanelHeight is invalid. mOverExpansion: "
|
||||||
+ getOverExpansionAmount() + ", calculatePanelHeightQsExpanded: "
|
+ mOverExpansion + ", calculatePanelHeightQsExpanded: "
|
||||||
+ calculatePanelHeightQsExpanded() + ", calculatePanelHeightShade: "
|
+ calculatePanelHeightQsExpanded() + ", calculatePanelHeightShade: "
|
||||||
+ calculatePanelHeightShade() + ", mStatusBarMinHeight = "
|
+ calculatePanelHeightShade() + ", mStatusBarMinHeight = "
|
||||||
+ mStatusBarMinHeight + ", mQsMinExpansionHeight = " + mQsMinExpansionHeight);
|
+ mStatusBarMinHeight + ", mQsMinExpansionHeight = " + mQsMinExpansionHeight);
|
||||||
@@ -2807,23 +2817,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
return alpha;
|
return alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected float getOverExpansionAmount() {
|
|
||||||
float result = mNotificationStackScrollLayoutController
|
|
||||||
.getCurrentOverScrollAmount(true /* top */);
|
|
||||||
if (isNaN(result)) {
|
|
||||||
Log.wtf(TAG, "OverExpansionAmount is NaN!");
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected float getOverExpansionPixels() {
|
|
||||||
return mNotificationStackScrollLayoutController
|
|
||||||
.getCurrentOverScrolledPixels(true /* top */);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hides the header when notifications are colliding with it.
|
* Hides the header when notifications are colliding with it.
|
||||||
*/
|
*/
|
||||||
@@ -3018,31 +3011,15 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSectionPadding(float padding) {
|
public void setOverExpansion(float overExpansion) {
|
||||||
if (padding == mSectionPadding) {
|
if (overExpansion == mOverExpansion) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mSectionPadding = padding;
|
super.setOverExpansion(overExpansion);
|
||||||
// TODO(b/172289889) update overscroll to spec
|
// Translating the quick settings by half the overexpansion to center it in the background
|
||||||
}
|
// frame
|
||||||
|
mQsFrame.setTranslationY(overExpansion / 2f);
|
||||||
@Override
|
mNotificationStackScrollLayoutController.setOverExpansion(overExpansion);
|
||||||
protected void setOverExpansion(float overExpansion, boolean isPixels) {
|
|
||||||
if (mConflictingQsExpansionGesture || mQsExpandImmediate) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mBarState != KEYGUARD) {
|
|
||||||
mNotificationStackScrollLayoutController.setOnHeightChangedListener(null);
|
|
||||||
if (isPixels) {
|
|
||||||
mNotificationStackScrollLayoutController.setOverScrolledPixels(
|
|
||||||
overExpansion, true /* onTop */, false /* animate */);
|
|
||||||
} else {
|
|
||||||
mNotificationStackScrollLayoutController.setOverScrollAmount(
|
|
||||||
overExpansion, true /* onTop */, false /* animate */);
|
|
||||||
}
|
|
||||||
mNotificationStackScrollLayoutController
|
|
||||||
.setOnHeightChangedListener(mOnHeightChangedListener);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -3066,7 +3043,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
mFalsingCollector.onTrackingStopped();
|
mFalsingCollector.onTrackingStopped();
|
||||||
super.onTrackingStopped(expand);
|
super.onTrackingStopped(expand);
|
||||||
if (expand) {
|
if (expand) {
|
||||||
mNotificationStackScrollLayoutController.setOverScrolledPixels(0.0f, true /* onTop */,
|
mNotificationStackScrollLayoutController.setOverScrollAmount(0.0f, true /* onTop */,
|
||||||
true /* animate */);
|
true /* animate */);
|
||||||
}
|
}
|
||||||
mNotificationStackScrollLayoutController.onPanelTrackingStopped();
|
mNotificationStackScrollLayoutController.onPanelTrackingStopped();
|
||||||
@@ -3111,18 +3088,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
|| !isTracking());
|
|| !isTracking());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean fullyExpandedClearAllVisible() {
|
|
||||||
return mNotificationStackScrollLayoutController.isFooterViewNotGone()
|
|
||||||
&& mNotificationStackScrollLayoutController.isScrolledToBottom()
|
|
||||||
&& !mQsExpandImmediate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isClearAllVisible() {
|
|
||||||
return mNotificationStackScrollLayoutController.isFooterViewContentVisible();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isTrackingBlocked() {
|
protected boolean isTrackingBlocked() {
|
||||||
return mConflictingQsExpansionGesture && mQsExpanded || mBlockingExpansionForCurrentTouch;
|
return mConflictingQsExpansionGesture && mQsExpanded || mBlockingExpansionForCurrentTouch;
|
||||||
@@ -3973,10 +3938,15 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
}
|
}
|
||||||
mLastOverscroll = 0f;
|
mLastOverscroll = 0f;
|
||||||
mQsExpansionFromOverscroll = false;
|
mQsExpansionFromOverscroll = false;
|
||||||
|
if (open) {
|
||||||
|
// During overscrolling, qsExpansion doesn't actually change that the qs is
|
||||||
|
// becoming expanded. Any layout could therefore reset the position again. Let's
|
||||||
|
// make sure we can expand
|
||||||
|
setOverScrolling(false);
|
||||||
|
}
|
||||||
setQsExpansion(mQsExpansionHeight);
|
setQsExpansion(mQsExpansionHeight);
|
||||||
flingSettings(!mQsExpansionEnabled && open ? 0f : velocity,
|
flingSettings(!mQsExpansionEnabled && open ? 0f : velocity,
|
||||||
open && mQsExpansionEnabled ? FLING_EXPAND : FLING_COLLAPSE, () -> {
|
open && mQsExpansionEnabled ? FLING_EXPAND : FLING_COLLAPSE, () -> {
|
||||||
mStackScrollerOverscrolling = false;
|
|
||||||
setOverScrolling(false);
|
setOverScrolling(false);
|
||||||
updateQsState();
|
updateQsState();
|
||||||
}, false /* isClick */);
|
}, false /* isClick */);
|
||||||
@@ -4392,7 +4362,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
if (mQsMaxExpansionHeight != oldMaxHeight) {
|
if (mQsMaxExpansionHeight != oldMaxHeight) {
|
||||||
startQsSizeChangeAnimation(oldMaxHeight, mQsMaxExpansionHeight);
|
startQsSizeChangeAnimation(oldMaxHeight, mQsMaxExpansionHeight);
|
||||||
}
|
}
|
||||||
} else if (!mQsExpanded) {
|
} else if (!mQsExpanded && mQsExpansionAnimator == null) {
|
||||||
setQsExpansion(mQsMinExpansionHeight + mLastOverscroll);
|
setQsExpansion(mQsMinExpansionHeight + mLastOverscroll);
|
||||||
}
|
}
|
||||||
updateExpandedHeight(getExpandedHeight());
|
updateExpandedHeight(getExpandedHeight());
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public abstract class PanelBar extends FrameLayout {
|
|||||||
if (DEBUG) LOG("go state: %d -> %d", mState, state);
|
if (DEBUG) LOG("go state: %d -> %d", mState, state);
|
||||||
mState = state;
|
mState = state;
|
||||||
if (mPanel != null) {
|
if (mPanel != null) {
|
||||||
mPanel.getAmbientState().setIsShadeOpening(state == STATE_OPENING);
|
mPanel.setIsShadeOpening(state == STATE_OPENING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,12 +68,14 @@ public abstract class PanelViewController {
|
|||||||
public static final String TAG = PanelView.class.getSimpleName();
|
public static final String TAG = PanelView.class.getSimpleName();
|
||||||
private static final int NO_FIXED_DURATION = -1;
|
private static final int NO_FIXED_DURATION = -1;
|
||||||
private static final long SHADE_OPEN_SPRING_OUT_DURATION = 350L;
|
private static final long SHADE_OPEN_SPRING_OUT_DURATION = 350L;
|
||||||
private static final long SHADE_OPEN_SPRING_BACK_DURATION = 200L;
|
private static final long SHADE_OPEN_SPRING_BACK_DURATION = 400L;
|
||||||
private static final float MIN_OVERSCROLL = -50;
|
|
||||||
private static final float MAX_OVERSCROLL = 30;
|
/**
|
||||||
|
* The factor of the usual high velocity that is needed in order to reach the maximum overshoot
|
||||||
|
* when flinging. A low value will make it that most flings will reach the maximum overshoot.
|
||||||
|
*/
|
||||||
|
private static final float FACTOR_OF_HIGH_VELOCITY_FOR_MAX_OVERSHOOT = 0.5f;
|
||||||
|
|
||||||
private float mFlingTarget;
|
|
||||||
private float mFlingVelocity;
|
|
||||||
protected long mDownTime;
|
protected long mDownTime;
|
||||||
protected boolean mTouchSlopExceededBeforeDown;
|
protected boolean mTouchSlopExceededBeforeDown;
|
||||||
private float mMinExpandHeight;
|
private float mMinExpandHeight;
|
||||||
@@ -83,6 +85,22 @@ public abstract class PanelViewController {
|
|||||||
protected boolean mIsLaunchAnimationRunning;
|
protected boolean mIsLaunchAnimationRunning;
|
||||||
private int mFixedDuration = NO_FIXED_DURATION;
|
private int mFixedDuration = NO_FIXED_DURATION;
|
||||||
protected ArrayList<PanelExpansionListener> mExpansionListeners = new ArrayList<>();
|
protected ArrayList<PanelExpansionListener> mExpansionListeners = new ArrayList<>();
|
||||||
|
protected float mOverExpansion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The overshoot amount when the panel flings open
|
||||||
|
*/
|
||||||
|
private float mPanelFlingOvershootAmount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The amount of pixels that we have overexpanded the last time with a gesture
|
||||||
|
*/
|
||||||
|
private float mLastGesturedOverExpansion = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the current animator the spring back animation?
|
||||||
|
*/
|
||||||
|
private boolean mIsSpringBackAnimation;
|
||||||
|
|
||||||
private void logf(String fmt, Object... args) {
|
private void logf(String fmt, Object... args) {
|
||||||
Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
|
Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
|
||||||
@@ -254,6 +272,7 @@ public abstract class PanelViewController {
|
|||||||
mTouchSlop = configuration.getScaledTouchSlop();
|
mTouchSlop = configuration.getScaledTouchSlop();
|
||||||
mSlopMultiplier = configuration.getScaledAmbiguousGestureMultiplier();
|
mSlopMultiplier = configuration.getScaledAmbiguousGestureMultiplier();
|
||||||
mHintDistance = mResources.getDimension(R.dimen.hint_move_distance);
|
mHintDistance = mResources.getDimension(R.dimen.hint_move_distance);
|
||||||
|
mPanelFlingOvershootAmount = mResources.getDimension(R.dimen.panel_overshoot_amount);
|
||||||
mUnlockFalsingThreshold = mResources.getDimensionPixelSize(
|
mUnlockFalsingThreshold = mResources.getDimensionPixelSize(
|
||||||
R.dimen.unlock_falsing_threshold);
|
R.dimen.unlock_falsing_threshold);
|
||||||
}
|
}
|
||||||
@@ -529,21 +548,38 @@ public abstract class PanelViewController {
|
|||||||
|
|
||||||
protected void flingToHeight(float vel, boolean expand, float target,
|
protected void flingToHeight(float vel, boolean expand, float target,
|
||||||
float collapseSpeedUpFactor, boolean expandBecauseOfFalsing) {
|
float collapseSpeedUpFactor, boolean expandBecauseOfFalsing) {
|
||||||
if (target == mExpandedHeight || getOverExpansionAmount() > 0f && expand) {
|
if (target == mExpandedHeight && mOverExpansion == 0.0f) {
|
||||||
|
// We're at the target and didn't fling and there's no overshoot
|
||||||
endJankMonitoring(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
|
endJankMonitoring(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
|
||||||
mKeyguardStateController.notifyPanelFlingEnd();
|
mKeyguardStateController.notifyPanelFlingEnd();
|
||||||
notifyExpandingFinished();
|
notifyExpandingFinished();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mIsFlinging = true;
|
mIsFlinging = true;
|
||||||
mOverExpandedBeforeFling = getOverExpansionAmount() > 0f;
|
// we want to perform an overshoot animation when flinging open
|
||||||
ValueAnimator animator = createHeightAnimator(target);
|
final boolean addOverscroll = expand
|
||||||
mFlingTarget = target;
|
&& mStatusBarStateController.getState() != StatusBarState.KEYGUARD
|
||||||
|
&& mOverExpansion == 0.0f
|
||||||
|
&& vel >= 0;
|
||||||
|
final boolean shouldSpringBack = addOverscroll || (mOverExpansion != 0.0f && expand);
|
||||||
|
float overshootAmount = 0.0f;
|
||||||
|
if (addOverscroll) {
|
||||||
|
// Let's overshoot depending on the amount of velocity
|
||||||
|
overshootAmount = MathUtils.lerp(
|
||||||
|
0.2f,
|
||||||
|
1.0f,
|
||||||
|
MathUtils.saturate(vel
|
||||||
|
/ (mFlingAnimationUtils.getHighVelocityPxPerSecond()
|
||||||
|
* FACTOR_OF_HIGH_VELOCITY_FOR_MAX_OVERSHOOT)));
|
||||||
|
overshootAmount += mOverExpansion / mPanelFlingOvershootAmount;
|
||||||
|
}
|
||||||
|
ValueAnimator animator = createHeightAnimator(target, overshootAmount);
|
||||||
if (expand) {
|
if (expand) {
|
||||||
if (expandBecauseOfFalsing && vel < 0) {
|
if (expandBecauseOfFalsing && vel < 0) {
|
||||||
vel = 0;
|
vel = 0;
|
||||||
}
|
}
|
||||||
mFlingAnimationUtils.apply(animator, mExpandedHeight, target, vel, mView.getHeight());
|
mFlingAnimationUtils.apply(animator, mExpandedHeight,
|
||||||
|
target + overshootAmount * mPanelFlingOvershootAmount, vel, mView.getHeight());
|
||||||
if (vel == 0) {
|
if (vel == 0) {
|
||||||
animator.setDuration(SHADE_OPEN_SPRING_OUT_DURATION);
|
animator.setDuration(SHADE_OPEN_SPRING_OUT_DURATION);
|
||||||
}
|
}
|
||||||
@@ -570,7 +606,6 @@ public abstract class PanelViewController {
|
|||||||
animator.setDuration(mFixedDuration);
|
animator.setDuration(mFixedDuration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mFlingVelocity = vel;
|
|
||||||
animator.addListener(new AnimatorListenerAdapter() {
|
animator.addListener(new AnimatorListenerAdapter() {
|
||||||
private boolean mCancelled;
|
private boolean mCancelled;
|
||||||
|
|
||||||
@@ -586,7 +621,7 @@ public abstract class PanelViewController {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
if (expand && mFlingVelocity > 0) {
|
if (shouldSpringBack && !mCancelled) {
|
||||||
// After the shade is flinged open to an overscrolled state, spring back
|
// After the shade is flinged open to an overscrolled state, spring back
|
||||||
// the shade by reducing section padding to 0.
|
// the shade by reducing section padding to 0.
|
||||||
springBack();
|
springBack();
|
||||||
@@ -600,14 +635,19 @@ public abstract class PanelViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void springBack() {
|
private void springBack() {
|
||||||
ValueAnimator animator = ValueAnimator.ofFloat(MAX_OVERSCROLL, 0);
|
if (mOverExpansion == 0) {
|
||||||
|
onFlingEnd(false /* cancelled */);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mIsSpringBackAnimation = true;
|
||||||
|
ValueAnimator animator = ValueAnimator.ofFloat(mOverExpansion, 0);
|
||||||
animator.addUpdateListener(
|
animator.addUpdateListener(
|
||||||
animation -> {
|
animation -> {
|
||||||
setSectionPadding((float) animation.getAnimatedValue());
|
setOverExpansionInternal((float) animation.getAnimatedValue(),
|
||||||
setExpandedHeightInternal(mFlingTarget);
|
false /* isFromGesture */);
|
||||||
});
|
});
|
||||||
animator.setDuration(SHADE_OPEN_SPRING_BACK_DURATION);
|
animator.setDuration(SHADE_OPEN_SPRING_BACK_DURATION);
|
||||||
animator.setInterpolator(Interpolators.LINEAR);
|
animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
|
||||||
animator.addListener(new AnimatorListenerAdapter() {
|
animator.addListener(new AnimatorListenerAdapter() {
|
||||||
private boolean mCancelled;
|
private boolean mCancelled;
|
||||||
@Override
|
@Override
|
||||||
@@ -616,6 +656,7 @@ public abstract class PanelViewController {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
mIsSpringBackAnimation = false;
|
||||||
onFlingEnd(mCancelled);
|
onFlingEnd(mCancelled);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -625,6 +666,8 @@ public abstract class PanelViewController {
|
|||||||
|
|
||||||
private void onFlingEnd(boolean cancelled) {
|
private void onFlingEnd(boolean cancelled) {
|
||||||
mIsFlinging = false;
|
mIsFlinging = false;
|
||||||
|
// No overshoot when the animation ends
|
||||||
|
setOverExpansionInternal(0, false /* isFromGesture */);
|
||||||
setAnimator(null);
|
setAnimator(null);
|
||||||
mKeyguardStateController.notifyPanelFlingEnd();
|
mKeyguardStateController.notifyPanelFlingEnd();
|
||||||
if (!cancelled) {
|
if (!cancelled) {
|
||||||
@@ -644,7 +687,7 @@ public abstract class PanelViewController {
|
|||||||
|
|
||||||
public void setExpandedHeight(float height) {
|
public void setExpandedHeight(float height) {
|
||||||
if (DEBUG) logf("setExpandedHeight(%.1f)", height);
|
if (DEBUG) logf("setExpandedHeight(%.1f)", height);
|
||||||
setExpandedHeightInternal(height + getOverExpansionPixels());
|
setExpandedHeightInternal(height);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void requestPanelHeightUpdate() {
|
protected void requestPanelHeightUpdate() {
|
||||||
@@ -662,7 +705,7 @@ public abstract class PanelViewController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mHeightAnimator != null) {
|
if (mHeightAnimator != null && !mIsSpringBackAnimation) {
|
||||||
mPanelUpdateWhenAnimatorEnds = true;
|
mPanelUpdateWhenAnimatorEnds = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -677,38 +720,24 @@ public abstract class PanelViewController {
|
|||||||
return stackHeightFraction;
|
return stackHeightFraction;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the shade is flinged open, add space before sections for overscroll effect.
|
|
||||||
private void maybeOverScrollForShadeFlingOpen(float height) {
|
|
||||||
if (!mBar.isShadeOpening() || mFlingVelocity <= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final float padding = MathUtils.lerp(
|
|
||||||
MIN_OVERSCROLL, MAX_OVERSCROLL, getStackHeightFraction(height));
|
|
||||||
setSectionPadding(padding);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExpandedHeightInternal(float h) {
|
public void setExpandedHeightInternal(float h) {
|
||||||
if (isNaN(h)) {
|
if (isNaN(h)) {
|
||||||
Log.wtf(TAG, "ExpandedHeight set to NaN");
|
Log.wtf(TAG, "ExpandedHeight set to NaN");
|
||||||
}
|
}
|
||||||
maybeOverScrollForShadeFlingOpen(h);
|
|
||||||
if (mExpandLatencyTracking && h != 0f) {
|
if (mExpandLatencyTracking && h != 0f) {
|
||||||
DejankUtils.postAfterTraversal(
|
DejankUtils.postAfterTraversal(
|
||||||
() -> mLatencyTracker.onActionEnd(LatencyTracker.ACTION_EXPAND_PANEL));
|
() -> mLatencyTracker.onActionEnd(LatencyTracker.ACTION_EXPAND_PANEL));
|
||||||
mExpandLatencyTracking = false;
|
mExpandLatencyTracking = false;
|
||||||
}
|
}
|
||||||
float fhWithoutOverExpansion = getMaxPanelHeight() - getOverExpansionAmount();
|
float maxPanelHeight = getMaxPanelHeight();
|
||||||
if (mHeightAnimator == null) {
|
if (mHeightAnimator == null) {
|
||||||
float overExpansionPixels = Math.max(0, h - fhWithoutOverExpansion);
|
if (mTracking) {
|
||||||
if (getOverExpansionPixels() != overExpansionPixels && mTracking) {
|
float overExpansionPixels = Math.max(0, h - maxPanelHeight);
|
||||||
setOverExpansion(overExpansionPixels, true /* isPixels */);
|
setOverExpansionInternal(overExpansionPixels, true /* isFromGesture */);
|
||||||
}
|
}
|
||||||
mExpandedHeight = Math.min(h, fhWithoutOverExpansion) + getOverExpansionAmount();
|
mExpandedHeight = Math.min(h, maxPanelHeight);
|
||||||
} else {
|
} else {
|
||||||
mExpandedHeight = h;
|
mExpandedHeight = h;
|
||||||
if (mOverExpandedBeforeFling) {
|
|
||||||
setOverExpansion(Math.max(0, h - fhWithoutOverExpansion), false /* isPixels */);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are closing the panel and we are almost there due to a slow decelerating
|
// If we are closing the panel and we are almost there due to a slow decelerating
|
||||||
@@ -720,7 +749,7 @@ public abstract class PanelViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mExpandedFraction = Math.min(1f,
|
mExpandedFraction = Math.min(1f,
|
||||||
fhWithoutOverExpansion == 0 ? 0 : mExpandedHeight / fhWithoutOverExpansion);
|
maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight);
|
||||||
onHeightUpdated(mExpandedHeight);
|
onHeightUpdated(mExpandedHeight);
|
||||||
notifyBarPanelExpansionChanged();
|
notifyBarPanelExpansionChanged();
|
||||||
}
|
}
|
||||||
@@ -731,16 +760,31 @@ public abstract class PanelViewController {
|
|||||||
*/
|
*/
|
||||||
protected abstract boolean isTrackingBlocked();
|
protected abstract boolean isTrackingBlocked();
|
||||||
|
|
||||||
protected abstract void setSectionPadding(float padding);
|
protected void setOverExpansion(float overExpansion) {
|
||||||
|
mOverExpansion = overExpansion;
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract void setOverExpansion(float overExpansion, boolean isPixels);
|
/**
|
||||||
|
* Set the current overexpansion
|
||||||
|
*
|
||||||
|
* @param overExpansion the amount of overexpansion to apply
|
||||||
|
* @param isFromGesture is this amount from a gesture and needs to be rubberBanded?
|
||||||
|
*/
|
||||||
|
private void setOverExpansionInternal(float overExpansion, boolean isFromGesture) {
|
||||||
|
if (!isFromGesture) {
|
||||||
|
mLastGesturedOverExpansion = -1;
|
||||||
|
setOverExpansion(overExpansion);
|
||||||
|
} else if (mLastGesturedOverExpansion != overExpansion) {
|
||||||
|
mLastGesturedOverExpansion = overExpansion;
|
||||||
|
final float heightForFullOvershoot = mView.getHeight() / 3.0f;
|
||||||
|
float newExpansion = MathUtils.saturate(overExpansion / heightForFullOvershoot);
|
||||||
|
newExpansion = Interpolators.getOvershootInterpolation(newExpansion);
|
||||||
|
setOverExpansion(newExpansion * mPanelFlingOvershootAmount * 2.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract void onHeightUpdated(float expandedHeight);
|
protected abstract void onHeightUpdated(float expandedHeight);
|
||||||
|
|
||||||
protected abstract float getOverExpansionAmount();
|
|
||||||
|
|
||||||
protected abstract float getOverExpansionPixels();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This returns the maximum height of the panel. Children should override this if their
|
* This returns the maximum height of the panel. Children should override this if their
|
||||||
* desired height is not the full height.
|
* desired height is not the full height.
|
||||||
@@ -977,9 +1021,32 @@ public abstract class PanelViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ValueAnimator createHeightAnimator(float targetHeight) {
|
private ValueAnimator createHeightAnimator(float targetHeight) {
|
||||||
|
return createHeightAnimator(targetHeight, 0.0f /* performOvershoot */);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an animator that can also overshoot
|
||||||
|
*
|
||||||
|
* @param targetHeight the target height
|
||||||
|
* @param overshootAmount the amount of overshoot desired
|
||||||
|
*/
|
||||||
|
private ValueAnimator createHeightAnimator(float targetHeight, float overshootAmount) {
|
||||||
|
float startExpansion = mOverExpansion;
|
||||||
ValueAnimator animator = ValueAnimator.ofFloat(mExpandedHeight, targetHeight);
|
ValueAnimator animator = ValueAnimator.ofFloat(mExpandedHeight, targetHeight);
|
||||||
animator.addUpdateListener(
|
animator.addUpdateListener(
|
||||||
animation -> setExpandedHeightInternal((float) animation.getAnimatedValue()));
|
animation -> {
|
||||||
|
if (overshootAmount > 0.0f
|
||||||
|
// Also remove the overExpansion when collapsing
|
||||||
|
|| (targetHeight == 0.0f && startExpansion != 0)) {
|
||||||
|
final float expansion = MathUtils.lerp(
|
||||||
|
startExpansion,
|
||||||
|
mPanelFlingOvershootAmount * overshootAmount,
|
||||||
|
Interpolators.FAST_OUT_SLOW_IN.getInterpolation(
|
||||||
|
animator.getAnimatedFraction()));
|
||||||
|
setOverExpansionInternal(expansion, false /* isFromGesture */);
|
||||||
|
}
|
||||||
|
setExpandedHeightInternal((float) animation.getAnimatedValue());
|
||||||
|
});
|
||||||
return animator;
|
return animator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -989,7 +1056,7 @@ public abstract class PanelViewController {
|
|||||||
mExpandedFraction,
|
mExpandedFraction,
|
||||||
mExpandedFraction > 0f || mInstantExpanding
|
mExpandedFraction > 0f || mInstantExpanding
|
||||||
|| isPanelVisibleBecauseOfHeadsUp() || mTracking
|
|| isPanelVisibleBecauseOfHeadsUp() || mTracking
|
||||||
|| mHeightAnimator != null);
|
|| mHeightAnimator != null && !mIsSpringBackAnimation);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < mExpansionListeners.size(); i++) {
|
for (int i = 0; i < mExpansionListeners.size(); i++) {
|
||||||
mExpansionListeners.get(i).onPanelExpansionChanged(mExpandedFraction, mTracking);
|
mExpansionListeners.get(i).onPanelExpansionChanged(mExpandedFraction, mTracking);
|
||||||
@@ -1037,14 +1104,6 @@ public abstract class PanelViewController {
|
|||||||
|
|
||||||
public abstract void resetViews(boolean animate);
|
public abstract void resetViews(boolean animate);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return whether "Clear all" button will be visible when the panel is fully expanded
|
|
||||||
*/
|
|
||||||
protected abstract boolean fullyExpandedClearAllVisible();
|
|
||||||
|
|
||||||
protected abstract boolean isClearAllVisible();
|
|
||||||
|
|
||||||
public void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) {
|
public void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) {
|
||||||
mHeadsUpManager = headsUpManager;
|
mHeadsUpManager = headsUpManager;
|
||||||
}
|
}
|
||||||
@@ -1080,6 +1139,11 @@ public abstract class PanelViewController {
|
|||||||
return new OnConfigurationChangedListener();
|
return new OnConfigurationChangedListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set that the panel is currently opening and not fully opened or closed.
|
||||||
|
*/
|
||||||
|
public abstract void setIsShadeOpening(boolean opening);
|
||||||
|
|
||||||
public class TouchHandler implements View.OnTouchListener {
|
public class TouchHandler implements View.OnTouchListener {
|
||||||
public boolean onInterceptTouchEvent(MotionEvent event) {
|
public boolean onInterceptTouchEvent(MotionEvent event) {
|
||||||
if (mInstantExpanding || !mNotificationsDragEnabled || mTouchDisabled || (mMotionAborted
|
if (mInstantExpanding || !mNotificationsDragEnabled || mTouchDisabled || (mMotionAborted
|
||||||
@@ -1108,7 +1172,7 @@ public abstract class PanelViewController {
|
|||||||
switch (event.getActionMasked()) {
|
switch (event.getActionMasked()) {
|
||||||
case MotionEvent.ACTION_DOWN:
|
case MotionEvent.ACTION_DOWN:
|
||||||
mStatusBar.userActivity();
|
mStatusBar.userActivity();
|
||||||
mAnimatingOnDown = mHeightAnimator != null;
|
mAnimatingOnDown = mHeightAnimator != null && !mIsSpringBackAnimation;
|
||||||
mMinExpandHeight = 0.0f;
|
mMinExpandHeight = 0.0f;
|
||||||
mDownTime = SystemClock.uptimeMillis();
|
mDownTime = SystemClock.uptimeMillis();
|
||||||
if (mAnimatingOnDown && mClosing && !mHintAnimationRunning) {
|
if (mAnimatingOnDown && mClosing && !mHintAnimationRunning) {
|
||||||
@@ -1227,10 +1291,10 @@ public abstract class PanelViewController {
|
|||||||
mCollapsedAndHeadsUpOnDown =
|
mCollapsedAndHeadsUpOnDown =
|
||||||
isFullyCollapsed() && mHeadsUpManager.hasPinnedHeadsUp();
|
isFullyCollapsed() && mHeadsUpManager.hasPinnedHeadsUp();
|
||||||
addMovement(event);
|
addMovement(event);
|
||||||
if (!mGestureWaitForTouchSlop || (mHeightAnimator != null
|
boolean regularHeightAnimationRunning = mHeightAnimator != null
|
||||||
&& !mHintAnimationRunning)) {
|
&& !mHintAnimationRunning && !mIsSpringBackAnimation;
|
||||||
mTouchSlopExceeded =
|
if (!mGestureWaitForTouchSlop || regularHeightAnimationRunning) {
|
||||||
(mHeightAnimator != null && !mHintAnimationRunning)
|
mTouchSlopExceeded = regularHeightAnimationRunning
|
||||||
|| mTouchSlopExceededBeforeDown;
|
|| mTouchSlopExceededBeforeDown;
|
||||||
cancelHeightAnimator();
|
cancelHeightAnimator();
|
||||||
onTrackingStarted();
|
onTrackingStarted();
|
||||||
|
|||||||
@@ -638,8 +638,6 @@ public class NotificationPanelViewTest extends SysuiTestCase {
|
|||||||
public void testCancelSwipeWhileLocked_notifiesKeyguardState() {
|
public void testCancelSwipeWhileLocked_notifiesKeyguardState() {
|
||||||
mStatusBarStateController.setState(KEYGUARD);
|
mStatusBarStateController.setState(KEYGUARD);
|
||||||
|
|
||||||
mNotificationPanelViewController.setOverExpansion(100f, true);
|
|
||||||
|
|
||||||
// Fling expanded (cancelling the keyguard exit swipe). We should notify keyguard state that
|
// Fling expanded (cancelling the keyguard exit swipe). We should notify keyguard state that
|
||||||
// the fling occurred and did not dismiss the keyguard.
|
// the fling occurred and did not dismiss the keyguard.
|
||||||
mNotificationPanelViewController.flingToHeight(
|
mNotificationPanelViewController.flingToHeight(
|
||||||
|
|||||||
Reference in New Issue
Block a user