Merge "[Motion] Split-shade transition on LS: add an overshoot/overscroll effect" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
0f3393a461
@@ -122,6 +122,11 @@ public interface QS extends FragmentBase {
|
||||
*/
|
||||
default void setScrollListener(ScrollListener scrollListener) {}
|
||||
|
||||
/**
|
||||
* Sets the amount of vertical over scroll that should be performed on QS.
|
||||
*/
|
||||
default void setOverScrollAmount(int overScrollAmount) {}
|
||||
|
||||
/**
|
||||
* Callback for when QSPanel container is scrolled
|
||||
*/
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
|
||||
<dimen name="status_bar_header_height_keyguard">42dp</dimen>
|
||||
|
||||
<dimen name="lockscreen_shade_max_over_scroll_amount">32dp</dimen>
|
||||
|
||||
<!-- Distance that the full shade transition takes in order to complete by tapping on a button
|
||||
like "expand". -->
|
||||
<dimen name="lockscreen_shade_transition_by_tap_distance">200dp</dimen>
|
||||
|
||||
20
packages/SystemUI/res/values-sw600dp-land/integers.xml
Normal file
20
packages/SystemUI/res/values-sw600dp-land/integers.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
* Copyright (c) 2006, 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.
|
||||
*/
|
||||
-->
|
||||
<resources>
|
||||
<integer name="lockscreen_shade_over_scroll_release_duration">500</integer>
|
||||
</resources>
|
||||
@@ -26,4 +26,6 @@
|
||||
<dimen name="status_bar_header_height_keyguard">56dp</dimen>
|
||||
|
||||
<dimen name="qs_media_session_height_expanded">251dp</dimen>
|
||||
|
||||
<dimen name="lockscreen_shade_max_over_scroll_amount">42dp</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -1174,9 +1174,8 @@
|
||||
the shade -->
|
||||
<dimen name="lockscreen_shade_media_transition_distance">120dp</dimen>
|
||||
|
||||
<!-- Maximum overshoot for the topPadding of notifications when transitioning to the full
|
||||
shade -->
|
||||
<dimen name="lockscreen_shade_notification_movement">24dp</dimen>
|
||||
<!-- Maximum over scroll amount for the shade when transition to the full shade. -->
|
||||
<dimen name="lockscreen_shade_max_over_scroll_amount">24dp</dimen>
|
||||
|
||||
<!-- Maximum overshoot for the pulse expansion -->
|
||||
<dimen name="pulse_expansion_max_top_overshoot">32dp</dimen>
|
||||
|
||||
@@ -25,4 +25,7 @@
|
||||
See com.android.systemui.volume.VolumeDialogImpl.
|
||||
Value 21 corresponds to RIGHT|CENTER_VERTICAL. -->
|
||||
<integer name="volume_dialog_gravity">21</integer>
|
||||
|
||||
<!-- The time it takes for the over scroll release animation to complete, in milli seconds. -->
|
||||
<integer name="lockscreen_shade_over_scroll_release_duration">0</integer>
|
||||
</resources>
|
||||
@@ -141,6 +141,8 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
||||
*/
|
||||
private float mFullShadeProgress;
|
||||
|
||||
private boolean mOverScrolling;
|
||||
|
||||
@Inject
|
||||
public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
|
||||
QSTileHost qsTileHost,
|
||||
@@ -497,6 +499,12 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
||||
isTransitioningToFullShade ? progress : mSquishinessFraction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOverScrollAmount(int overScrollAmount) {
|
||||
mOverScrolling = overScrollAmount != 0;
|
||||
getView().setTranslationY(overScrollAmount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeightDiff() {
|
||||
return mQSPanelScrollView.getBottom() - mHeader.getBottom()
|
||||
@@ -515,7 +523,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
||||
? 1 : QSAnimator.SHORT_PARALLAX_AMOUNT) * (expansion - 1);
|
||||
boolean onKeyguard = isKeyguardState();
|
||||
boolean onKeyguardAndExpanded = onKeyguard && !mShowCollapsedOnKeyguard;
|
||||
if (!mHeaderAnimating && !headerWillBeAnimating()) {
|
||||
if (!mHeaderAnimating && !headerWillBeAnimating() && !mOverScrolling) {
|
||||
getView().setTranslationY(
|
||||
onKeyguardAndExpanded
|
||||
? translationScaleY * mHeader.getHeight()
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.android.systemui.statusbar
|
||||
|
||||
/** Represents an over scroller for the transition to full shade on lock screen. */
|
||||
interface LockScreenShadeOverScroller {
|
||||
|
||||
/** The amount in pixels that the user has dragged to expand the shade. */
|
||||
var expansionDragDownAmount: Float
|
||||
}
|
||||
@@ -64,6 +64,8 @@ class LockscreenShadeTransitionController @Inject constructor(
|
||||
private val scrimController: ScrimController,
|
||||
private val depthController: NotificationShadeDepthController,
|
||||
private val context: Context,
|
||||
private val splitShadeOverScrollerFactory: SplitShadeLockScreenOverScroller.Factory,
|
||||
private val singleShadeOverScrollerFactory: SingleShadeLockScreenOverScroller.Factory,
|
||||
wakefulnessLifecycle: WakefulnessLifecycle,
|
||||
configurationController: ConfigurationController,
|
||||
falsingManager: FalsingManager,
|
||||
@@ -194,6 +196,27 @@ class LockscreenShadeTransitionController @Inject constructor(
|
||||
*/
|
||||
val touchHelper = DragDownHelper(falsingManager, falsingCollector, this, context)
|
||||
|
||||
private val splitShadeOverScroller: SplitShadeLockScreenOverScroller by lazy {
|
||||
splitShadeOverScrollerFactory.create(qS, nsslController)
|
||||
}
|
||||
|
||||
private val phoneShadeOverScroller: SingleShadeLockScreenOverScroller by lazy {
|
||||
singleShadeOverScrollerFactory.create(nsslController)
|
||||
}
|
||||
|
||||
/**
|
||||
* [LockScreenShadeOverScroller] property that delegates to either
|
||||
* [SingleShadeLockScreenOverScroller] or [SplitShadeLockScreenOverScroller].
|
||||
*
|
||||
* There are currently two different implementations, as the over scroll behavior is different
|
||||
* on single shade and split shade.
|
||||
*
|
||||
* On single shade, only notifications are over scrolled, whereas on split shade, everything is
|
||||
* over scrolled.
|
||||
*/
|
||||
private val shadeOverScroller: LockScreenShadeOverScroller
|
||||
get() = if (useSplitShade) splitShadeOverScroller else phoneShadeOverScroller
|
||||
|
||||
init {
|
||||
updateResources()
|
||||
configurationController.addCallback(object : ConfigurationController.ConfigurationListener {
|
||||
@@ -410,7 +433,7 @@ class LockscreenShadeTransitionController @Inject constructor(
|
||||
if (!nsslController.isInLockedDownShade() || field == 0f || forceApplyAmount) {
|
||||
val notificationShelfProgress =
|
||||
MathUtils.saturate(dragDownAmount / notificationShelfTransitionDistance)
|
||||
nsslController.setTransitionToFullShadeAmount(field, notificationShelfProgress)
|
||||
nsslController.setTransitionToFullShadeAmount(notificationShelfProgress)
|
||||
|
||||
qSDragProgress = MathUtils.saturate(dragDownAmount / qsTransitionDistance)
|
||||
qS.setTransitionToFullShadeAmount(field, qSDragProgress)
|
||||
@@ -422,6 +445,7 @@ class LockscreenShadeTransitionController @Inject constructor(
|
||||
transitionToShadeAmountScrim(field)
|
||||
transitionToShadeAmountCommon(field)
|
||||
transitionToShadeAmountKeyguard(field)
|
||||
shadeOverScroller.expansionDragDownAmount = dragDownAmount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.android.systemui.statusbar
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.util.MathUtils
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.animation.Interpolators
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
class SingleShadeLockScreenOverScroller
|
||||
@AssistedInject
|
||||
constructor(
|
||||
configurationController: ConfigurationController,
|
||||
private val context: Context,
|
||||
private val statusBarStateController: SysuiStatusBarStateController,
|
||||
@Assisted private val nsslController: NotificationStackScrollLayoutController
|
||||
) : LockScreenShadeOverScroller {
|
||||
|
||||
private var maxOverScrollAmount = 0
|
||||
private var totalDistanceForFullShadeTransition = 0
|
||||
|
||||
init {
|
||||
updateResources()
|
||||
configurationController.addCallback(
|
||||
object : ConfigurationController.ConfigurationListener {
|
||||
override fun onConfigChanged(newConfig: Configuration?) {
|
||||
updateResources()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun updateResources() {
|
||||
val resources = context.resources
|
||||
totalDistanceForFullShadeTransition =
|
||||
resources.getDimensionPixelSize(R.dimen.lockscreen_shade_qs_transition_distance)
|
||||
maxOverScrollAmount =
|
||||
resources.getDimensionPixelSize(R.dimen.lockscreen_shade_max_over_scroll_amount)
|
||||
}
|
||||
|
||||
override var expansionDragDownAmount: Float = 0f
|
||||
set(value) {
|
||||
if (value == field) {
|
||||
return
|
||||
}
|
||||
field = value
|
||||
overScroll()
|
||||
}
|
||||
|
||||
private fun overScroll() {
|
||||
var extraTopInset = 0.0f
|
||||
if (statusBarStateController.state == StatusBarState.KEYGUARD) {
|
||||
val viewHeight = nsslController.height
|
||||
val overallProgress = MathUtils.saturate(expansionDragDownAmount / viewHeight)
|
||||
val transitionProgress =
|
||||
Interpolators.getOvershootInterpolation(
|
||||
overallProgress,
|
||||
0.6f,
|
||||
totalDistanceForFullShadeTransition.toFloat() / viewHeight.toFloat())
|
||||
extraTopInset = transitionProgress * maxOverScrollAmount
|
||||
}
|
||||
nsslController.setOverScrollAmount(extraTopInset.toInt())
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
fun interface Factory {
|
||||
fun create(
|
||||
nsslController: NotificationStackScrollLayoutController
|
||||
): SingleShadeLockScreenOverScroller
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package com.android.systemui.statusbar
|
||||
|
||||
import android.animation.Animator
|
||||
import android.animation.ValueAnimator
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.util.MathUtils
|
||||
import android.view.animation.PathInterpolator
|
||||
import com.android.internal.annotations.VisibleForTesting
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.animation.Interpolators
|
||||
import com.android.systemui.plugins.qs.QS
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
|
||||
import com.android.systemui.statusbar.phone.ScrimController
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
class SplitShadeLockScreenOverScroller
|
||||
@AssistedInject
|
||||
constructor(
|
||||
configurationController: ConfigurationController,
|
||||
private val context: Context,
|
||||
private val scrimController: ScrimController,
|
||||
private val statusBarStateController: SysuiStatusBarStateController,
|
||||
@Assisted private val qS: QS,
|
||||
@Assisted private val nsslController: NotificationStackScrollLayoutController
|
||||
) : LockScreenShadeOverScroller {
|
||||
|
||||
private var releaseOverScrollAnimator: Animator? = null
|
||||
private var transitionToFullShadeDistance = 0
|
||||
private var releaseOverScrollDuration = 0L
|
||||
private var maxOverScrollAmount = 0
|
||||
private var previousOverscrollAmount = 0
|
||||
|
||||
init {
|
||||
updateResources()
|
||||
configurationController.addCallback(
|
||||
object : ConfigurationController.ConfigurationListener {
|
||||
override fun onConfigChanged(newConfig: Configuration?) {
|
||||
updateResources()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun updateResources() {
|
||||
val resources = context.resources
|
||||
transitionToFullShadeDistance =
|
||||
resources.getDimensionPixelSize(R.dimen.lockscreen_shade_full_transition_distance)
|
||||
maxOverScrollAmount =
|
||||
resources.getDimensionPixelSize(R.dimen.lockscreen_shade_max_over_scroll_amount)
|
||||
releaseOverScrollDuration =
|
||||
resources.getInteger(R.integer.lockscreen_shade_over_scroll_release_duration).toLong()
|
||||
}
|
||||
|
||||
override var expansionDragDownAmount: Float = 0f
|
||||
set(dragDownAmount) {
|
||||
if (field == dragDownAmount) {
|
||||
return
|
||||
}
|
||||
field = dragDownAmount
|
||||
if (shouldOverscroll()) {
|
||||
overScroll(dragDownAmount)
|
||||
} else if (shouldReleaseOverscroll()) {
|
||||
releaseOverScroll()
|
||||
}
|
||||
}
|
||||
|
||||
private fun shouldOverscroll() = statusBarStateController.state == StatusBarState.KEYGUARD
|
||||
|
||||
private fun shouldReleaseOverscroll() = !shouldOverscroll() && previousOverscrollAmount != 0
|
||||
|
||||
private fun overScroll(dragDownAmount: Float) {
|
||||
val overscrollAmount: Int = calculateOverscrollAmount(dragDownAmount)
|
||||
applyOverscroll(overscrollAmount)
|
||||
previousOverscrollAmount = overscrollAmount
|
||||
}
|
||||
|
||||
private fun applyOverscroll(overscrollAmount: Int) {
|
||||
qS.setOverScrollAmount(overscrollAmount)
|
||||
scrimController.setNotificationsOverScrollAmount(overscrollAmount)
|
||||
nsslController.setOverScrollAmount(overscrollAmount)
|
||||
}
|
||||
|
||||
private fun calculateOverscrollAmount(dragDownAmount: Float): Int {
|
||||
val fullHeight: Int = nsslController.height
|
||||
val fullHeightProgress: Float = MathUtils.saturate(dragDownAmount / fullHeight)
|
||||
val overshootStart: Float = transitionToFullShadeDistance / fullHeight.toFloat()
|
||||
val overShootTransitionProgress: Float =
|
||||
Interpolators.getOvershootInterpolation(
|
||||
fullHeightProgress, OVER_SHOOT_AMOUNT, overshootStart)
|
||||
return (overShootTransitionProgress * maxOverScrollAmount).toInt()
|
||||
}
|
||||
|
||||
private fun releaseOverScroll() {
|
||||
val animator = ValueAnimator.ofInt(previousOverscrollAmount, 0)
|
||||
animator.addUpdateListener {
|
||||
val overScrollAmount = it.animatedValue as Int
|
||||
qS.setOverScrollAmount(overScrollAmount)
|
||||
scrimController.setNotificationsOverScrollAmount(overScrollAmount)
|
||||
nsslController.setOverScrollAmount(overScrollAmount)
|
||||
}
|
||||
animator.interpolator = RELEASE_OVER_SCROLL_INTERPOLATOR
|
||||
animator.duration = releaseOverScrollDuration
|
||||
animator.start()
|
||||
releaseOverScrollAnimator = animator
|
||||
previousOverscrollAmount = 0
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
internal fun finishAnimations() {
|
||||
releaseOverScrollAnimator?.end()
|
||||
releaseOverScrollAnimator = null
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
fun interface Factory {
|
||||
fun create(
|
||||
qS: QS,
|
||||
nsslController: NotificationStackScrollLayoutController
|
||||
): SplitShadeLockScreenOverScroller
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val OVER_SHOOT_AMOUNT = 0.6f
|
||||
private val RELEASE_OVER_SCROLL_INTERPOLATOR = PathInterpolator(0.17f, 0f, 0f, 1f)
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,6 @@ import android.provider.Settings;
|
||||
import android.service.notification.NotificationListenerService;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.util.Log;
|
||||
import android.util.MathUtils;
|
||||
import android.util.Pair;
|
||||
import android.view.Display;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -65,7 +64,6 @@ import com.android.systemui.ExpandHelper;
|
||||
import com.android.systemui.Gefingerpoken;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SwipeHelper;
|
||||
import com.android.systemui.animation.Interpolators;
|
||||
import com.android.systemui.classifier.Classifier;
|
||||
import com.android.systemui.classifier.FalsingCollector;
|
||||
import com.android.systemui.colorextraction.SysuiColorExtractor;
|
||||
@@ -205,18 +203,6 @@ public class NotificationStackScrollLayoutController {
|
||||
|
||||
private ColorExtractor.OnColorsChangedListener mOnColorsChangedListener;
|
||||
|
||||
/**
|
||||
* The total distance in pixels that the full shade transition takes to transition entirely to
|
||||
* the full shade.
|
||||
*/
|
||||
private int mTotalDistanceForFullShadeTransition;
|
||||
|
||||
/**
|
||||
* The amount of movement the notifications do when transitioning to the full shade before
|
||||
* reaching the overstrech
|
||||
*/
|
||||
private int mNotificationDragDownMovement;
|
||||
|
||||
@VisibleForTesting
|
||||
final View.OnAttachStateChangeListener mOnAttachStateChangeListener =
|
||||
new View.OnAttachStateChangeListener() {
|
||||
@@ -304,10 +290,6 @@ public class NotificationStackScrollLayoutController {
|
||||
private NotifStats mNotifStats = NotifStats.getEmpty();
|
||||
|
||||
private void updateResources() {
|
||||
mNotificationDragDownMovement = mResources.getDimensionPixelSize(
|
||||
R.dimen.lockscreen_shade_notification_movement);
|
||||
mTotalDistanceForFullShadeTransition = mResources.getDimensionPixelSize(
|
||||
R.dimen.lockscreen_shade_qs_transition_distance);
|
||||
mNotificationStackSizeCalculator.updateResources();
|
||||
}
|
||||
|
||||
@@ -1537,8 +1519,6 @@ public class NotificationStackScrollLayoutController {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param amount The amount of pixels we have currently dragged down
|
||||
* for the lockscreen to shade transition. 0f for all other states.
|
||||
* @param fraction The fraction of lockscreen to shade transition.
|
||||
* 0f for all other states.
|
||||
*
|
||||
@@ -1546,18 +1526,15 @@ public class NotificationStackScrollLayoutController {
|
||||
* LockscreenShadeTransitionController resets amount and fraction to 0, where they remain
|
||||
* until the next lockscreen-to-shade transition.
|
||||
*/
|
||||
public void setTransitionToFullShadeAmount(float amount, float fraction) {
|
||||
public void setTransitionToFullShadeAmount(float fraction) {
|
||||
mView.setFractionToShade(fraction);
|
||||
}
|
||||
|
||||
float extraTopInset = 0.0f;
|
||||
if (mStatusBarStateController.getState() == KEYGUARD) {
|
||||
float overallProgress = MathUtils.saturate(amount / mView.getHeight());
|
||||
float transitionProgress = Interpolators.getOvershootInterpolation(overallProgress,
|
||||
0.6f,
|
||||
(float) mTotalDistanceForFullShadeTransition / (float) mView.getHeight());
|
||||
extraTopInset = transitionProgress * mNotificationDragDownMovement;
|
||||
}
|
||||
mView.setExtraTopInsetForFullShadeTransition(extraTopInset);
|
||||
/**
|
||||
* Sets the amount of vertical over scroll that should be performed on NSSL.
|
||||
*/
|
||||
public void setOverScrollAmount(int overScrollAmount) {
|
||||
mView.setExtraTopInsetForFullShadeTransition(overScrollAmount);
|
||||
}
|
||||
|
||||
/** */
|
||||
|
||||
@@ -644,6 +644,13 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the amount of vertical over scroll that should be performed on the notifications scrim.
|
||||
*/
|
||||
public void setNotificationsOverScrollAmount(int overScrollAmount) {
|
||||
mNotificationsScrim.setTranslationY(overScrollAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Current state of the QuickSettings when pulling it from the top.
|
||||
*
|
||||
|
||||
@@ -44,6 +44,7 @@ import org.mockito.Mockito
|
||||
import org.mockito.Mockito.clearInvocations
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.verifyZeroInteractions
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
|
||||
private fun <T> anyObject(): T {
|
||||
@@ -75,6 +76,8 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
|
||||
@Mock lateinit var expandHelperCallback: ExpandHelper.Callback
|
||||
@Mock lateinit var mCentralSurfaces: CentralSurfaces
|
||||
@Mock lateinit var qS: QS
|
||||
@Mock lateinit var singleShadeOverScroller: SingleShadeLockScreenOverScroller
|
||||
@Mock lateinit var splitShadeOverScroller: SplitShadeLockScreenOverScroller
|
||||
@JvmField @Rule val mockito = MockitoJUnit.rule()
|
||||
|
||||
private val configurationController = FakeConfigurationController()
|
||||
@@ -104,7 +107,9 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
|
||||
context = context,
|
||||
configurationController = configurationController,
|
||||
falsingManager = falsingManager,
|
||||
dumpManager = dumpManager
|
||||
dumpManager = dumpManager,
|
||||
splitShadeOverScrollerFactory = { _, _ -> splitShadeOverScroller },
|
||||
singleShadeOverScrollerFactory = { singleShadeOverScroller }
|
||||
)
|
||||
whenever(nsslController.view).thenReturn(stackscroller)
|
||||
whenever(nsslController.expandHelperCallback).thenReturn(expandHelperCallback)
|
||||
@@ -229,7 +234,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
|
||||
fun testDragDownAmountDoesntCallOutInLockedDownShade() {
|
||||
whenever(nsslController.isInLockedDownShade).thenReturn(true)
|
||||
transitionController.dragDownAmount = 10f
|
||||
verify(nsslController, never()).setTransitionToFullShadeAmount(anyFloat(), anyFloat())
|
||||
verify(nsslController, never()).setTransitionToFullShadeAmount(anyFloat())
|
||||
verify(mediaHierarchyManager, never()).setTransitionToFullShadeAmount(anyFloat())
|
||||
verify(scrimController, never()).setTransitionToFullShadeProgress(anyFloat(), anyFloat())
|
||||
verify(notificationPanelController, never()).setTransitionToFullShadeAmount(anyFloat(),
|
||||
@@ -240,7 +245,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun testDragDownAmountCallsOut() {
|
||||
transitionController.dragDownAmount = 10f
|
||||
verify(nsslController).setTransitionToFullShadeAmount(anyFloat(), anyFloat())
|
||||
verify(nsslController).setTransitionToFullShadeAmount(anyFloat())
|
||||
verify(mediaHierarchyManager).setTransitionToFullShadeAmount(anyFloat())
|
||||
verify(scrimController).setTransitionToFullShadeProgress(anyFloat(), anyFloat())
|
||||
verify(notificationPanelController).setTransitionToFullShadeAmount(anyFloat(),
|
||||
@@ -388,6 +393,26 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
|
||||
verify(mediaHierarchyManager).setTransitionToFullShadeAmount(10f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setDragAmount_notInSplitShade_forwardsToSingleShadeOverScroller() {
|
||||
disableSplitShade()
|
||||
|
||||
transitionController.dragDownAmount = 10f
|
||||
|
||||
verify(singleShadeOverScroller).expansionDragDownAmount = 10f
|
||||
verifyZeroInteractions(splitShadeOverScroller)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setDragAmount_inSplitShade_forwardsToSplitShadeOverScroller() {
|
||||
enableSplitShade()
|
||||
|
||||
transitionController.dragDownAmount = 10f
|
||||
|
||||
verify(splitShadeOverScroller).expansionDragDownAmount = 10f
|
||||
verifyZeroInteractions(singleShadeOverScroller)
|
||||
}
|
||||
|
||||
private fun enableSplitShade() {
|
||||
setSplitShadeEnabled(true)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.android.systemui.statusbar
|
||||
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
import android.testing.AndroidTestingRunner
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
|
||||
import com.android.systemui.statusbar.policy.FakeConfigurationController
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.intThat
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@SmallTest
|
||||
class SingleShadeLockScreenOverScrollerTest : SysuiTestCase() {
|
||||
|
||||
@Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
|
||||
@Mock private lateinit var nsslController: NotificationStackScrollLayoutController
|
||||
|
||||
private lateinit var overScroller: SingleShadeLockScreenOverScroller
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
whenever(nsslController.height).thenReturn(1800)
|
||||
overScroller =
|
||||
SingleShadeLockScreenOverScroller(
|
||||
FakeConfigurationController(),
|
||||
context,
|
||||
statusBarStateController,
|
||||
nsslController
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setDragDownAmount_onKeyguard_overScrolls() {
|
||||
whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
|
||||
|
||||
overScroller.expansionDragDownAmount = 10f
|
||||
|
||||
verify(nsslController).setOverScrollAmount(intThat { it > 0 })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setDragDownAmount_notOnKeyguard_doesNotOverScroll() {
|
||||
whenever(statusBarStateController.state).thenReturn(StatusBarState.SHADE)
|
||||
|
||||
overScroller.expansionDragDownAmount = 10f
|
||||
|
||||
verify(nsslController).setOverScrollAmount(0)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package com.android.systemui.statusbar
|
||||
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.testing.TestableLooper
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.plugins.qs.QS
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
|
||||
import com.android.systemui.statusbar.phone.ScrimController
|
||||
import com.android.systemui.statusbar.policy.FakeConfigurationController
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.atLeast
|
||||
import org.mockito.Mockito.intThat
|
||||
import org.mockito.Mockito.reset
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.verifyNoMoreInteractions
|
||||
import org.mockito.Mockito.verifyZeroInteractions
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@SmallTest
|
||||
@TestableLooper.RunWithLooper
|
||||
class SplitShadeLockScreenOverScrollerTest : SysuiTestCase() {
|
||||
|
||||
private val configurationController = FakeConfigurationController()
|
||||
|
||||
@Mock private lateinit var scrimController: ScrimController
|
||||
@Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
|
||||
@Mock private lateinit var qS: QS
|
||||
@Mock private lateinit var nsslController: NotificationStackScrollLayoutController
|
||||
|
||||
private lateinit var overScroller: SplitShadeLockScreenOverScroller
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
|
||||
whenever(nsslController.height).thenReturn(1800)
|
||||
|
||||
overScroller =
|
||||
SplitShadeLockScreenOverScroller(
|
||||
configurationController,
|
||||
context,
|
||||
scrimController,
|
||||
statusBarStateController,
|
||||
qS,
|
||||
nsslController)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setDragDownAmount_onKeyguard_appliesOverScroll() {
|
||||
whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
|
||||
|
||||
setDragAmount(1000f)
|
||||
|
||||
verifyOverScrollPerformed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setDragDownAmount_notOnKeyguard_doesNotApplyOverScroll() {
|
||||
whenever(statusBarStateController.state).thenReturn(StatusBarState.SHADE)
|
||||
|
||||
setDragAmount(1000f)
|
||||
|
||||
verifyZeroInteractions(qS)
|
||||
verifyZeroInteractions(scrimController)
|
||||
verifyZeroInteractions(nsslController)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setDragAmount_onKeyguard_thenNotOnKeyguard_resetsOverScrollToZero() {
|
||||
whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
|
||||
setDragAmount(1000f)
|
||||
verifyOverScrollPerformed()
|
||||
reset(qS, scrimController, nsslController)
|
||||
|
||||
whenever(statusBarStateController.state).thenReturn(StatusBarState.SHADE)
|
||||
setDragAmount(999f)
|
||||
verifyOverScrollResetToZero()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setDragAmount_onKeyguard_thenNotOnKeyguard_multipleTimes_resetsOverScrollToZeroOnlyOnce() {
|
||||
whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
|
||||
setDragAmount(1000f)
|
||||
whenever(statusBarStateController.state).thenReturn(StatusBarState.SHADE)
|
||||
setDragAmount(999f)
|
||||
reset(qS, scrimController, nsslController)
|
||||
|
||||
setDragAmount(998f)
|
||||
setDragAmount(997f)
|
||||
setDragAmount(996f)
|
||||
verifyNoMoreOverScrollChanges()
|
||||
}
|
||||
|
||||
private fun verifyOverScrollPerformed() {
|
||||
verify(qS).setOverScrollAmount(intThat { it > 0 })
|
||||
verify(scrimController).setNotificationsOverScrollAmount(intThat { it > 0 })
|
||||
verify(nsslController).setOverScrollAmount(intThat { it > 0 })
|
||||
}
|
||||
|
||||
private fun verifyOverScrollResetToZero() {
|
||||
// Might be more than once as the animator might have multiple values close to zero that
|
||||
// round down to zero.
|
||||
verify(qS, atLeast(1)).setOverScrollAmount(0)
|
||||
verify(scrimController, atLeast(1)).setNotificationsOverScrollAmount(0)
|
||||
verify(nsslController, atLeast(1)).setOverScrollAmount(0)
|
||||
}
|
||||
|
||||
private fun verifyNoMoreOverScrollChanges() {
|
||||
verifyNoMoreInteractions(qS)
|
||||
verifyNoMoreInteractions(scrimController)
|
||||
verifyNoMoreInteractions(nsslController)
|
||||
}
|
||||
|
||||
private fun setDragAmount(dragDownAmount: Float) {
|
||||
overScroller.expansionDragDownAmount = dragDownAmount
|
||||
overScroller.finishAnimations()
|
||||
}
|
||||
}
|
||||
@@ -1296,6 +1296,33 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
assertThat(mNotificationsScrim.getViewAlpha()).isEqualTo(notifProgress);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setNotificationsOverScrollAmount_setsTranslationYOnNotificationsScrim() {
|
||||
int overScrollAmount = 10;
|
||||
|
||||
mScrimController.setNotificationsOverScrollAmount(overScrollAmount);
|
||||
|
||||
assertThat(mNotificationsScrim.getTranslationY()).isEqualTo(overScrollAmount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setNotificationsOverScrollAmount_doesNotSetTranslationYOnBehindScrim() {
|
||||
int overScrollAmount = 10;
|
||||
|
||||
mScrimController.setNotificationsOverScrollAmount(overScrollAmount);
|
||||
|
||||
assertThat(mScrimBehind.getTranslationY()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setNotificationsOverScrollAmount_doesNotSetTranslationYOnFrontScrim() {
|
||||
int overScrollAmount = 10;
|
||||
|
||||
mScrimController.setNotificationsOverScrollAmount(overScrollAmount);
|
||||
|
||||
assertThat(mScrimInFront.getTranslationY()).isEqualTo(0);
|
||||
}
|
||||
|
||||
private void assertAlphaAfterExpansion(ScrimView scrim, float expectedAlpha, float expansion) {
|
||||
mScrimController.setRawPanelExpansionFraction(expansion);
|
||||
finishAnimationsImmediately();
|
||||
|
||||
Reference in New Issue
Block a user