diff options
| author | 2022-01-28 22:01:40 +0000 | |
|---|---|---|
| committer | 2022-01-28 22:01:40 +0000 | |
| commit | 63075cc39a35fa86f23c15c3f616e2daac81a625 (patch) | |
| tree | 0e68431f2131daaaec62d6fede2d3a1ef603a54c | |
| parent | cb6178a280d7c35dd4671616923b46743e558a51 (diff) | |
| parent | 9a52b474d67c76c4d1c1bf59dd4e62b4cd2a3b3c (diff) | |
Merge "Short shelf on lockscreen that animates width with transition to shade"
9 files changed, 358 insertions, 33 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt index c136d9cc7272..b312ce20b313 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt @@ -337,11 +337,11 @@ class LockscreenShadeTransitionController @Inject constructor( if (field != value || forceApplyAmount) { field = value if (!nsslController.isInLockedDownShade() || field == 0f || forceApplyAmount) { - nsslController.setTransitionToFullShadeAmount(field) - notificationPanelController.setTransitionToFullShadeAmount(field, - false /* animate */, 0 /* delay */) qSDragProgress = MathUtils.saturate(dragDownAmount / scrimTransitionDistance) + nsslController.setTransitionToFullShadeAmount(field, qSDragProgress) qS.setTransitionToFullShadeAmount(field, qSDragProgress) + notificationPanelController.setTransitionToFullShadeAmount(field, + false /* animate */, 0 /* delay */) // TODO: appear media also in split shade val mediaAmount = if (useSplitShade) 0f else field mediaHierarchyManager.setTransitionToFullShadeAmount(mediaAmount) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index 51a66aad39fb..3411eab23d63 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar; +import static com.android.systemui.statusbar.phone.NotificationIconContainer.MAX_ICONS_ON_LOCKSCREEN; + import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; @@ -32,6 +34,7 @@ import android.view.animation.PathInterpolator; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.SystemBarUtils; import com.android.systemui.R; +import com.android.systemui.animation.Interpolators; import com.android.systemui.animation.ShadeInterpolation; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; import com.android.systemui.statusbar.notification.NotificationUtils; @@ -45,6 +48,7 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm; import com.android.systemui.statusbar.notification.stack.ViewState; import com.android.systemui.statusbar.phone.NotificationIconContainer; +import com.android.systemui.util.Utils; /** * A notification shelf view that is placed inside the notification scroller. It manages the @@ -81,6 +85,11 @@ public class NotificationShelf extends ActivatableNotificationView implements private int mIndexOfFirstViewInShelf = -1; private float mCornerAnimationDistance; private NotificationShelfController mController; + private int mActualWidth = -1; + private boolean mUseSplitShade; + + /** Fraction of lockscreen to shade animation (on lockscreen swipe down). */ + private float mFractionToShade; public NotificationShelf(Context context, AttributeSet attrs) { super(context, attrs); @@ -122,13 +131,16 @@ public class NotificationShelf extends ActivatableNotificationView implements layoutParams.height = res.getDimensionPixelOffset(R.dimen.notification_shelf_height); setLayoutParams(layoutParams); - int padding = res.getDimensionPixelOffset(R.dimen.shelf_icon_container_padding); + final int padding = res.getDimensionPixelOffset(R.dimen.shelf_icon_container_padding); mShelfIcons.setPadding(padding, 0, padding, 0); mScrollFastThreshold = res.getDimensionPixelOffset(R.dimen.scroll_fast_threshold); mShowNotificationShelf = res.getBoolean(R.bool.config_showNotificationShelf); mCornerAnimationDistance = res.getDimensionPixelSize( R.dimen.notification_corner_animation_distance); + // TODO(b/213480466) enable short shelf on split shade + mUseSplitShade = Utils.shouldUseSplitNotificationShade(mContext.getResources()); + mShelfIcons.setInNotificationIconShelf(true); if (!mShowNotificationShelf) { setVisibility(GONE); @@ -203,6 +215,10 @@ public class NotificationShelf extends ActivatableNotificationView implements final float stackEnd = ambientState.getStackY() + ambientState.getStackHeight(); viewState.yTranslation = stackEnd - viewState.height; + + final int shortestWidth = mShelfIcons.calculateWidthFor(MAX_ICONS_ON_LOCKSCREEN); + final float fraction = Interpolators.STANDARD.getInterpolation(mFractionToShade); + updateStateWidth(viewState, fraction, shortestWidth); } else { viewState.hidden = true; viewState.location = ExpandableViewState.LOCATION_GONE; @@ -211,6 +227,77 @@ public class NotificationShelf extends ActivatableNotificationView implements } /** + * @param shelfState View state for NotificationShelf + * @param fraction Fraction of lockscreen to shade transition + * @param shortestWidth Shortest width to use for lockscreen shelf + */ + @VisibleForTesting + public void updateStateWidth(ShelfState shelfState, float fraction, int shortestWidth) { + shelfState.actualWidth = !mUseSplitShade && mAmbientState.isOnKeyguard() + ? (int) MathUtils.lerp(shortestWidth, getWidth(), fraction) + : getWidth(); + } + + /** + * @param fractionToShade Fraction of lockscreen to shade transition + */ + public void setFractionToShade(float fractionToShade) { + mFractionToShade = fractionToShade; + } + + /** + * @return Actual width of shelf, accounting for possible ongoing width animation + */ + public int getActualWidth() { + return mActualWidth > -1 ? mActualWidth : getWidth(); + } + + /** + * @param localX Click x from left of screen + * @param slop Margin of error within which we count x for valid click + * @param left Left of shelf, from left of screen + * @param right Right of shelf, from left of screen + * @return Whether click x was in view + */ + @VisibleForTesting + public boolean isXInView(float localX, float slop, float left, float right) { + return (left - slop) <= localX && localX < (right + slop); + } + + /** + * @param localY Click y from top of shelf + * @param slop Margin of error within which we count y for valid click + * @param top Top of shelf + * @param bottom Height of shelf + * @return Whether click y was in view + */ + @VisibleForTesting + public boolean isYInView(float localY, float slop, float top, float bottom) { + return (top - slop) <= localY && localY < (bottom + slop); + } + + /** + * @param localX Click x + * @param localY Click y + * @param slop Margin of error for valid click + * @return Whether this click was on the visible (non-clipped) part of the shelf + */ + @Override + public boolean pointInView(float localX, float localY, float slop) { + final float containerWidth = getWidth(); + final float shelfWidth = getActualWidth(); + + final float left = isLayoutRtl() ? containerWidth - shelfWidth : 0; + final float right = isLayoutRtl() ? containerWidth : shelfWidth; + + final float top = mClipTopAmount; + final float bottom = getActualHeight(); + + return isXInView(localX, slop, left, right) + && isYInView(localY, slop, top, bottom); + } + + /** * Update the shelf appearance based on the other notifications around it. This transforms * the icons from the notification area into the shelf. */ @@ -732,11 +819,15 @@ public class NotificationShelf extends ActivatableNotificationView implements // we always want to clip to our sides, such that nothing can draw outside of these bounds int height = getResources().getDisplayMetrics().heightPixels; mClipRect.set(0, -height, getWidth(), height); - mShelfIcons.setClipBounds(mClipRect); + if (mShelfIcons != null) { + mShelfIcons.setClipBounds(mClipRect); + } } private void updateRelativeOffset() { - mCollapsedIcons.getLocationOnScreen(mTmp); + if (mCollapsedIcons != null) { + mCollapsedIcons.getLocationOnScreen(mTmp); + } getLocationOnScreen(mTmp); } @@ -831,9 +922,20 @@ public class NotificationShelf extends ActivatableNotificationView implements mIndexOfFirstViewInShelf = mHostLayoutController.indexOfChild(firstViewInShelf); } - private class ShelfState extends ExpandableViewState { + public class ShelfState extends ExpandableViewState { private boolean hasItemsInStableShelf; private ExpandableView firstViewInShelf; + public int actualWidth = -1; + + private void updateShelfWidth(View view) { + if (actualWidth < 0) { + return; + } + mActualWidth = actualWidth; + ActivatableNotificationView anv = (ActivatableNotificationView) view; + anv.getBackgroundNormal().setActualWidth(actualWidth); + mShelfIcons.setActualLayoutWidth(actualWidth); + } @Override public void applyToView(View view) { @@ -846,19 +948,21 @@ public class NotificationShelf extends ActivatableNotificationView implements updateAppearance(); setHasItemsInStableShelf(hasItemsInStableShelf); mShelfIcons.setAnimationsEnabled(mAnimationsEnabled); + updateShelfWidth(view); } @Override - public void animateTo(View child, AnimationProperties properties) { + public void animateTo(View view, AnimationProperties properties) { if (!mShowNotificationShelf) { return; } - super.animateTo(child, properties); + super.animateTo(view, properties); setIndexOfFirstViewInShelf(firstViewInShelf); updateAppearance(); setHasItemsInStableShelf(hasItemsInStableShelf); mShelfIcons.setAnimationsEnabled(mAnimationsEnabled); + updateShelfWidth(view); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java index 5d6d0f701f12..fca2aa167e37 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java @@ -162,6 +162,13 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView updateBackgroundTint(); } + /** + * @return The background of this view. + */ + public NotificationBackgroundView getBackgroundNormal() { + return mBackgroundNormal; + } + @Override protected void onFinishInflate() { super.onFinishInflate(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java index 0f615aa9356f..c640ab6c3a90 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java @@ -29,6 +29,7 @@ import android.view.View; import com.android.internal.util.ArrayUtils; import com.android.systemui.R; +import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.notification.ExpandAnimationParameters; /** @@ -39,15 +40,17 @@ public class NotificationBackgroundView extends View { private final boolean mDontModifyCorners; private Drawable mBackground; private int mClipTopAmount; - private int mActualHeight; private int mClipBottomAmount; private int mTintColor; private final float[] mCornerRadii = new float[8]; private boolean mBottomIsRounded; private int mBackgroundTop; private boolean mBottomAmountClips = true; + private int mActualHeight = -1; + private int mActualWidth = -1; private boolean mExpandAnimationRunning; - private float mActualWidth; + private int mExpandAnimationWidth = -1; + private int mExpandAnimationHeight = -1; private int mDrawableAlpha = 255; private boolean mIsPressedAllowed; @@ -59,11 +62,12 @@ public class NotificationBackgroundView extends View { @Override protected void onDraw(Canvas canvas) { - if (mClipTopAmount + mClipBottomAmount < mActualHeight - mBackgroundTop + if (mClipTopAmount + mClipBottomAmount < getActualHeight() - mBackgroundTop || mExpandAnimationRunning) { canvas.save(); if (!mExpandAnimationRunning) { - canvas.clipRect(0, mClipTopAmount, getWidth(), mActualHeight - mClipBottomAmount); + canvas.clipRect(0, mClipTopAmount, getWidth(), + getActualHeight() - mClipBottomAmount); } draw(canvas, mBackground); canvas.restore(); @@ -73,17 +77,23 @@ public class NotificationBackgroundView extends View { private void draw(Canvas canvas, Drawable drawable) { if (drawable != null) { int top = mBackgroundTop; - int bottom = mActualHeight; + int bottom = getActualHeight(); if (mBottomIsRounded && mBottomAmountClips && !mExpandAnimationRunning) { bottom -= mClipBottomAmount; } - int left = 0; - int right = getWidth(); + final boolean isRtl = isLayoutRtl(); + final int width = getWidth(); + final int actualWidth = getActualWidth(); + + int left = isRtl ? width - actualWidth : 0; + int right = isRtl ? width : actualWidth; + if (mExpandAnimationRunning) { - left = (int) ((getWidth() - mActualWidth) / 2.0f); - right = (int) (left + mActualWidth); + // Horizontally center this background view inside of the container + left = (int) ((width - actualWidth) / 2.0f); + right = (int) (left + actualWidth); } drawable.setBounds(left, top, right, bottom); drawable.draw(canvas); @@ -152,8 +162,26 @@ public class NotificationBackgroundView extends View { invalidate(); } - public int getActualHeight() { - return mActualHeight; + private int getActualHeight() { + if (mExpandAnimationRunning && mExpandAnimationHeight > -1) { + return mExpandAnimationHeight; + } else if (mActualHeight > -1) { + return mActualHeight; + } + return getHeight(); + } + + public void setActualWidth(int actualWidth) { + mActualWidth = actualWidth; + } + + private int getActualWidth() { + if (mExpandAnimationRunning && mExpandAnimationWidth > -1) { + return mExpandAnimationWidth; + } else if (mActualWidth > -1) { + return mActualWidth; + } + return getWidth(); } public void setClipTopAmount(int clipTopAmount) { @@ -241,9 +269,9 @@ public class NotificationBackgroundView extends View { } /** Set the current expand animation size. */ - public void setExpandAnimationSize(int actualWidth, int actualHeight) { - mActualHeight = actualHeight; - mActualWidth = actualWidth; + public void setExpandAnimationSize(int width, int height) { + mExpandAnimationHeight = width; + mExpandAnimationWidth = height; invalidate(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 9655a9ce5e45..9f6a81d3a9ee 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -5497,6 +5497,17 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } /** + * @param fraction Fraction of the lockscreen to shade transition. 0f for all other states. + * Once the lockscreen to shade transition completes and the shade is 100% open + * LockscreenShadeTransitionController resets fraction to 0 + * where it remains until the next lockscreen-to-shade transition. + */ + public void setFractionToShade(float fraction) { + mShelf.setFractionToShade(fraction); + requestChildrenUpdate(); + } + + /** * Set a listener to when scrolling changes. */ public void setOnScrollListener(Consumer<Integer> listener) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index 0d0e5e850523..334128a2b4ca 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -1515,10 +1515,18 @@ public class NotificationStackScrollLayoutController { } /** - * Set the amount of pixels we have currently dragged down if we're transitioning to the full - * shade. 0.0f means we're not transitioning yet. + * @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. + * + * Once the lockscreen to shade transition completes and the shade is 100% open, + * LockscreenShadeTransitionController resets amount and fraction to 0, where they remain + * until the next lockscreen-to-shade transition. */ - public void setTransitionToFullShadeAmount(float amount) { + public void setTransitionToFullShadeAmount(float amount, float fraction) { + mView.setFractionToShade(fraction); + float extraTopInset = 0.0f; if (mStatusBarStateController.getState() == KEYGUARD) { float overallProgress = MathUtils.saturate(amount / mView.getHeight()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java index c09c48540901..febf2b5b5f24 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java @@ -135,7 +135,8 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout { } }.setDuration(CONTENT_FADE_DURATION); - private static final int MAX_VISIBLE_ICONS_ON_LOCK = 5; + private static final int MAX_ICONS_ON_AOD = 5; + public static final int MAX_ICONS_ON_LOCKSCREEN = 3; public static final int MAX_STATIC_ICONS = 4; private static final int MAX_DOTS = 1; @@ -386,6 +387,19 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout { } /** + * @return Width of shelf for the given number of icons and overflow dot + */ + public int calculateWidthFor(int numMaxIcons) { + if (getChildCount() == 0) { + return 0; + } + return (int) (getActualPaddingStart() + + numMaxIcons * mIconSize + + mOverflowWidth + + getActualPaddingEnd()); + } + + /** * Calculate the horizontal translations for each notification based on how much the icons * are inserted into the notification container. * If this is not a whole number, the fraction means by how much the icon is appearing. @@ -394,7 +408,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout { float translationX = getActualPaddingStart(); int firstOverflowIndex = -1; int childCount = getChildCount(); - int maxVisibleIcons = mOnLockScreen ? MAX_VISIBLE_ICONS_ON_LOCK : + int maxVisibleIcons = mOnLockScreen ? MAX_ICONS_ON_AOD : mIsStaticLayout ? MAX_STATIC_ICONS : childCount; float layoutEnd = getLayoutEnd(); float overflowStart = getMaxOverflowStart(); @@ -414,7 +428,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout { } boolean forceOverflow = mSpeedBumpIndex != -1 && i >= mSpeedBumpIndex && iconState.iconAppearAmount > 0.0f || i >= maxVisibleIcons; - boolean noOverflowAfter = i == childCount - 1; + boolean isLastChild = i == childCount - 1; float drawingScale = mOnLockScreen && view instanceof StatusBarIconView ? ((StatusBarIconView) view).getIconScaleIncreased() : 1f; @@ -423,10 +437,10 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout { : StatusBarIconView.STATE_ICON; boolean isOverflowing = - (translationX > (noOverflowAfter ? layoutEnd - mIconSize + (translationX > (isLastChild ? layoutEnd - mIconSize : overflowStart - mIconSize)); if (firstOverflowIndex == -1 && (forceOverflow || isOverflowing)) { - firstOverflowIndex = noOverflowAfter && !forceOverflow ? i - 1 : i; + firstOverflowIndex = isLastChild && !forceOverflow ? i - 1 : i; mVisualOverflowStart = layoutEnd - mOverflowWidth; if (forceOverflow || mIsStaticLayout) { mVisualOverflowStart = Math.min(translationX, mVisualOverflowStart); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt index 42647f7b026a..d51d370eecb9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt @@ -227,7 +227,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { fun testDragDownAmountDoesntCallOutInLockedDownShade() { whenever(nsslController.isInLockedDownShade).thenReturn(true) transitionController.dragDownAmount = 10f - verify(nsslController, never()).setTransitionToFullShadeAmount(anyFloat()) + verify(nsslController, never()).setTransitionToFullShadeAmount(anyFloat(), anyFloat()) verify(mediaHierarchyManager, never()).setTransitionToFullShadeAmount(anyFloat()) verify(scrimController, never()).setTransitionToFullShadeProgress(anyFloat()) verify(notificationPanelController, never()).setTransitionToFullShadeAmount(anyFloat(), @@ -238,7 +238,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { @Test fun testDragDownAmountCallsOut() { transitionController.dragDownAmount = 10f - verify(nsslController).setTransitionToFullShadeAmount(anyFloat()) + verify(nsslController).setTransitionToFullShadeAmount(anyFloat(), anyFloat()) verify(mediaHierarchyManager).setTransitionToFullShadeAmount(anyFloat()) verify(scrimController).setTransitionToFullShadeProgress(anyFloat()) verify(notificationPanelController).setTransitionToFullShadeAmount(anyFloat(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt new file mode 100644 index 000000000000..d280f54e32f2 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt @@ -0,0 +1,153 @@ +package com.android.systemui.statusbar.notification.stack + +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper.RunWithLooper +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.statusbar.NotificationShelf +import junit.framework.Assert.assertFalse +import junit.framework.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.* +import org.mockito.Mockito.`when` as whenever + +/** + * Tests for {@link NotificationShelf}. + */ +@SmallTest +@RunWith(AndroidTestingRunner::class) +@RunWithLooper +class NotificationShelfTest : SysuiTestCase() { + + private val shelf = NotificationShelf(context, /* attrs */ null) + private val shelfState = shelf.viewState as NotificationShelf.ShelfState + private val ambientState = mock(AmbientState::class.java) + + @Before + fun setUp() { + shelf.bind(ambientState, /* hostLayoutController */ null) + shelf.layout(/* left */ 0, /* top */ 0, /* right */ 30, /* bottom */5) + } + + @Test + fun testShadeWidth_BasedOnFractionToShade() { + setFractionToShade(0f) + setOnLockscreen(true) + + shelf.updateStateWidth(shelfState, /* fraction */ 0f, /* shortestWidth */ 10) + assertTrue(shelfState.actualWidth == 10) + + shelf.updateStateWidth(shelfState, /* fraction */ 0.5f, /* shortestWidth */ 10) + assertTrue(shelfState.actualWidth == 20) + + shelf.updateStateWidth(shelfState, /* fraction */ 1f, /* shortestWidth */ 10) + assertTrue(shelfState.actualWidth == 30) + } + + @Test + fun testShelfIsLong_WhenNotOnLockscreen() { + setFractionToShade(0f) + setOnLockscreen(false) + + shelf.updateStateWidth(shelfState, /* fraction */ 0f, /* shortestWidth */ 10) + assertTrue(shelfState.actualWidth == 30) + } + + @Test + fun testX_inViewForClick() { + val isXInView = shelf.isXInView( + /* localX */ 5f, + /* slop */ 5f, + /* left */ 0f, + /* right */ 10f) + assertTrue(isXInView) + } + + @Test + fun testXSlop_inViewForClick() { + val isLeftXSlopInView = shelf.isXInView( + /* localX */ -3f, + /* slop */ 5f, + /* left */ 0f, + /* right */ 10f) + assertTrue(isLeftXSlopInView) + + val isRightXSlopInView = shelf.isXInView( + /* localX */ 13f, + /* slop */ 5f, + /* left */ 0f, + /* right */ 10f) + assertTrue(isRightXSlopInView) + } + + @Test + fun testX_notInViewForClick() { + val isXLeftOfShelfInView = shelf.isXInView( + /* localX */ -10f, + /* slop */ 5f, + /* left */ 0f, + /* right */ 10f) + assertFalse(isXLeftOfShelfInView) + + val isXRightOfShelfInView = shelf.isXInView( + /* localX */ 20f, + /* slop */ 5f, + /* left */ 0f, + /* right */ 10f) + assertFalse(isXRightOfShelfInView) + } + + @Test + fun testY_inViewForClick() { + val isYInView = shelf.isYInView( + /* localY */ 5f, + /* slop */ 5f, + /* top */ 0f, + /* bottom */ 10f) + assertTrue(isYInView) + } + + @Test + fun testYSlop_inViewForClick() { + val isTopYSlopInView = shelf.isYInView( + /* localY */ -3f, + /* slop */ 5f, + /* top */ 0f, + /* bottom */ 10f) + assertTrue(isTopYSlopInView) + + val isBottomYSlopInView = shelf.isYInView( + /* localY */ 13f, + /* slop */ 5f, + /* top */ 0f, + /* bottom */ 10f) + assertTrue(isBottomYSlopInView) + } + + @Test + fun testY_notInViewForClick() { + val isYAboveShelfInView = shelf.isYInView( + /* localY */ -10f, + /* slop */ 5f, + /* top */ 0f, + /* bottom */ 5f) + assertFalse(isYAboveShelfInView) + + val isYBelowShelfInView = shelf.isYInView( + /* localY */ 15f, + /* slop */ 5f, + /* top */ 0f, + /* bottom */ 5f) + assertFalse(isYBelowShelfInView) + } + + private fun setFractionToShade(fraction: Float) { + shelf.setFractionToShade(fraction) + } + + private fun setOnLockscreen(isOnLockscreen: Boolean) { + whenever(ambientState.isOnKeyguard).thenReturn(isOnLockscreen) + } +}
\ No newline at end of file |