From 0b558b4fe06eeb577c20774d1e716a2092e91477 Mon Sep 17 00:00:00 2001 From: Hawkwood Glazier Date: Wed, 24 May 2023 14:59:30 +0000 Subject: [PATCH] Translate and Scale the status area with the large weather clock This is intended to better position smartspace when using the weather clock on certain devices, but does this by adjusting the entire status area. In practice this is fine as smartspace is the only child view that's rendered in this case. Bug: 283308908 Test: Manually checked on several device Change-Id: I75378c6a2732f8486eef49b91a1c24caed002f1a Merged-In: I75378c6a2732f8486eef49b91a1c24caed002f1a --- .../layout/keyguard_clock_switch.xml | 4 +- .../values-sw600dp-land/integers.xml | 2 +- .../SystemUI/res-keyguard/values/dimens.xml | 5 + packages/SystemUI/res-keyguard/values/ids.xml | 14 +++ .../UnfoldConstantTranslateAnimator.kt | 15 ++- .../android/keyguard/KeyguardClockSwitch.java | 78 ++++++++++-- .../KeyguardClockSwitchController.java | 14 ++- .../keyguard/KeyguardStatusAreaView.kt | 118 ++++++++++++++++++ .../KeyguardStatusViewController.java | 6 +- .../keyguard/KeyguardUnfoldTransition.kt | 5 +- .../keyguard/KeyguardClockSwitchTest.java | 29 +++++ .../keyguard/KeyguardStatusAreaViewTest.kt | 44 +++++++ 12 files changed, 310 insertions(+), 24 deletions(-) create mode 100644 packages/SystemUI/src/com/android/keyguard/KeyguardStatusAreaView.kt create mode 100644 packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusAreaViewTest.kt diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml index 3fc0965f4a813..fc9c917c152bb 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml @@ -43,7 +43,7 @@ - - + diff --git a/packages/SystemUI/res-keyguard/values-sw600dp-land/integers.xml b/packages/SystemUI/res-keyguard/values-sw600dp-land/integers.xml index 2a8092010a376..3d1cb5ee6177e 100644 --- a/packages/SystemUI/res-keyguard/values-sw600dp-land/integers.xml +++ b/packages/SystemUI/res-keyguard/values-sw600dp-land/integers.xml @@ -16,5 +16,5 @@ --> - 8 + 4 diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml index 4b79689534204..39dd90e5ed60f 100644 --- a/packages/SystemUI/res-keyguard/values/dimens.xml +++ b/packages/SystemUI/res-keyguard/values/dimens.xml @@ -148,4 +148,9 @@ 34dp 0dp + + 1.0 + 0dp + 0dp + diff --git a/packages/SystemUI/res-keyguard/values/ids.xml b/packages/SystemUI/res-keyguard/values/ids.xml index 0dff4ffa38662..1435907eaef68 100644 --- a/packages/SystemUI/res-keyguard/values/ids.xml +++ b/packages/SystemUI/res-keyguard/values/ids.xml @@ -17,4 +17,18 @@ + + + + + + + + + + + + + + diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt index c5979cc50c3c4..7a8c82cee32ac 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt @@ -65,8 +65,8 @@ class UnfoldConstantTranslateAnimator( } else { 1 } - viewsToTranslate.forEach { (view, direction) -> - view.get()?.translationX = xTrans * direction.multiplier * rtlMultiplier + viewsToTranslate.forEach { (view, direction, func) -> + view.get()?.let { func(it, xTrans * direction.multiplier * rtlMultiplier) } } } @@ -77,7 +77,7 @@ class UnfoldConstantTranslateAnimator( .filter { it.shouldBeAnimated() } .mapNotNull { parent.findViewById(it.viewId)?.let { view -> - ViewToTranslate(WeakReference(view), it.direction) + ViewToTranslate(WeakReference(view), it.direction, it.translateFunc) } } .toList() @@ -91,14 +91,19 @@ class UnfoldConstantTranslateAnimator( data class ViewIdToTranslate( val viewId: Int, val direction: Direction, - val shouldBeAnimated: () -> Boolean = { true } + val shouldBeAnimated: () -> Boolean = { true }, + val translateFunc: (View, Float) -> Unit = { view, value -> view.translationX = value }, ) /** * Represents a view whose animation process is in-progress. It should be immutable because the * started animation should be completed. */ - private data class ViewToTranslate(val view: WeakReference, val direction: Direction) + private data class ViewToTranslate( + val view: WeakReference, + val direction: Direction, + val translateFunc: (View, Float) -> Unit, + ) /** Direction of the animation. */ enum class Direction(val multiplier: Float) { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java index d9d64ad5a8937..376e27c6cf448 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java @@ -1,8 +1,14 @@ package com.android.keyguard; import static android.view.View.ALPHA; +import static android.view.View.SCALE_X; +import static android.view.View.SCALE_Y; import static android.view.View.TRANSLATION_Y; +import static com.android.keyguard.KeyguardStatusAreaView.TRANSLATE_X_CLOCK_DESIGN; +import static com.android.keyguard.KeyguardStatusAreaView.TRANSLATE_Y_CLOCK_DESIGN; +import static com.android.keyguard.KeyguardStatusAreaView.TRANSLATE_Y_CLOCK_SIZE; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; @@ -17,6 +23,7 @@ import android.widget.RelativeLayout; import androidx.annotation.IntDef; import androidx.annotation.VisibleForTesting; +import androidx.core.content.res.ResourcesCompat; import com.android.app.animation.Interpolators; import com.android.keyguard.dagger.KeyguardStatusViewScope; @@ -44,6 +51,7 @@ public class KeyguardClockSwitch extends RelativeLayout { private static final long STATUS_AREA_START_DELAY_MILLIS = 0; private static final long STATUS_AREA_MOVE_UP_MILLIS = 967; private static final long STATUS_AREA_MOVE_DOWN_MILLIS = 467; + private static final float SMARTSPACE_TRANSLATION_CENTER_MULTIPLIER = 1.4f; @IntDef({LARGE, SMALL}) @Retention(RetentionPolicy.SOURCE) @@ -88,14 +96,18 @@ public class KeyguardClockSwitch extends RelativeLayout { private KeyguardClockFrame mLargeClockFrame; private ClockController mClock; - private View mStatusArea; + private KeyguardStatusAreaView mStatusArea; private int mSmartspaceTopOffset; + private float mWeatherClockSmartspaceScaling = 1f; + private int mWeatherClockSmartspaceTranslateX = 0; + private int mWeatherClockSmartspaceTranslateY = 0; private int mDrawAlpha = 255; /** * Maintain state so that a newly connected plugin can be initialized. */ private float mDarkAmount; + private boolean mSplitShadeCentered = false; /** * Indicates which clock is currently displayed - should be one of {@link ClockSize}. @@ -105,7 +117,7 @@ public class KeyguardClockSwitch extends RelativeLayout { @VisibleForTesting AnimatorSet mClockInAnim = null; @VisibleForTesting AnimatorSet mClockOutAnim = null; - private AnimatorSet mStatusAreaAnim = null; + @VisibleForTesting AnimatorSet mStatusAreaAnim = null; private int mClockSwitchYAmount; @VisibleForTesting boolean mChildrenAreLaidOut = false; @@ -117,13 +129,30 @@ public class KeyguardClockSwitch extends RelativeLayout { } /** - * Apply dp changes on font/scale change + * Apply dp changes on configuration change */ - public void onDensityOrFontScaleChanged() { + public void onConfigChanged() { mClockSwitchYAmount = mContext.getResources().getDimensionPixelSize( R.dimen.keyguard_clock_switch_y_shift); mSmartspaceTopOffset = mContext.getResources().getDimensionPixelSize( R.dimen.keyguard_smartspace_top_offset); + mWeatherClockSmartspaceScaling = ResourcesCompat.getFloat( + mContext.getResources(), R.dimen.weather_clock_smartspace_scale); + mWeatherClockSmartspaceTranslateX = mContext.getResources().getDimensionPixelSize( + R.dimen.weather_clock_smartspace_translateX); + mWeatherClockSmartspaceTranslateY = mContext.getResources().getDimensionPixelSize( + R.dimen.weather_clock_smartspace_translateY); + updateStatusArea(/* animate= */false); + } + + /** + * Enable or disable split shade specific positioning + */ + public void setSplitShadeCentered(boolean splitShadeCentered) { + if (mSplitShadeCentered != splitShadeCentered) { + mSplitShadeCentered = splitShadeCentered; + updateStatusArea(/* animate= */true); + } } @Override @@ -134,7 +163,7 @@ public class KeyguardClockSwitch extends RelativeLayout { mLargeClockFrame = findViewById(R.id.lockscreen_clock_view_large); mStatusArea = findViewById(R.id.keyguard_status_area); - onDensityOrFontScaleChanged(); + onConfigChanged(); } @Override @@ -182,6 +211,13 @@ public class KeyguardClockSwitch extends RelativeLayout { mSmallClockFrame.addView(clock.getSmallClock().getView()); mLargeClockFrame.addView(clock.getLargeClock().getView()); updateClockTargetRegions(); + updateStatusArea(/* animate= */false); + } + + private void updateStatusArea(boolean animate) { + if (mDisplayedClockSize != null && mChildrenAreLaidOut) { + updateClockViews(mDisplayedClockSize == LARGE, animate); + } } void updateClockTargetRegions() { @@ -230,13 +266,25 @@ public class KeyguardClockSwitch extends RelativeLayout { mStatusAreaAnim = null; View in, out; - float statusAreaYTranslation, clockInYTranslation, clockOutYTranslation; + float statusAreaYTranslation, statusAreaClockScale = 1f; + float statusAreaClockTranslateX = 0f, statusAreaClockTranslateY = 0f; + float clockInYTranslation, clockOutYTranslation; if (useLargeClock) { out = mSmallClockFrame; in = mLargeClockFrame; if (indexOfChild(in) == -1) addView(in, 0); statusAreaYTranslation = mSmallClockFrame.getTop() - mStatusArea.getTop() + mSmartspaceTopOffset; + // TODO: Load from clock config when less risky + if (mClock != null + && mClock.getLargeClock().getConfig().getHasCustomWeatherDataDisplay()) { + statusAreaClockScale = mWeatherClockSmartspaceScaling; + statusAreaClockTranslateX = mWeatherClockSmartspaceTranslateX; + statusAreaClockTranslateY = mWeatherClockSmartspaceTranslateY; + if (mSplitShadeCentered) { + statusAreaClockTranslateX *= SMARTSPACE_TRANSLATION_CENTER_MULTIPLIER; + } + } clockInYTranslation = 0; clockOutYTranslation = 0; // Small clock translation is handled with statusArea } else { @@ -258,7 +306,12 @@ public class KeyguardClockSwitch extends RelativeLayout { in.setAlpha(1f); in.setTranslationY(clockInYTranslation); in.setVisibility(View.VISIBLE); - mStatusArea.setTranslationY(statusAreaYTranslation); + mStatusArea.setScaleX(statusAreaClockScale); + mStatusArea.setScaleY(statusAreaClockScale); + mStatusArea.setTranslateXFromClockDesign(statusAreaClockTranslateX); + mStatusArea.setTranslateYFromClockDesign(statusAreaClockTranslateY); + mStatusArea.setTranslateYFromClockSize(statusAreaYTranslation); + mSmallClockFrame.setTranslationY(statusAreaYTranslation); return; } @@ -295,8 +348,15 @@ public class KeyguardClockSwitch extends RelativeLayout { useLargeClock ? STATUS_AREA_MOVE_UP_MILLIS : STATUS_AREA_MOVE_DOWN_MILLIS); mStatusAreaAnim.setInterpolator(Interpolators.EMPHASIZED); mStatusAreaAnim.playTogether( - ObjectAnimator.ofFloat(mStatusArea, TRANSLATION_Y, statusAreaYTranslation), - ObjectAnimator.ofFloat(mSmallClockFrame, TRANSLATION_Y, statusAreaYTranslation)); + ObjectAnimator.ofFloat(mStatusArea, TRANSLATE_Y_CLOCK_SIZE.getProperty(), + statusAreaYTranslation), + ObjectAnimator.ofFloat(mSmallClockFrame, TRANSLATION_Y, statusAreaYTranslation), + ObjectAnimator.ofFloat(mStatusArea, SCALE_X, statusAreaClockScale), + ObjectAnimator.ofFloat(mStatusArea, SCALE_Y, statusAreaClockScale), + ObjectAnimator.ofFloat(mStatusArea, TRANSLATE_X_CLOCK_DESIGN.getProperty(), + statusAreaClockTranslateX), + ObjectAnimator.ofFloat(mStatusArea, TRANSLATE_Y_CLOCK_DESIGN.getProperty(), + statusAreaClockTranslateY)); mStatusAreaAnim.addListener(new AnimatorListenerAdapter() { public void onAnimationEnd(Animator animation) { mStatusAreaAnim = null; diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java index 99e25745dda7f..41c1eda42e830 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java @@ -330,10 +330,10 @@ public class KeyguardClockSwitchController extends ViewController("TranslateXClockDesign") { + override fun setValue(view: KeyguardStatusAreaView, value: Float) { + view.translateXFromClockDesign = value + } + + override fun get(view: KeyguardStatusAreaView): Float { + return view.translateXFromClockDesign + } + }, + R.id.translate_x_clock_design_animator_tag, + R.id.translate_x_clock_design_animator_start_tag, + R.id.translate_x_clock_design_animator_end_tag + ) + + @JvmField + val TRANSLATE_X_AOD = + AnimatableProperty.from( + object : FloatProperty("TranslateXAod") { + override fun setValue(view: KeyguardStatusAreaView, value: Float) { + view.translateXFromAod = value + } + + override fun get(view: KeyguardStatusAreaView): Float { + return view.translateXFromAod + } + }, + R.id.translate_x_aod_animator_tag, + R.id.translate_x_aod_animator_start_tag, + R.id.translate_x_aod_animator_end_tag + ) + + @JvmField + val TRANSLATE_Y_CLOCK_SIZE = + AnimatableProperty.from( + object : FloatProperty("TranslateYClockSize") { + override fun setValue(view: KeyguardStatusAreaView, value: Float) { + view.translateYFromClockSize = value + } + + override fun get(view: KeyguardStatusAreaView): Float { + return view.translateYFromClockSize + } + }, + R.id.translate_y_clock_size_animator_tag, + R.id.translate_y_clock_size_animator_start_tag, + R.id.translate_y_clock_size_animator_end_tag + ) + + @JvmField + val TRANSLATE_Y_CLOCK_DESIGN = + AnimatableProperty.from( + object : FloatProperty("TranslateYClockDesign") { + override fun setValue(view: KeyguardStatusAreaView, value: Float) { + view.translateYFromClockDesign = value + } + + override fun get(view: KeyguardStatusAreaView): Float { + return view.translateYFromClockDesign + } + }, + R.id.translate_y_clock_design_animator_tag, + R.id.translate_y_clock_design_animator_start_tag, + R.id.translate_y_clock_design_animator_end_tag + ) + } +} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java index 835cc13bebb1f..00500d6177660 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java @@ -24,6 +24,7 @@ import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_CL import android.animation.Animator; import android.animation.ValueAnimator; import android.annotation.Nullable; +import android.content.res.Configuration; import android.graphics.Rect; import android.transition.ChangeBounds; import android.transition.Transition; @@ -280,8 +281,8 @@ public class KeyguardStatusViewController extends ViewController + (view as? KeyguardStatusAreaView)?.translateXFromUnfold = value + }), ViewIdToTranslate( R.id.lockscreen_clock_view_large, START, filterKeyguardAndSplitShadeOnly), ViewIdToTranslate(R.id.lockscreen_clock_view, START, filterKeyguard), diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java index 254f9531ef83d..061340e385a53 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java @@ -72,6 +72,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase { private FrameLayout mSmallClockFrame; private FrameLayout mLargeClockFrame; + private KeyguardStatusAreaView mStatusArea; KeyguardClockSwitch mKeyguardClockSwitch; @@ -109,6 +110,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase { (KeyguardClockSwitch) layoutInflater.inflate(R.layout.keyguard_clock_switch, null); mSmallClockFrame = mKeyguardClockSwitch.findViewById(R.id.lockscreen_clock_view); mLargeClockFrame = mKeyguardClockSwitch.findViewById(R.id.lockscreen_clock_view_large); + mStatusArea = mKeyguardClockSwitch.findViewById(R.id.keyguard_status_area); mKeyguardClockSwitch.mChildrenAreLaidOut = true; } @@ -185,6 +187,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase { mKeyguardClockSwitch.mClockInAnim.end(); mKeyguardClockSwitch.mClockOutAnim.end(); + mKeyguardClockSwitch.mStatusAreaAnim.end(); assertThat(mLargeClockFrame.getAlpha()).isEqualTo(1); assertThat(mLargeClockFrame.getVisibility()).isEqualTo(VISIBLE); @@ -206,6 +209,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase { mKeyguardClockSwitch.mClockInAnim.end(); mKeyguardClockSwitch.mClockOutAnim.end(); + mKeyguardClockSwitch.mStatusAreaAnim.end(); assertThat(mSmallClockFrame.getAlpha()).isEqualTo(1); assertThat(mSmallClockFrame.getVisibility()).isEqualTo(VISIBLE); @@ -225,6 +229,31 @@ public class KeyguardClockSwitchTest extends SysuiTestCase { assertThat(mLargeClockFrame.getAlpha()).isEqualTo(0); } + @Test + public void switchingToSmallClockAnimation_resetsStatusArea() { + mKeyguardClockSwitch.switchToClock(SMALL, true); + + mKeyguardClockSwitch.mClockInAnim.end(); + mKeyguardClockSwitch.mClockOutAnim.end(); + mKeyguardClockSwitch.mStatusAreaAnim.end(); + + assertThat(mStatusArea.getTranslationX()).isEqualTo(0); + assertThat(mStatusArea.getTranslationY()).isEqualTo(0); + assertThat(mStatusArea.getScaleX()).isEqualTo(1); + assertThat(mStatusArea.getScaleY()).isEqualTo(1); + } + + @Test + public void switchingToSmallClockNoAnimation_resetsStatusArea() { + mKeyguardClockSwitch.switchToClock(SMALL, false); + + assertThat(mStatusArea.getTranslationX()).isEqualTo(0); + assertThat(mStatusArea.getTranslationY()).isEqualTo(0); + assertThat(mStatusArea.getScaleX()).isEqualTo(1); + assertThat(mStatusArea.getScaleY()).isEqualTo(1); + } + + @Test public void switchingToBigClock_returnsTrueOnlyWhenItWasNotVisibleBefore() { assertThat(mKeyguardClockSwitch.switchToClock(LARGE, /* animate */ true)).isTrue(); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusAreaViewTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusAreaViewTest.kt new file mode 100644 index 0000000000000..e6b696454d422 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusAreaViewTest.kt @@ -0,0 +1,44 @@ +package com.android.keyguard + +import android.test.suitebuilder.annotation.SmallTest +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper.RunWithLooper +import com.android.systemui.SysuiTestCase +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidTestingRunner::class) +@RunWithLooper(setAsMainLooper = true) +class KeyguardStatusAreaViewTest : SysuiTestCase() { + + private lateinit var view: KeyguardStatusAreaView + + @Before + fun setUp() { + view = KeyguardStatusAreaView(context) + } + + @Test + fun checkTranslationX_AddedTotals() { + view.translateXFromClockDesign = 10f + assertEquals(10f, view.translationX) + + view.translateXFromAod = 20f + assertEquals(30f, view.translationX) + + view.translateXFromUnfold = 30f + assertEquals(60f, view.translationX) + } + + @Test + fun checkTranslationY_AddedTotals() { + view.translateYFromClockSize = 10f + assertEquals(10f, view.translationY) + + view.translateYFromClockDesign = 20f + assertEquals(30f, view.translationY) + } +}