Merge "Move "max to height" roundness logic to Roundable.kt" into udc-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
b5efe93950
@@ -3,7 +3,10 @@ package com.android.systemui.statusbar.notification
|
||||
import android.util.FloatProperty
|
||||
import android.view.View
|
||||
import androidx.annotation.FloatRange
|
||||
import com.android.systemui.Dependency
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
import com.android.systemui.flags.Flags
|
||||
import com.android.systemui.statusbar.notification.stack.AnimationProperties
|
||||
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
|
||||
import kotlin.math.abs
|
||||
@@ -20,6 +23,8 @@ interface Roundable {
|
||||
/** Properties required for a Roundable */
|
||||
val roundableState: RoundableState
|
||||
|
||||
val clipHeight: Int
|
||||
|
||||
/** Current top roundness */
|
||||
@get:FloatRange(from = 0.0, to = 1.0)
|
||||
@JvmDefault
|
||||
@@ -40,12 +45,16 @@ interface Roundable {
|
||||
/** Current top corner in pixel, based on [topRoundness] and [maxRadius] */
|
||||
@JvmDefault
|
||||
val topCornerRadius: Float
|
||||
get() = topRoundness * maxRadius
|
||||
get() =
|
||||
if (roundableState.newHeadsUpAnimFlagEnabled) roundableState.topCornerRadius
|
||||
else topRoundness * maxRadius
|
||||
|
||||
/** Current bottom corner in pixel, based on [bottomRoundness] and [maxRadius] */
|
||||
@JvmDefault
|
||||
val bottomCornerRadius: Float
|
||||
get() = bottomRoundness * maxRadius
|
||||
get() =
|
||||
if (roundableState.newHeadsUpAnimFlagEnabled) roundableState.bottomCornerRadius
|
||||
else bottomRoundness * maxRadius
|
||||
|
||||
/** Get and update the current radii */
|
||||
@JvmDefault
|
||||
@@ -320,14 +329,20 @@ interface Roundable {
|
||||
* @param roundable Target of the radius animation
|
||||
* @param maxRadius Max corner radius in pixels
|
||||
*/
|
||||
class RoundableState(
|
||||
class RoundableState
|
||||
@JvmOverloads
|
||||
constructor(
|
||||
internal val targetView: View,
|
||||
private val roundable: Roundable,
|
||||
maxRadius: Float,
|
||||
private val featureFlags: FeatureFlags = Dependency.get(FeatureFlags::class.java)
|
||||
) {
|
||||
internal var maxRadius = maxRadius
|
||||
private set
|
||||
|
||||
internal val newHeadsUpAnimFlagEnabled
|
||||
get() = featureFlags.isEnabled(Flags.IMPROVED_HUN_ANIMATIONS)
|
||||
|
||||
/** Animatable for top roundness */
|
||||
private val topAnimatable = topAnimatable(roundable)
|
||||
|
||||
@@ -344,6 +359,41 @@ class RoundableState(
|
||||
internal var bottomRoundness = 0f
|
||||
private set
|
||||
|
||||
internal val topCornerRadius: Float
|
||||
get() {
|
||||
val height = roundable.clipHeight
|
||||
val topRadius = topRoundness * maxRadius
|
||||
val bottomRadius = bottomRoundness * maxRadius
|
||||
|
||||
if (height == 0) {
|
||||
return 0f
|
||||
} else if (topRadius + bottomRadius > height) {
|
||||
// The sum of top and bottom corner radii should be at max the clipped height
|
||||
val overShoot = topRadius + bottomRadius - height
|
||||
return topRadius - (overShoot * topRoundness / (topRoundness + bottomRoundness))
|
||||
}
|
||||
|
||||
return topRadius
|
||||
}
|
||||
|
||||
internal val bottomCornerRadius: Float
|
||||
get() {
|
||||
val height = roundable.clipHeight
|
||||
val topRadius = topRoundness * maxRadius
|
||||
val bottomRadius = bottomRoundness * maxRadius
|
||||
|
||||
if (height == 0) {
|
||||
return 0f
|
||||
} else if (topRadius + bottomRadius > height) {
|
||||
// The sum of top and bottom corner radii should be at max the clipped height
|
||||
val overShoot = topRadius + bottomRadius - height
|
||||
return bottomRadius -
|
||||
(overShoot * bottomRoundness / (topRoundness + bottomRoundness))
|
||||
}
|
||||
|
||||
return bottomRadius
|
||||
}
|
||||
|
||||
/** Last requested top roundness associated by [SourceType] */
|
||||
internal val topRoundnessMap = mutableMapOf<SourceType, Float>()
|
||||
|
||||
|
||||
@@ -566,12 +566,20 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
|
||||
|
||||
@Override
|
||||
public float getTopCornerRadius() {
|
||||
if (isNewHeadsUpAnimFlagEnabled()) {
|
||||
return super.getTopCornerRadius();
|
||||
}
|
||||
|
||||
float fraction = getInterpolatedAppearAnimationFraction();
|
||||
return MathUtils.lerp(0, super.getTopCornerRadius(), fraction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getBottomCornerRadius() {
|
||||
if (isNewHeadsUpAnimFlagEnabled()) {
|
||||
return super.getBottomCornerRadius();
|
||||
}
|
||||
|
||||
float fraction = getInterpolatedAppearAnimationFraction();
|
||||
return MathUtils.lerp(0, super.getBottomCornerRadius(), fraction);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,10 @@ import android.util.IndentingPrintWriter;
|
||||
import android.view.View;
|
||||
import android.view.ViewOutlineProvider;
|
||||
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.flags.FeatureFlags;
|
||||
import com.android.systemui.flags.Flags;
|
||||
import com.android.systemui.statusbar.notification.RoundableState;
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
|
||||
import com.android.systemui.util.DumpUtilsKt;
|
||||
@@ -47,12 +50,14 @@ public abstract class ExpandableOutlineView extends ExpandableView {
|
||||
private float mOutlineAlpha = -1f;
|
||||
private boolean mAlwaysRoundBothCorners;
|
||||
private Path mTmpPath = new Path();
|
||||
private final FeatureFlags mFeatureFlags;
|
||||
|
||||
/**
|
||||
* {@code false} if the children views of the {@link ExpandableOutlineView} are translated when
|
||||
* it is moved. Otherwise, the translation is set on the {@code ExpandableOutlineView} itself.
|
||||
*/
|
||||
protected boolean mDismissUsingRowTranslationX = true;
|
||||
|
||||
private float[] mTmpCornerRadii = new float[8];
|
||||
|
||||
private final ViewOutlineProvider mProvider = new ViewOutlineProvider() {
|
||||
@@ -81,6 +86,15 @@ public abstract class ExpandableOutlineView extends ExpandableView {
|
||||
return mRoundableState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getClipHeight() {
|
||||
if (mCustomOutline) {
|
||||
return mOutlineRect.height();
|
||||
}
|
||||
|
||||
return super.getClipHeight();
|
||||
}
|
||||
|
||||
protected Path getClipPath(boolean ignoreTranslation) {
|
||||
int left;
|
||||
int top;
|
||||
@@ -112,7 +126,7 @@ public abstract class ExpandableOutlineView extends ExpandableView {
|
||||
return EMPTY_PATH;
|
||||
}
|
||||
float bottomRadius = mAlwaysRoundBothCorners ? getMaxRadius() : getBottomCornerRadius();
|
||||
if (topRadius + bottomRadius > height) {
|
||||
if (!isNewHeadsUpAnimFlagEnabled() && (topRadius + bottomRadius > height)) {
|
||||
float overShoot = topRadius + bottomRadius - height;
|
||||
float currentTopRoundness = getTopRoundness();
|
||||
float currentBottomRoundness = getBottomRoundness();
|
||||
@@ -153,6 +167,7 @@ public abstract class ExpandableOutlineView extends ExpandableView {
|
||||
super(context, attrs);
|
||||
setOutlineProvider(mProvider);
|
||||
initDimens();
|
||||
mFeatureFlags = Dependency.get(FeatureFlags.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -360,4 +375,9 @@ public abstract class ExpandableOutlineView extends ExpandableView {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// TODO(b/290365128) replace with ViewRefactorFlag
|
||||
protected boolean isNewHeadsUpAnimFlagEnabled() {
|
||||
return mFeatureFlags.isEnabled(Flags.IMPROVED_HUN_ANIMATIONS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,6 +93,12 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable, Ro
|
||||
return mRoundableState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getClipHeight() {
|
||||
int clipHeight = Math.max(mActualHeight - mClipTopAmount - mClipBottomAmount, 0);
|
||||
return Math.max(clipHeight, mMinimumHeightForClipping);
|
||||
}
|
||||
|
||||
private void initDimens() {
|
||||
mContentShift = getResources().getDimensionPixelSize(
|
||||
R.dimen.shelf_transform_content_shift);
|
||||
|
||||
@@ -119,6 +119,11 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper imple
|
||||
return mRoundableState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getClipHeight() {
|
||||
return mView.getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyRoundnessAndInvalidate() {
|
||||
if (mRoundnessChangedListener != null) {
|
||||
|
||||
@@ -30,8 +30,8 @@ import com.android.systemui.statusbar.notification.row.ExpandableView
|
||||
*/
|
||||
class MediaContainerView(context: Context, attrs: AttributeSet?) : ExpandableView(context, attrs) {
|
||||
|
||||
override var clipHeight = 0
|
||||
var cornerRadius = 0f
|
||||
var clipHeight = 0
|
||||
var clipRect = RectF()
|
||||
var clipPath = Path()
|
||||
|
||||
|
||||
@@ -191,6 +191,11 @@ public class NotificationChildrenContainer extends ViewGroup
|
||||
return mRoundableState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getClipHeight() {
|
||||
return Math.max(mActualHeight - mClipBottomAmount, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
int childCount =
|
||||
|
||||
@@ -3,7 +3,11 @@ package com.android.systemui.statusbar.notification
|
||||
import android.view.View
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.flags.FakeFeatureFlags
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
import com.android.systemui.flags.Flags
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.util.mockito.whenever
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -15,8 +19,9 @@ import org.mockito.Mockito.verify
|
||||
@SmallTest
|
||||
@RunWith(JUnit4::class)
|
||||
class RoundableTest : SysuiTestCase() {
|
||||
val targetView: View = mock()
|
||||
val roundable = FakeRoundable(targetView)
|
||||
private val targetView: View = mock()
|
||||
private val featureFlags = FakeFeatureFlags()
|
||||
private val roundable = FakeRoundable(targetView = targetView, featureFlags = featureFlags)
|
||||
|
||||
@Test
|
||||
fun defaultConfig_shouldNotHaveRoundedCorner() {
|
||||
@@ -144,16 +149,62 @@ class RoundableTest : SysuiTestCase() {
|
||||
assertEquals(0.2f, roundable.roundableState.bottomRoundness)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getCornerRadii_radius_maxed_to_height() {
|
||||
whenever(targetView.height).thenReturn(10)
|
||||
featureFlags.set(Flags.IMPROVED_HUN_ANIMATIONS, true)
|
||||
roundable.requestRoundness(1f, 1f, SOURCE1)
|
||||
|
||||
assertCornerRadiiEquals(5f, 5f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getCornerRadii_topRadius_maxed_to_height() {
|
||||
whenever(targetView.height).thenReturn(5)
|
||||
featureFlags.set(Flags.IMPROVED_HUN_ANIMATIONS, true)
|
||||
roundable.requestRoundness(1f, 0f, SOURCE1)
|
||||
|
||||
assertCornerRadiiEquals(5f, 0f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getCornerRadii_bottomRadius_maxed_to_height() {
|
||||
whenever(targetView.height).thenReturn(5)
|
||||
featureFlags.set(Flags.IMPROVED_HUN_ANIMATIONS, true)
|
||||
roundable.requestRoundness(0f, 1f, SOURCE1)
|
||||
|
||||
assertCornerRadiiEquals(0f, 5f)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getCornerRadii_radii_kept() {
|
||||
whenever(targetView.height).thenReturn(100)
|
||||
featureFlags.set(Flags.IMPROVED_HUN_ANIMATIONS, true)
|
||||
roundable.requestRoundness(1f, 1f, SOURCE1)
|
||||
|
||||
assertCornerRadiiEquals(MAX_RADIUS, MAX_RADIUS)
|
||||
}
|
||||
|
||||
private fun assertCornerRadiiEquals(top: Float, bottom: Float) {
|
||||
assertEquals("topCornerRadius", top, roundable.topCornerRadius)
|
||||
assertEquals("bottomCornerRadius", bottom, roundable.bottomCornerRadius)
|
||||
}
|
||||
|
||||
class FakeRoundable(
|
||||
targetView: View,
|
||||
radius: Float = MAX_RADIUS,
|
||||
featureFlags: FeatureFlags
|
||||
) : Roundable {
|
||||
override val roundableState =
|
||||
RoundableState(
|
||||
targetView = targetView,
|
||||
roundable = this,
|
||||
maxRadius = radius,
|
||||
featureFlags = featureFlags
|
||||
)
|
||||
|
||||
override val clipHeight: Int
|
||||
get() = roundableState.targetView.height
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
Reference in New Issue
Block a user