Merge "Move "max to height" roundness logic to Roundable.kt" into udc-qpr-dev

This commit is contained in:
András Kurucz
2023-07-12 16:28:55 +00:00
committed by Android (Google) Code Review
8 changed files with 152 additions and 7 deletions

View File

@@ -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>()

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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()

View File

@@ -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 =

View File

@@ -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 {