Merge "Implement dream complication motion/fade when transitionting to bouncer." into tm-dev
This commit is contained in:
@@ -1429,6 +1429,8 @@
|
||||
<!-- The margin applied between complications -->
|
||||
<dimen name="dream_overlay_complication_margin">0dp</dimen>
|
||||
|
||||
<dimen name="dream_overlay_y_offset">80dp</dimen>
|
||||
|
||||
<dimen name="status_view_margin_horizontal">0dp</dimen>
|
||||
|
||||
<!-- Media output broadcast dialog QR code picture size -->
|
||||
|
||||
@@ -46,4 +46,24 @@ object BouncerPanelExpansionCalculator {
|
||||
fun getKeyguardClockScaledExpansion(fraction: Float): Float {
|
||||
return MathUtils.constrain((fraction - 0.7f) / 0.3f, 0f, 1f)
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale the position of the dream complications.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getDreamYPositionScaledExpansion(fraction: Float): Float {
|
||||
return when {
|
||||
fraction >= 0.98f -> 1f
|
||||
fraction < 0.93 -> 0f
|
||||
else -> (fraction - 0.93f) / 0.05f
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale the alpha of the dream complications.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getDreamAlphaScaledExpansion(fraction: Float): Float {
|
||||
return MathUtils.constrain((fraction - 0.94f) / 0.06f, 0f, 1f)
|
||||
}
|
||||
}
|
||||
@@ -16,14 +16,21 @@
|
||||
|
||||
package com.android.systemui.dreams;
|
||||
|
||||
import static com.android.keyguard.BouncerPanelExpansionCalculator.getBackScrimScaledExpansion;
|
||||
import static com.android.keyguard.BouncerPanelExpansionCalculator.getDreamAlphaScaledExpansion;
|
||||
import static com.android.keyguard.BouncerPanelExpansionCalculator.getDreamYPositionScaledExpansion;
|
||||
import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
|
||||
import static com.android.systemui.dreams.complication.ComplicationLayoutParams.POSITION_BOTTOM;
|
||||
import static com.android.systemui.dreams.complication.ComplicationLayoutParams.POSITION_TOP;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.os.Handler;
|
||||
import android.util.MathUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.keyguard.BouncerPanelExpansionCalculator;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.animation.Interpolators;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.dreams.complication.ComplicationHostViewController;
|
||||
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
|
||||
@@ -33,6 +40,8 @@ import com.android.systemui.statusbar.phone.KeyguardBouncer;
|
||||
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
|
||||
import com.android.systemui.util.ViewController;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
@@ -63,6 +72,7 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
|
||||
|
||||
// Main thread handler used to schedule periodic tasks (e.g. burn-in protection updates).
|
||||
private final Handler mHandler;
|
||||
private final int mDreamOverlayMaxTranslationY;
|
||||
|
||||
private long mJitterStartTimeMillis;
|
||||
|
||||
@@ -93,13 +103,9 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
|
||||
|
||||
@Override
|
||||
public void onExpansionChanged(float bouncerHideAmount) {
|
||||
if (!mBouncerAnimating) return;
|
||||
final float scaledFraction =
|
||||
BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(
|
||||
bouncerHideAmount);
|
||||
final int blurRadius =
|
||||
(int) mBlurUtils.blurRadiusOfRatio(1 - scaledFraction);
|
||||
updateTransitionState(blurRadius, scaledFraction);
|
||||
if (mBouncerAnimating) {
|
||||
updateTransitionState(bouncerHideAmount);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -107,7 +113,7 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
|
||||
// The bouncer may be hidden abruptly without triggering onExpansionChanged.
|
||||
// In this case, we should reset the transition state.
|
||||
if (!isVisible) {
|
||||
updateTransitionState(0, 1f);
|
||||
updateTransitionState(1f);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -121,6 +127,7 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
|
||||
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
|
||||
BlurUtils blurUtils,
|
||||
@Main Handler handler,
|
||||
@Main Resources resources,
|
||||
@Named(DreamOverlayModule.MAX_BURN_IN_OFFSET) int maxBurnInOffset,
|
||||
@Named(DreamOverlayModule.BURN_IN_PROTECTION_UPDATE_INTERVAL) long
|
||||
burnInProtectionUpdateInterval,
|
||||
@@ -132,6 +139,8 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
|
||||
mBlurUtils = blurUtils;
|
||||
|
||||
mComplicationHostViewController = complicationHostViewController;
|
||||
mDreamOverlayMaxTranslationY = resources.getDimensionPixelSize(
|
||||
R.dimen.dream_overlay_y_offset);
|
||||
final View view = mComplicationHostViewController.getView();
|
||||
|
||||
mDreamOverlayContentView.addView(view,
|
||||
@@ -196,8 +205,31 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
|
||||
mHandler.postDelayed(this::updateBurnInOffsets, mBurnInProtectionUpdateInterval);
|
||||
}
|
||||
|
||||
private void updateTransitionState(int blurRadiusPixels, float alpha) {
|
||||
mBlurUtils.applyBlur(mView.getViewRootImpl(), blurRadiusPixels, false);
|
||||
mView.setAlpha(alpha);
|
||||
private void updateTransitionState(float bouncerHideAmount) {
|
||||
for (int position : Arrays.asList(POSITION_TOP, POSITION_BOTTOM)) {
|
||||
final float alpha = getAlpha(position, bouncerHideAmount);
|
||||
final float translationY = getTranslationY(position, bouncerHideAmount);
|
||||
mComplicationHostViewController.getViewsAtPosition(position).forEach(v -> {
|
||||
v.setAlpha(alpha);
|
||||
v.setTranslationY(translationY);
|
||||
});
|
||||
}
|
||||
|
||||
mBlurUtils.applyBlur(mView.getViewRootImpl(),
|
||||
(int) mBlurUtils.blurRadiusOfRatio(
|
||||
1 - getBackScrimScaledExpansion(bouncerHideAmount)), false);
|
||||
}
|
||||
|
||||
private static float getAlpha(int position, float expansion) {
|
||||
return Interpolators.LINEAR_OUT_SLOW_IN.getInterpolation(
|
||||
position == POSITION_TOP ? getDreamAlphaScaledExpansion(expansion)
|
||||
: getBackScrimScaledExpansion(expansion + 0.03f));
|
||||
}
|
||||
|
||||
private float getTranslationY(int position, float expansion) {
|
||||
final float fraction = Interpolators.LINEAR_OUT_SLOW_IN.getInterpolation(
|
||||
position == POSITION_TOP ? getDreamYPositionScaledExpansion(expansion)
|
||||
: getBackScrimScaledExpansion(expansion + 0.03f));
|
||||
return MathUtils.lerp(-mDreamOverlayMaxTranslationY, 0, fraction);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.android.systemui.util.ViewController;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -144,4 +145,11 @@ public class ComplicationHostViewController extends ViewController<ConstraintLay
|
||||
public View getView() {
|
||||
return mView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an unordered list of all the views at a particular position.
|
||||
*/
|
||||
public List<View> getViewsAtPosition(@ComplicationLayoutParams.Position int position) {
|
||||
return mLayoutEngine.getViewsAtPosition(position);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.constraintlayout.widget.Constraints;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.dreams.complication.ComplicationLayoutParams.Position;
|
||||
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
|
||||
import com.android.systemui.touch.TouchInsetManager;
|
||||
|
||||
@@ -39,7 +40,9 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
@@ -378,6 +381,14 @@ public class ComplicationLayoutEngine implements Complication.VisibilityControll
|
||||
directionGroup.updateViews(head.getView());
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<ViewEntry> getViews() {
|
||||
final ArrayList<ViewEntry> views = new ArrayList<>();
|
||||
for (DirectionGroup directionGroup : mDirectionGroups.values()) {
|
||||
views.addAll(directionGroup.getViews());
|
||||
}
|
||||
return views;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -454,6 +465,10 @@ public class ComplicationLayoutEngine implements Complication.VisibilityControll
|
||||
groupHead = viewEntry.getView();
|
||||
}
|
||||
}
|
||||
|
||||
private List<ViewEntry> getViews() {
|
||||
return mViews;
|
||||
}
|
||||
}
|
||||
|
||||
private final ConstraintLayout mLayout;
|
||||
@@ -551,4 +566,15 @@ public class ComplicationLayoutEngine implements Complication.VisibilityControll
|
||||
entry.remove();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an unordered list of all the views at a particular position.
|
||||
*/
|
||||
public List<View> getViewsAtPosition(@Position int position) {
|
||||
return mPositions.entrySet().stream()
|
||||
.filter(entry -> (entry.getKey() & position) == position)
|
||||
.flatMap(entry -> entry.getValue().getViews().stream())
|
||||
.map(ViewEntry::getView)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +107,7 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
|
||||
mStatusBarKeyguardViewManager,
|
||||
mBlurUtils,
|
||||
mHandler,
|
||||
mResources,
|
||||
MAX_BURN_IN_OFFSET,
|
||||
BURN_IN_PROTECTION_UPDATE_INTERVAL,
|
||||
MILLIS_UNTIL_FULL_JITTER);
|
||||
@@ -160,11 +161,10 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
|
||||
|
||||
bouncerExpansionCaptor.getValue().onExpansionChanged(0.5f);
|
||||
verify(mBlurUtils, never()).applyBlur(eq(mViewRoot), anyInt(), eq(false));
|
||||
verify(mDreamOverlayContainerView, never()).setAlpha(anyFloat());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBouncerAnimation_updateBlurAndAlpha() {
|
||||
public void testBouncerAnimation_updateBlur() {
|
||||
final ArgumentCaptor<BouncerExpansionCallback> bouncerExpansionCaptor =
|
||||
ArgumentCaptor.forClass(BouncerExpansionCallback.class);
|
||||
mController.onViewAttached();
|
||||
@@ -182,6 +182,5 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
|
||||
bouncerExpansionCaptor.getValue().onExpansionChanged(bouncerHideAmount);
|
||||
verify(mBlurUtils).blurRadiusOfRatio(1 - scaledFraction);
|
||||
verify(mBlurUtils).applyBlur(mViewRoot, (int) blurRadius, false);
|
||||
verify(mDreamOverlayContainerView).setAlpha(scaledFraction);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,10 @@ import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@@ -448,4 +451,70 @@ public class ComplicationLayoutEngineTest extends SysuiTestCase {
|
||||
verify(firstViewInfo.view, never()).getParent();
|
||||
verify(mLayout, never()).removeView(firstViewInfo.view);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetViews() {
|
||||
final ComplicationLayoutEngine engine =
|
||||
new ComplicationLayoutEngine(mLayout, 0, mTouchSession, 0, 0);
|
||||
|
||||
final ViewInfo topEndView = new ViewInfo(
|
||||
new ComplicationLayoutParams(
|
||||
100,
|
||||
100,
|
||||
ComplicationLayoutParams.POSITION_TOP
|
||||
| ComplicationLayoutParams.POSITION_END,
|
||||
ComplicationLayoutParams.DIRECTION_DOWN,
|
||||
0),
|
||||
Complication.CATEGORY_STANDARD,
|
||||
mLayout);
|
||||
|
||||
addComplication(engine, topEndView);
|
||||
|
||||
final ViewInfo topStartView = new ViewInfo(
|
||||
new ComplicationLayoutParams(
|
||||
100,
|
||||
100,
|
||||
ComplicationLayoutParams.POSITION_TOP
|
||||
| ComplicationLayoutParams.POSITION_START,
|
||||
ComplicationLayoutParams.DIRECTION_DOWN,
|
||||
0),
|
||||
Complication.CATEGORY_SYSTEM,
|
||||
mLayout);
|
||||
|
||||
addComplication(engine, topStartView);
|
||||
|
||||
final ViewInfo bottomEndView = new ViewInfo(
|
||||
new ComplicationLayoutParams(
|
||||
100,
|
||||
100,
|
||||
ComplicationLayoutParams.POSITION_BOTTOM
|
||||
| ComplicationLayoutParams.POSITION_END,
|
||||
ComplicationLayoutParams.DIRECTION_START,
|
||||
1),
|
||||
Complication.CATEGORY_SYSTEM,
|
||||
mLayout);
|
||||
|
||||
addComplication(engine, bottomEndView);
|
||||
|
||||
verifyViewsAtPosition(engine, ComplicationLayoutParams.POSITION_TOP, topStartView,
|
||||
topEndView);
|
||||
verifyViewsAtPosition(engine,
|
||||
ComplicationLayoutParams.POSITION_TOP | ComplicationLayoutParams.POSITION_START,
|
||||
topStartView);
|
||||
verifyViewsAtPosition(engine,
|
||||
ComplicationLayoutParams.POSITION_BOTTOM,
|
||||
bottomEndView);
|
||||
}
|
||||
|
||||
private void verifyViewsAtPosition(ComplicationLayoutEngine engine, int position,
|
||||
ViewInfo... views) {
|
||||
final List<Integer> idList = engine.getViewsAtPosition(position).stream()
|
||||
.map(View::getId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
assertThat(idList).containsExactlyElementsIn(
|
||||
Arrays.stream(views)
|
||||
.map(viewInfo -> viewInfo.view.getId())
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user