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) + } +}