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:
@@ -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"
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user