Merge "Fix one-icon shelf flicker on lockscreen swipe-up" into tm-dev am: 49fa2fb7c5
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18133237 Change-Id: Ice844e13772fdca2ec8cd27f66725f6d001bea45 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -326,9 +326,9 @@ public class NotificationShelf extends ActivatableNotificationView implements
|
|||||||
|| child.isPinned();
|
|| child.isPinned();
|
||||||
boolean isLastChild = child == lastChild;
|
boolean isLastChild = child == lastChild;
|
||||||
final float viewStart = child.getTranslationY();
|
final float viewStart = child.getTranslationY();
|
||||||
|
final float shelfClipStart = getTranslationY() - mPaddingBetweenElements;
|
||||||
final float inShelfAmount = updateShelfTransformation(i, child, scrollingFast,
|
final float inShelfAmount = getAmountInShelf(i, child, scrollingFast,
|
||||||
expandingAnimated, isLastChild);
|
expandingAnimated, isLastChild, shelfClipStart);
|
||||||
|
|
||||||
// TODO(b/172289889) scale mPaddingBetweenElements with expansion amount
|
// TODO(b/172289889) scale mPaddingBetweenElements with expansion amount
|
||||||
if ((isLastChild && !child.isInShelf()) || aboveShelf || backgroundForceHidden) {
|
if ((isLastChild && !child.isInShelf()) || aboveShelf || backgroundForceHidden) {
|
||||||
@@ -609,10 +609,18 @@ public class NotificationShelf extends ActivatableNotificationView implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the amount how much this notification is in the shelf
|
* @param i Index of the view in the host layout.
|
||||||
|
* @param view The current ExpandableView.
|
||||||
|
* @param scrollingFast Whether we are scrolling fast.
|
||||||
|
* @param expandingAnimated Whether we are expanding a notification.
|
||||||
|
* @param isLastChild Whether this is the last view.
|
||||||
|
* @param shelfClipStart The point at which notifications start getting clipped by the shelf.
|
||||||
|
* @return The amount how much this notification is in the shelf.
|
||||||
|
* 0f is not in shelf. 1f is completely in shelf.
|
||||||
*/
|
*/
|
||||||
private float updateShelfTransformation(int i, ExpandableView view, boolean scrollingFast,
|
@VisibleForTesting
|
||||||
boolean expandingAnimated, boolean isLastChild) {
|
public float getAmountInShelf(int i, ExpandableView view, boolean scrollingFast,
|
||||||
|
boolean expandingAnimated, boolean isLastChild, float shelfClipStart) {
|
||||||
|
|
||||||
// Let's calculate how much the view is in the shelf
|
// Let's calculate how much the view is in the shelf
|
||||||
float viewStart = view.getTranslationY();
|
float viewStart = view.getTranslationY();
|
||||||
@@ -635,29 +643,33 @@ public class NotificationShelf extends ActivatableNotificationView implements
|
|||||||
float viewEnd = viewStart + fullHeight;
|
float viewEnd = viewStart + fullHeight;
|
||||||
float fullTransitionAmount = 0.0f;
|
float fullTransitionAmount = 0.0f;
|
||||||
float iconTransitionAmount = 0.0f;
|
float iconTransitionAmount = 0.0f;
|
||||||
float shelfStart = getTranslationY() - mPaddingBetweenElements;
|
|
||||||
|
// Don't animate shelf icons during shade expansion.
|
||||||
if (mAmbientState.isExpansionChanging() && !mAmbientState.isOnKeyguard()) {
|
if (mAmbientState.isExpansionChanging() && !mAmbientState.isOnKeyguard()) {
|
||||||
// TODO(b/172289889) handle icon placement for notification that is clipped by the shelf
|
// TODO(b/172289889) handle icon placement for notification that is clipped by the shelf
|
||||||
if (mIndexOfFirstViewInShelf != -1 && i >= mIndexOfFirstViewInShelf) {
|
if (mIndexOfFirstViewInShelf != -1 && i >= mIndexOfFirstViewInShelf) {
|
||||||
fullTransitionAmount = 1f;
|
fullTransitionAmount = 1f;
|
||||||
iconTransitionAmount = 1f;
|
iconTransitionAmount = 1f;
|
||||||
}
|
}
|
||||||
} else if (viewEnd >= shelfStart
|
|
||||||
|
} else if (viewEnd >= shelfClipStart
|
||||||
&& (!mAmbientState.isUnlockHintRunning() || view.isInShelf())
|
&& (!mAmbientState.isUnlockHintRunning() || view.isInShelf())
|
||||||
&& (mAmbientState.isShadeExpanded()
|
&& (mAmbientState.isShadeExpanded()
|
||||||
|| (!view.isPinned() && !view.isHeadsUpAnimatingAway()))) {
|
|| (!view.isPinned() && !view.isHeadsUpAnimatingAway()))) {
|
||||||
|
|
||||||
if (viewStart < shelfStart) {
|
if (viewStart < shelfClipStart && Math.abs(viewStart - shelfClipStart) > 0.001f) {
|
||||||
float fullAmount = (shelfStart - viewStart) / fullHeight;
|
// Partially clipped by shelf.
|
||||||
|
float fullAmount = (shelfClipStart - viewStart) / fullHeight;
|
||||||
fullAmount = Math.min(1.0f, fullAmount);
|
fullAmount = Math.min(1.0f, fullAmount);
|
||||||
fullTransitionAmount = 1.0f - fullAmount;
|
fullTransitionAmount = 1.0f - fullAmount;
|
||||||
if (isLastChild) {
|
if (isLastChild) {
|
||||||
// Reduce icon transform distance to completely fade in shelf icon
|
// Reduce icon transform distance to completely fade in shelf icon
|
||||||
// by the time the notification icon fades out, and vice versa
|
// by the time the notification icon fades out, and vice versa
|
||||||
iconTransitionAmount = (shelfStart - viewStart)
|
iconTransitionAmount = (shelfClipStart - viewStart)
|
||||||
/ (iconTransformStart - viewStart);
|
/ (iconTransformStart - viewStart);
|
||||||
} else {
|
} else {
|
||||||
iconTransitionAmount = (shelfStart - iconTransformStart) / transformDistance;
|
iconTransitionAmount = (shelfClipStart - iconTransformStart)
|
||||||
|
/ transformDistance;
|
||||||
}
|
}
|
||||||
iconTransitionAmount = MathUtils.constrain(iconTransitionAmount, 0.0f, 1.0f);
|
iconTransitionAmount = MathUtils.constrain(iconTransitionAmount, 0.0f, 1.0f);
|
||||||
iconTransitionAmount = 1.0f - iconTransitionAmount;
|
iconTransitionAmount = 1.0f - iconTransitionAmount;
|
||||||
@@ -772,6 +784,9 @@ public class NotificationShelf extends ActivatableNotificationView implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
private NotificationIconContainer.IconState getIconState(StatusBarIconView icon) {
|
private NotificationIconContainer.IconState getIconState(StatusBarIconView icon) {
|
||||||
|
if (mShelfIcons == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return mShelfIcons.getIconState(icon);
|
return mShelfIcons.getIconState(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ import android.testing.TestableLooper.RunWithLooper
|
|||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.statusbar.NotificationShelf
|
import com.android.systemui.statusbar.NotificationShelf
|
||||||
import junit.framework.Assert.assertFalse
|
import com.android.systemui.statusbar.StatusBarIconView
|
||||||
import junit.framework.Assert.assertTrue
|
import com.android.systemui.statusbar.notification.row.ExpandableView
|
||||||
|
import junit.framework.Assert.*
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
@@ -143,6 +144,113 @@ class NotificationShelfTest : SysuiTestCase() {
|
|||||||
assertFalse(isYBelowShelfInView)
|
assertFalse(isYBelowShelfInView)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getAmountInShelf_lastViewBelowShelf_completelyInShelf() {
|
||||||
|
val shelfClipStart = 0f
|
||||||
|
val viewStart = 1f
|
||||||
|
|
||||||
|
val expandableView = mock(ExpandableView::class.java)
|
||||||
|
whenever(expandableView.shelfIcon).thenReturn(mock(StatusBarIconView::class.java))
|
||||||
|
whenever(expandableView.translationY).thenReturn(viewStart)
|
||||||
|
whenever(expandableView.actualHeight).thenReturn(20)
|
||||||
|
|
||||||
|
whenever(expandableView.minHeight).thenReturn(20)
|
||||||
|
whenever(expandableView.shelfTransformationTarget).thenReturn(null) // use translationY
|
||||||
|
whenever(expandableView.isInShelf).thenReturn(true)
|
||||||
|
|
||||||
|
whenever(ambientState.isOnKeyguard).thenReturn(true)
|
||||||
|
whenever(ambientState.isExpansionChanging).thenReturn(false)
|
||||||
|
whenever(ambientState.isShadeExpanded).thenReturn(true)
|
||||||
|
|
||||||
|
val amountInShelf = shelf.getAmountInShelf(/* i= */ 0,
|
||||||
|
/* view= */ expandableView,
|
||||||
|
/* scrollingFast= */ false,
|
||||||
|
/* expandingAnimated= */ false,
|
||||||
|
/* isLastChild= */ true,
|
||||||
|
shelfClipStart)
|
||||||
|
assertEquals(1f, amountInShelf)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getAmountInShelf_lastViewAlmostBelowShelf_completelyInShelf() {
|
||||||
|
val viewStart = 0f
|
||||||
|
val shelfClipStart = 0.001f
|
||||||
|
|
||||||
|
val expandableView = mock(ExpandableView::class.java)
|
||||||
|
whenever(expandableView.shelfIcon).thenReturn(mock(StatusBarIconView::class.java))
|
||||||
|
whenever(expandableView.translationY).thenReturn(viewStart)
|
||||||
|
whenever(expandableView.actualHeight).thenReturn(20)
|
||||||
|
|
||||||
|
whenever(expandableView.minHeight).thenReturn(20)
|
||||||
|
whenever(expandableView.shelfTransformationTarget).thenReturn(null) // use translationY
|
||||||
|
whenever(expandableView.isInShelf).thenReturn(true)
|
||||||
|
|
||||||
|
whenever(ambientState.isOnKeyguard).thenReturn(true)
|
||||||
|
whenever(ambientState.isExpansionChanging).thenReturn(false)
|
||||||
|
whenever(ambientState.isShadeExpanded).thenReturn(true)
|
||||||
|
|
||||||
|
val amountInShelf = shelf.getAmountInShelf(/* i= */ 0,
|
||||||
|
/* view= */ expandableView,
|
||||||
|
/* scrollingFast= */ false,
|
||||||
|
/* expandingAnimated= */ false,
|
||||||
|
/* isLastChild= */ true,
|
||||||
|
shelfClipStart)
|
||||||
|
assertEquals(1f, amountInShelf)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getAmountInShelf_lastViewHalfClippedByShelf_halfInShelf() {
|
||||||
|
val viewStart = 0f
|
||||||
|
val shelfClipStart = 10f
|
||||||
|
|
||||||
|
val expandableView = mock(ExpandableView::class.java)
|
||||||
|
whenever(expandableView.shelfIcon).thenReturn(mock(StatusBarIconView::class.java))
|
||||||
|
whenever(expandableView.translationY).thenReturn(viewStart)
|
||||||
|
whenever(expandableView.actualHeight).thenReturn(25)
|
||||||
|
|
||||||
|
whenever(expandableView.minHeight).thenReturn(25)
|
||||||
|
whenever(expandableView.shelfTransformationTarget).thenReturn(null) // use translationY
|
||||||
|
whenever(expandableView.isInShelf).thenReturn(true)
|
||||||
|
|
||||||
|
whenever(ambientState.isOnKeyguard).thenReturn(true)
|
||||||
|
whenever(ambientState.isExpansionChanging).thenReturn(false)
|
||||||
|
whenever(ambientState.isShadeExpanded).thenReturn(true)
|
||||||
|
|
||||||
|
val amountInShelf = shelf.getAmountInShelf(/* i= */ 0,
|
||||||
|
/* view= */ expandableView,
|
||||||
|
/* scrollingFast= */ false,
|
||||||
|
/* expandingAnimated= */ false,
|
||||||
|
/* isLastChild= */ true,
|
||||||
|
shelfClipStart)
|
||||||
|
assertEquals(0.5f, amountInShelf)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getAmountInShelf_lastViewAboveShelf_notInShelf() {
|
||||||
|
val viewStart = 0f
|
||||||
|
val shelfClipStart = 15f
|
||||||
|
|
||||||
|
val expandableView = mock(ExpandableView::class.java)
|
||||||
|
whenever(expandableView.shelfIcon).thenReturn(mock(StatusBarIconView::class.java))
|
||||||
|
whenever(expandableView.translationY).thenReturn(viewStart)
|
||||||
|
whenever(expandableView.actualHeight).thenReturn(10)
|
||||||
|
|
||||||
|
whenever(expandableView.minHeight).thenReturn(10)
|
||||||
|
whenever(expandableView.shelfTransformationTarget).thenReturn(null) // use translationY
|
||||||
|
whenever(expandableView.isInShelf).thenReturn(false)
|
||||||
|
|
||||||
|
whenever(ambientState.isExpansionChanging).thenReturn(false)
|
||||||
|
whenever(ambientState.isOnKeyguard).thenReturn(true)
|
||||||
|
|
||||||
|
val amountInShelf = shelf.getAmountInShelf(/* i= */ 0,
|
||||||
|
/* view= */ expandableView,
|
||||||
|
/* scrollingFast= */ false,
|
||||||
|
/* expandingAnimated= */ false,
|
||||||
|
/* isLastChild= */ true,
|
||||||
|
shelfClipStart)
|
||||||
|
assertEquals(0f, amountInShelf)
|
||||||
|
}
|
||||||
|
|
||||||
private fun setFractionToShade(fraction: Float) {
|
private fun setFractionToShade(fraction: Float) {
|
||||||
whenever(ambientState.fractionToShade).thenReturn(fraction)
|
whenever(ambientState.fractionToShade).thenReturn(fraction)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user