Merge "Prevent alpha transitions from clipping out-of-bounds clocks" into udc-dev am: 5623c50b66

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23149088

Change-Id: If0a47059c767839b8731268450998d39ff68010f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Hawkwood Glazier
2023-05-13 15:02:12 +00:00
committed by Automerger Merge Worker
10 changed files with 107 additions and 80 deletions

View File

@@ -25,7 +25,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clipChildren="false" android:clipChildren="false"
android:layout_gravity="center_horizontal|top"> android:layout_gravity="center_horizontal|top">
<FrameLayout <com.android.keyguard.KeyguardClockFrame
android:id="@+id/lockscreen_clock_view" android:id="@+id/lockscreen_clock_view"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="@dimen/small_clock_height" android:layout_height="@dimen/small_clock_height"
@@ -34,7 +34,7 @@
android:clipChildren="false" android:clipChildren="false"
android:paddingStart="@dimen/clock_padding_start" android:paddingStart="@dimen/clock_padding_start"
android:visibility="invisible" /> android:visibility="invisible" />
<FrameLayout <com.android.keyguard.KeyguardClockFrame
android:id="@+id/lockscreen_clock_view_large" android:id="@+id/lockscreen_clock_view_large"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"

View File

@@ -30,7 +30,7 @@
android:clipChildren="false" android:clipChildren="false"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<LinearLayout <com.android.keyguard.KeyguardStatusContainer
android:id="@+id/status_view_container" android:id="@+id/status_view_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -48,5 +48,5 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="@dimen/qs_media_padding" android:padding="@dimen/qs_media_padding"
/> />
</LinearLayout> </com.android.keyguard.KeyguardStatusContainer>
</com.android.keyguard.KeyguardStatusView> </com.android.keyguard.KeyguardStatusView>

View File

@@ -0,0 +1,39 @@
package com.android.keyguard
import android.content.Context
import android.graphics.Canvas
import android.util.AttributeSet
import android.view.View
import android.widget.FrameLayout
class KeyguardClockFrame(
context: Context,
attrs: AttributeSet,
) : FrameLayout(context, attrs) {
private var drawAlpha: Int = 255
protected override fun onSetAlpha(alpha: Int): Boolean {
drawAlpha = alpha
return true
}
protected override fun dispatchDraw(canvas: Canvas) {
val restoreTo = saveCanvasAlpha(this, canvas, drawAlpha)
super.dispatchDraw(canvas)
canvas.restoreToCount(restoreTo)
}
companion object {
@JvmStatic
fun saveCanvasAlpha(view: View, canvas: Canvas, alpha: Int): Int {
var (x, y) =
run {
val locationOnScreen = IntArray(2)
view.getLocationOnScreen(locationOnScreen)
Pair(locationOnScreen[0].toFloat(), locationOnScreen[1].toFloat())
}
return canvas.saveLayerAlpha(-1f * x, -1f * y, x + view.width, y + view.height, alpha)
}
}
}

View File

@@ -5,11 +5,11 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet; import android.animation.AnimatorSet;
import android.animation.ObjectAnimator; import android.animation.ObjectAnimator;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect; import android.graphics.Rect;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
@@ -69,12 +69,13 @@ public class KeyguardClockSwitch extends RelativeLayout {
/** /**
* Frame for small/large clocks * Frame for small/large clocks
*/ */
private FrameLayout mSmallClockFrame; private KeyguardClockFrame mSmallClockFrame;
private FrameLayout mLargeClockFrame; private KeyguardClockFrame mLargeClockFrame;
private ClockController mClock; private ClockController mClock;
private View mStatusArea; private View mStatusArea;
private int mSmartspaceTopOffset; private int mSmartspaceTopOffset;
private int mDrawAlpha = 255;
/** /**
* Maintain state so that a newly connected plugin can be initialized. * Maintain state so that a newly connected plugin can be initialized.
@@ -121,6 +122,19 @@ public class KeyguardClockSwitch extends RelativeLayout {
onDensityOrFontScaleChanged(); onDensityOrFontScaleChanged();
} }
@Override
protected boolean onSetAlpha(int alpha) {
mDrawAlpha = alpha;
return true;
}
@Override
protected void dispatchDraw(Canvas canvas) {
int restoreTo = KeyguardClockFrame.saveCanvasAlpha(this, canvas, mDrawAlpha);
super.dispatchDraw(canvas);
canvas.restoreToCount(restoreTo);
}
public void setLogBuffer(LogBuffer logBuffer) { public void setLogBuffer(LogBuffer logBuffer) {
mLogBuffer = logBuffer; mLogBuffer = logBuffer;
} }

View File

@@ -178,20 +178,6 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
} }
} }
/**
* Set alpha directly to mView will clip clock, so we set alpha to clock face instead
*/
public void setAlpha(float alpha) {
ClockController clock = getClock();
if (clock != null) {
clock.getLargeClock().getView().setAlpha(alpha);
clock.getSmallClock().getView().setAlpha(alpha);
}
if (mStatusArea != null) {
mStatusArea.setAlpha(alpha);
}
}
/** /**
* Attach the controller to the view it relates to. * Attach the controller to the view it relates to.
*/ */

View File

@@ -0,0 +1,24 @@
package com.android.keyguard
import android.content.Context
import android.graphics.Canvas
import android.util.AttributeSet
import android.widget.LinearLayout
class KeyguardStatusContainer(
context: Context,
attrs: AttributeSet,
) : LinearLayout(context, attrs) {
private var drawAlpha: Int = 255
protected override fun onSetAlpha(alpha: Int): Boolean {
drawAlpha = alpha
return true
}
protected override fun dispatchDraw(canvas: Canvas) {
val restoreTo = KeyguardClockFrame.saveCanvasAlpha(this, canvas, drawAlpha)
super.dispatchDraw(canvas)
canvas.restoreToCount(restoreTo)
}
}

View File

@@ -19,6 +19,7 @@ package com.android.keyguard;
import static java.util.Collections.emptySet; import static java.util.Collections.emptySet;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas;
import android.os.Build; import android.os.Build;
import android.os.Trace; import android.os.Trace;
import android.util.AttributeSet; import android.util.AttributeSet;
@@ -47,6 +48,7 @@ public class KeyguardStatusView extends GridLayout {
private KeyguardSliceView mKeyguardSlice; private KeyguardSliceView mKeyguardSlice;
private View mMediaHostContainer; private View mMediaHostContainer;
private int mDrawAlpha = 255;
private float mDarkAmount = 0; private float mDarkAmount = 0;
public KeyguardStatusView(Context context) { public KeyguardStatusView(Context context) {
@@ -136,30 +138,16 @@ public class KeyguardStatusView extends GridLayout {
Trace.endSection(); Trace.endSection();
} }
/** @Override
* Clock content will be clipped when goes beyond bounds, protected boolean onSetAlpha(int alpha) {
* so we setAlpha for all views except clock mDrawAlpha = alpha;
*/ return true;
public void setAlpha(float alpha, boolean excludeClock) { }
if (!excludeClock) {
setAlpha(alpha); @Override
return; protected void dispatchDraw(Canvas canvas) {
} int restoreTo = KeyguardClockFrame.saveCanvasAlpha(this, canvas, mDrawAlpha);
if (alpha == 1 || alpha == 0) { super.dispatchDraw(canvas);
setAlpha(alpha); canvas.restoreToCount(restoreTo);
}
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
if (child == mStatusViewContainer) {
for (int j = 0; j < mStatusViewContainer.getChildCount(); j++) {
View innerChild = mStatusViewContainer.getChildAt(j);
if (innerChild != mClockView) {
innerChild.setAlpha(alpha);
}
}
} else {
child.setAlpha(alpha);
}
}
} }
} }

View File

@@ -180,8 +180,7 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
*/ */
public void setAlpha(float alpha) { public void setAlpha(float alpha) {
if (!mKeyguardVisibilityHelper.isVisibilityAnimating()) { if (!mKeyguardVisibilityHelper.isVisibilityAnimating()) {
mView.setAlpha(alpha, true); mView.setAlpha(alpha);
mKeyguardClockSwitchController.setAlpha(alpha);
} }
} }

View File

@@ -134,7 +134,6 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
private KeyguardClockSwitchController mController; private KeyguardClockSwitchController mController;
private View mSliceView; private View mSliceView;
private LinearLayout mStatusArea;
private FakeExecutor mExecutor; private FakeExecutor mExecutor;
@Before @Before
@@ -196,8 +195,8 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
mSliceView = new View(getContext()); mSliceView = new View(getContext());
when(mView.findViewById(R.id.keyguard_slice_view)).thenReturn(mSliceView); when(mView.findViewById(R.id.keyguard_slice_view)).thenReturn(mSliceView);
mStatusArea = new LinearLayout(getContext()); when(mView.findViewById(R.id.keyguard_status_area)).thenReturn(
when(mView.findViewById(R.id.keyguard_status_area)).thenReturn(mStatusArea); new LinearLayout(getContext()));
} }
@Test @Test
@@ -402,15 +401,6 @@ public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
assertNull(mController.getClock()); assertNull(mController.getClock());
} }
@Test
public void testSetAlpha_setClockAlphaForCLockFace() {
mController.onViewAttached();
mController.setAlpha(0.5f);
verify(mLargeClockView).setAlpha(0.5f);
verify(mSmallClockView).setAlpha(0.5f);
assertEquals(0.5f, mStatusArea.getAlpha(), 0.0f);
}
private void verifyAttachment(VerificationMode times) { private void verifyAttachment(VerificationMode times) {
verify(mClockRegistry, times).registerClockChangeListener( verify(mClockRegistry, times).registerClockChangeListener(
any(ClockRegistry.ClockChangeListener.class)); any(ClockRegistry.ClockChangeListener.class));

View File

@@ -24,46 +24,33 @@ class KeyguardStatusViewTest : SysuiTestCase() {
get() = keyguardStatusView.findViewById(R.id.status_view_media_container) get() = keyguardStatusView.findViewById(R.id.status_view_media_container)
private val statusViewContainer: ViewGroup private val statusViewContainer: ViewGroup
get() = keyguardStatusView.findViewById(R.id.status_view_container) get() = keyguardStatusView.findViewById(R.id.status_view_container)
private val clockView: ViewGroup
get() = keyguardStatusView.findViewById(R.id.keyguard_clock_container)
private val childrenExcludingMedia private val childrenExcludingMedia
get() = statusViewContainer.children.filter { it != mediaView } get() = statusViewContainer.children.filter { it != mediaView }
@Before @Before
fun setUp() { fun setUp() {
keyguardStatusView = LayoutInflater.from(context) keyguardStatusView =
.inflate(R.layout.keyguard_status_view, /* root= */ null) as KeyguardStatusView LayoutInflater.from(context).inflate(R.layout.keyguard_status_view, /* root= */ null)
as KeyguardStatusView
} }
@Test @Test
fun setChildrenTranslationYExcludingMediaView_mediaViewIsNotTranslated() { fun setChildrenTranslationYExcludingMediaView_mediaViewIsNotTranslated() {
val translationY = 1234f val translationY = 1234f
keyguardStatusView.setChildrenTranslationY(translationY, /* excludeMedia= */true) keyguardStatusView.setChildrenTranslationY(translationY, /* excludeMedia= */ true)
assertThat(mediaView.translationY).isEqualTo(0) assertThat(mediaView.translationY).isEqualTo(0)
childrenExcludingMedia.forEach { childrenExcludingMedia.forEach { assertThat(it.translationY).isEqualTo(translationY) }
assertThat(it.translationY).isEqualTo(translationY)
}
} }
@Test @Test
fun setChildrenTranslationYIncludeMediaView() { fun setChildrenTranslationYIncludeMediaView() {
val translationY = 1234f val translationY = 1234f
keyguardStatusView.setChildrenTranslationY(translationY, /* excludeMedia= */false) keyguardStatusView.setChildrenTranslationY(translationY, /* excludeMedia= */ false)
statusViewContainer.children.forEach { statusViewContainer.children.forEach { assertThat(it.translationY).isEqualTo(translationY) }
assertThat(it.translationY).isEqualTo(translationY)
}
}
@Test
fun setAlphaExcludeClock() {
keyguardStatusView.setAlpha(0.5f, /* excludeClock= */true)
assertThat(statusViewContainer.alpha).isNotEqualTo(0.5f)
assertThat(mediaView.alpha).isEqualTo(0.5f)
assertThat(clockView.alpha).isNotEqualTo(0.5f)
} }
} }