summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/res/layout/media_carousel.xml1
-rw-r--r--packages/SystemUI/res/layout/qs_media_panel.xml11
-rw-r--r--packages/SystemUI/res/values/ids.xml20
-rw-r--r--packages/SystemUI/res/xml/media_scene.xml20
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/LayoutAnimationHelper.kt115
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaViewManager.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/AnimatableProperty.java96
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java22
10 files changed, 325 insertions, 21 deletions
diff --git a/packages/SystemUI/res/layout/media_carousel.xml b/packages/SystemUI/res/layout/media_carousel.xml
index fe8f2bb76f55..f888ca11b5fb 100644
--- a/packages/SystemUI/res/layout/media_carousel.xml
+++ b/packages/SystemUI/res/layout/media_carousel.xml
@@ -23,7 +23,6 @@
android:scrollbars="none"
android:clipChildren="false"
android:clipToPadding="false"
- android:fillViewport="true"
>
<LinearLayout
android:id="@+id/media_carousel"
diff --git a/packages/SystemUI/res/layout/qs_media_panel.xml b/packages/SystemUI/res/layout/qs_media_panel.xml
index 36ae2251d963..9ad380d260c0 100644
--- a/packages/SystemUI/res/layout/qs_media_panel.xml
+++ b/packages/SystemUI/res/layout/qs_media_panel.xml
@@ -31,7 +31,7 @@
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/qs_media_background"
- app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintEnd_toEndOf="@id/view_width"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
@@ -175,7 +175,14 @@
<include
layout="@layout/qs_media_panel_options"
android:visibility="gone"
- app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintEnd_toEndOf="@id/view_width"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
+
+ <androidx.constraintlayout.widget.Guideline
+ android:id="@+id/view_width"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ app:layout_constraintGuide_begin="300dp" />
</androidx.constraintlayout.motion.widget.MotionLayout>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 04640f418e97..fef8300395b3 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -70,6 +70,26 @@
<item type="id" name="panel_alpha_animator_end_tag"/>
<item type="id" name="cross_fade_layer_type_changed_tag"/>
+ <item type="id" name="absolute_x_animator_tag"/>
+ <item type="id" name="absolute_x_animator_start_tag"/>
+ <item type="id" name="absolute_x_animator_end_tag"/>
+ <item type="id" name="absolute_x_current_value"/>
+
+ <item type="id" name="absolute_y_animator_tag"/>
+ <item type="id" name="absolute_y_animator_start_tag"/>
+ <item type="id" name="absolute_y_animator_end_tag"/>
+ <item type="id" name="absolute_y_current_value"/>
+
+ <item type="id" name="view_height_animator_tag"/>
+ <item type="id" name="view_height_animator_start_tag"/>
+ <item type="id" name="view_height_animator_end_tag"/>
+ <item type="id" name="view_height_current_value"/>
+
+ <item type="id" name="view_width_animator_tag"/>
+ <item type="id" name="view_width_animator_start_tag"/>
+ <item type="id" name="view_width_animator_end_tag"/>
+ <item type="id" name="view_width_current_value"/>
+
<!-- Whether the icon is from a notification for which targetSdk < L -->
<item type="id" name="icon_is_pre_L"/>
diff --git a/packages/SystemUI/res/xml/media_scene.xml b/packages/SystemUI/res/xml/media_scene.xml
index ab9b7d9a284d..6f99d9a675f1 100644
--- a/packages/SystemUI/res/xml/media_scene.xml
+++ b/packages/SystemUI/res/xml/media_scene.xml
@@ -145,7 +145,7 @@
android:id="@+id/media_seamless"
android:layout_width="0dp"
android:layout_height="wrap_content"
- app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintEnd_toEndOf="@id/view_width"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_min="60dp"
android:layout_marginTop="@dimen/qs_media_panel_outer_padding"
@@ -172,7 +172,7 @@
android:layout_marginStart="16dp"
app:layout_constraintTop_toBottomOf="@+id/app_name"
app:layout_constraintStart_toEndOf="@id/album_art"
- app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintEnd_toEndOf="@id/view_width"
app:layout_constraintHorizontal_bias="0"/>
<!-- Artist name -->
@@ -184,7 +184,7 @@
android:layout_marginTop="3dp"
app:layout_constraintTop_toBottomOf="@id/header_title"
app:layout_constraintStart_toStartOf="@id/header_title"
- app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintEnd_toEndOf="@id/view_width"
app:layout_constraintHorizontal_bias="0"/>
<!-- Seek Bar -->
@@ -195,7 +195,7 @@
android:layout_marginTop="3dp"
app:layout_constraintTop_toBottomOf="@id/header_artist"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintEnd_toEndOf="@id/view_width"
/>
<Constraint
@@ -207,7 +207,7 @@
android:layout_marginStart="@dimen/qs_media_panel_outer_padding"
app:layout_constraintTop_toBottomOf="@id/header_artist"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintEnd_toEndOf="@id/view_width"
/>
<Constraint
@@ -272,7 +272,7 @@
android:layout_marginEnd="4dp"
android:layout_marginBottom="@dimen/qs_media_panel_outer_padding"
app:layout_constraintLeft_toRightOf="@id/action3"
- app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintRight_toRightOf="@id/view_width"
app:layout_constraintTop_toTopOf="@id/action0"
app:layout_constraintBottom_toBottomOf="parent">
</Constraint>
@@ -306,7 +306,7 @@
android:id="@+id/media_seamless"
android:layout_width="0dp"
android:layout_height="wrap_content"
- app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintEnd_toEndOf="@id/view_width"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_min="60dp"
android:layout_marginTop="@dimen/qs_media_panel_outer_padding"
@@ -358,7 +358,7 @@
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/album_art"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintEnd_toEndOf="@id/view_width"
android:visibility="gone"
/>
@@ -371,7 +371,7 @@
android:layout_marginStart="@dimen/qs_media_panel_outer_padding"
app:layout_constraintTop_toBottomOf="@id/album_art"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintEnd_toEndOf="@id/view_width"
android:visibility="gone"
/>
@@ -438,7 +438,7 @@
android:layout_marginTop="18dp"
app:layout_constraintTop_toBottomOf="@id/app_name"
app:layout_constraintLeft_toRightOf="@id/action3"
- app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintRight_toRightOf="@id/view_width"
>
</Constraint>
</ConstraintSet>
diff --git a/packages/SystemUI/src/com/android/systemui/media/LayoutAnimationHelper.kt b/packages/SystemUI/src/com/android/systemui/media/LayoutAnimationHelper.kt
new file mode 100644
index 000000000000..a366725a4398
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/LayoutAnimationHelper.kt
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.systemui.media
+
+import android.graphics.Rect
+import android.view.View
+import android.view.ViewGroup
+import android.view.ViewTreeObserver
+import com.android.systemui.statusbar.notification.AnimatableProperty
+import com.android.systemui.statusbar.notification.PropertyAnimator
+import com.android.systemui.statusbar.notification.stack.AnimationProperties
+
+/**
+ * A utility class that helps with animations of bound changes designed for motionlayout which
+ * doesn't work together with regular changeBounds.
+ */
+class LayoutAnimationHelper {
+
+ private val layout: ViewGroup
+ private var sizeAnimationPending = false
+ private val desiredBounds = mutableMapOf<View, Rect>()
+ private val animationProperties = AnimationProperties()
+ private val layoutListener = object : View.OnLayoutChangeListener {
+ override fun onLayoutChange(v: View?, left: Int, top: Int, right: Int, bottom: Int,
+ oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int) {
+ v?.let {
+ if (v.alpha == 0.0f || v.visibility == View.GONE || oldLeft - oldRight == 0 ||
+ oldTop - oldBottom == 0) {
+ return
+ }
+ if (oldLeft != left || oldTop != top || oldBottom != bottom || oldRight != right) {
+ val rect = desiredBounds.getOrPut(v, { Rect() })
+ rect.set(left, top, right, bottom)
+ onDesiredLocationChanged(v, rect)
+ }
+ }
+ }
+ }
+
+ constructor(layout: ViewGroup) {
+ this.layout = layout
+ val childCount = this.layout.childCount
+ for (i in 0 until childCount) {
+ val child = this.layout.getChildAt(i)
+ child.addOnLayoutChangeListener(layoutListener)
+ }
+ }
+
+ private fun onDesiredLocationChanged(v: View, rect: Rect) {
+ if (!sizeAnimationPending) {
+ applyBounds(v, rect, animate = false)
+ }
+ // We need to reapply the current bounds in every frame since the layout may override
+ // the layout bounds making this view jump and not all calls to apply bounds actually
+ // reapply them, for example if there's already an animator to the same target
+ reapplyProperty(v, AnimatableProperty.ABSOLUTE_X);
+ reapplyProperty(v, AnimatableProperty.ABSOLUTE_Y);
+ reapplyProperty(v, AnimatableProperty.WIDTH);
+ reapplyProperty(v, AnimatableProperty.HEIGHT);
+ }
+
+ private fun reapplyProperty(v: View, property: AnimatableProperty) {
+ property.property.set(v, property.property.get(v))
+ }
+
+ private fun applyBounds(v: View, newBounds: Rect, animate: Boolean) {
+ PropertyAnimator.setProperty(v, AnimatableProperty.ABSOLUTE_X, newBounds.left.toFloat(),
+ animationProperties, animate)
+ PropertyAnimator.setProperty(v, AnimatableProperty.ABSOLUTE_Y, newBounds.top.toFloat(),
+ animationProperties, animate)
+ PropertyAnimator.setProperty(v, AnimatableProperty.WIDTH, newBounds.width().toFloat(),
+ animationProperties, animate)
+ PropertyAnimator.setProperty(v, AnimatableProperty.HEIGHT, newBounds.height().toFloat(),
+ animationProperties, animate)
+ }
+
+ private fun startBoundAnimation(v: View) {
+ val target = desiredBounds[v] ?: return
+ applyBounds(v, target, animate = true)
+ }
+
+ fun animatePendingSizeChange(duration: Long, delay: Long) {
+ animationProperties.duration = duration
+ animationProperties.delay = delay
+ if (!sizeAnimationPending) {
+ sizeAnimationPending = true
+ layout.viewTreeObserver.addOnPreDrawListener (
+ object : ViewTreeObserver.OnPreDrawListener {
+ override fun onPreDraw(): Boolean {
+ layout.viewTreeObserver.removeOnPreDrawListener(this)
+ sizeAnimationPending = false
+ val childCount = layout.childCount
+ for (i in 0 until childCount) {
+ val child = layout.getChildAt(i)
+ startBoundAnimation(child)
+ }
+ return true
+ }
+ })
+ }
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index 5a5cd6dc3a50..0b0bfc62ed74 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -36,6 +36,7 @@ import android.media.session.MediaController.PlaybackInfo;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
import android.service.media.MediaBrowserService;
+import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -93,6 +94,7 @@ public class MediaControlPanel {
private final Executor mForegroundExecutor;
protected final Executor mBackgroundExecutor;
private final ActivityStarter mActivityStarter;
+ private final LayoutAnimationHelper mLayoutAnimationHelper;
private Context mContext;
private MotionLayout mMediaNotifView;
@@ -109,6 +111,7 @@ public class MediaControlPanel {
private String mKey;
private int mAlbumArtSize;
private int mAlbumArtRadius;
+ private int mViewWidth;
public static final String MEDIA_PREFERENCES = "media_control_prefs";
public static final String MEDIA_PREFERENCE_KEY = "browser_components";
@@ -176,6 +179,7 @@ public class MediaControlPanel {
LayoutInflater inflater = LayoutInflater.from(mContext);
mMediaNotifView = (MotionLayout) inflater.inflate(R.layout.qs_media_panel, parent, false);
mBackground = mMediaNotifView.findViewById(R.id.media_background);
+ mLayoutAnimationHelper = new LayoutAnimationHelper(mMediaNotifView);
mKeyFrames = mMediaNotifView.getDefinedTransitions().get(0).getKeyFrameList();
mLocalMediaManager = routeManager;
mForegroundExecutor = foregroundExecutor;
@@ -732,4 +736,32 @@ public class MediaControlPanel {
* Called when a player can't be resumed to give it an opportunity to hide or remove itself
*/
protected void removePlayer() { }
+
+ public void setDimension(int newWidth, int newHeight, boolean animate, long duration,
+ long startDelay) {
+ // Let's remeasure if our width changed. Our height is dependent on the expansion, so we
+ // won't animate if it changed
+ if (newWidth != mViewWidth) {
+ if (animate) {
+ mLayoutAnimationHelper.animatePendingSizeChange(duration, startDelay);
+ }
+ setViewWidth(newWidth);
+ mMediaNotifView.layout(0, 0, newWidth, mMediaNotifView.getMeasuredHeight());
+ }
+ }
+
+ protected void setViewWidth(int newWidth) {
+ ConstraintSet expandedSet = mMediaNotifView.getConstraintSet(R.id.expanded);
+ ConstraintSet collapsedSet = mMediaNotifView.getConstraintSet(R.id.collapsed);
+ collapsedSet.setGuidelineBegin(R.id.view_width, newWidth);
+ expandedSet.setGuidelineBegin(R.id.view_width, newWidth);
+ DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
+ int widthSpec = View.MeasureSpec.makeMeasureSpec(displayMetrics.widthPixels,
+ View.MeasureSpec.AT_MOST);
+ int heightSpec = View.MeasureSpec.makeMeasureSpec(displayMetrics.heightPixels,
+ View.MeasureSpec.AT_MOST);
+ mMediaNotifView.setMinimumWidth(displayMetrics.widthPixels);
+ mMediaNotifView.measure(widthSpec, heightSpec);
+ mViewWidth = newWidth;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
index 673a543d8ac0..fc141bf256f0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
@@ -24,9 +24,6 @@ import android.content.Context
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroupOverlay
-import com.android.settingslib.bluetooth.LocalBluetoothManager
-import com.android.settingslib.media.InfoMediaManager
-import com.android.settingslib.media.LocalMediaManager
import com.android.systemui.Interpolators
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.StatusBarState
@@ -167,6 +164,7 @@ class MediaHierarchyManager @Inject constructor(
return;
}
updateTargetState()
+ var animate = false
if (isCurrentlyInGuidedTransformation()) {
applyTargetStateIfNotAnimating()
} else if (shouldAnimateTransition(currentHost, previousHost)) {
@@ -175,9 +173,12 @@ class MediaHierarchyManager @Inject constructor(
animationStartState = currentState.copy()
adjustAnimatorForTransition(previousLocation, desiredLocation)
animator.start()
+ animate = true
} else {
cancelAnimationAndApplyDesiredState()
}
+ mediaViewManager.performTransition(targetState, animate, animator.duration,
+ animator.startDelay)
}
private fun shouldAnimateTransition(currentHost: MediaHost, previousHost: MediaHost): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaViewManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaViewManager.kt
index eeecf2bb6ef4..636e4e46a1b0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaViewManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaViewManager.kt
@@ -33,7 +33,6 @@ class MediaViewManager @Inject constructor(
private val activityStarter: ActivityStarter,
mediaManager: MediaDataManager
) {
- private var targetState: MediaState? = null
val mediaCarousel: ViewGroup
private val mediaContent: ViewGroup
private val mediaPlayers: MutableMap<String, MediaControlPanel> = mutableMapOf()
@@ -140,4 +139,25 @@ class MediaViewManager @Inject constructor(
}
viewsExpanded = state.expansion > 0;
}
+
+ /**
+ * @param targetState the target state we're transitioning to
+ * @param animate should this be animated
+ */
+ fun performTransition(targetState: MediaState?, animate: Boolean, duration: Long,
+ startDelay: Long) {
+ if (targetState == null) {
+ return
+ }
+ val newWidth = targetState.boundsOnScreen.width()
+ val newHeight = targetState.boundsOnScreen.height()
+ remeasureViews(newWidth, newHeight, animate, duration, startDelay)
+ }
+
+ private fun remeasureViews(newWidth: Int, newHeight: Int, animate: Boolean, duration: Long,
+ startDelay: Long) {
+ for (mediaPlayer in mediaPlayers.values) {
+ mediaPlayer.setDimension(newWidth, newHeight, animate, duration, startDelay)
+ }
+ }
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AnimatableProperty.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AnimatableProperty.java
index 75b41ca3e162..eee9cc683e2b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AnimatableProperty.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AnimatableProperty.java
@@ -16,7 +16,9 @@
package com.android.systemui.statusbar.notification;
+import android.graphics.drawable.Drawable;
import android.util.FloatProperty;
+import android.util.Log;
import android.util.Property;
import android.view.View;
@@ -35,6 +37,100 @@ public abstract class AnimatableProperty {
public static final AnimatableProperty Y = AnimatableProperty.from(View.Y,
R.id.y_animator_tag, R.id.y_animator_tag_start_value, R.id.y_animator_tag_end_value);
+ /**
+ * Similar to X, however this doesn't allow for any other modifications other than from this
+ * property. When using X, it's possible that the view is laid out during the animation,
+ * which could break the continuity
+ */
+ public static final AnimatableProperty ABSOLUTE_X = AnimatableProperty.from(
+ new FloatProperty<View>("ViewAbsoluteX") {
+ @Override
+ public void setValue(View view, float value) {
+ view.setTag(R.id.absolute_x_current_value, value);
+ View.X.set(view, value);
+ }
+
+ @Override
+ public Float get(View view) {
+ Object tag = view.getTag(R.id.absolute_x_current_value);
+ if (tag instanceof Float) {
+ return (Float) tag;
+ }
+ return View.X.get(view);
+ }
+ },
+ R.id.absolute_x_animator_tag,
+ R.id.absolute_x_animator_start_tag,
+ R.id.absolute_x_animator_end_tag);
+
+ /**
+ * Similar to Y, however this doesn't allow for any other modifications other than from this
+ * property. When using X, it's possible that the view is laid out during the animation,
+ * which could break the continuity
+ */
+ public static final AnimatableProperty ABSOLUTE_Y = AnimatableProperty.from(
+ new FloatProperty<View>("ViewAbsoluteY") {
+ @Override
+ public void setValue(View view, float value) {
+ view.setTag(R.id.absolute_y_current_value, value);
+ View.Y.set(view, value);
+ }
+
+ @Override
+ public Float get(View view) {
+ Object tag = view.getTag(R.id.absolute_y_current_value);
+ if (tag instanceof Float) {
+ return (Float) tag;
+ }
+ return View.Y.get(view);
+ }
+ },
+ R.id.absolute_y_animator_tag,
+ R.id.absolute_y_animator_start_tag,
+ R.id.absolute_y_animator_end_tag);
+
+ public static final AnimatableProperty WIDTH = AnimatableProperty.from(
+ new FloatProperty<View>("ViewWidth") {
+ @Override
+ public void setValue(View view, float value) {
+ view.setTag(R.id.view_width_current_value, value);
+ view.setRight((int) (view.getLeft() + value));
+ }
+
+ @Override
+ public Float get(View view) {
+ Object tag = view.getTag(R.id.view_width_current_value);
+ if (tag instanceof Float) {
+ return (Float) tag;
+ }
+ return (float) view.getWidth();
+ }
+ },
+ R.id.view_width_animator_tag,
+ R.id.view_width_animator_start_tag,
+ R.id.view_width_animator_end_tag);
+
+ public static final AnimatableProperty HEIGHT = AnimatableProperty.from(
+ new FloatProperty<View>("ViewHeight") {
+ @Override
+ public void setValue(View view, float value) {
+ view.setTag(R.id.view_height_current_value, value);
+ view.setBottom((int) (view.getTop() + value));
+ }
+
+ @Override
+ public Float get(View view) {
+ Object tag = view.getTag(R.id.view_height_current_value);
+ if (tag instanceof Float) {
+ return (Float) tag;
+ }
+ return (float) view.getHeight();
+ }
+ },
+ R.id.view_height_animator_tag,
+ R.id.view_height_animator_start_tag,
+ R.id.view_height_animator_end_tag);
+
public abstract int getAnimationStartTag();
public abstract int getAnimationEndTag();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java
index 1f9d3af70b4f..b1b6a1c12a0a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/PropertyAnimator.java
@@ -34,13 +34,20 @@ import com.android.systemui.statusbar.notification.stack.ViewState;
*/
public class PropertyAnimator {
+ /**
+ * Set a property on a view, updating its value, even if it's already animating.
+ * The @param animated can be used to request an animation.
+ * If the view isn't animated, this utility will update the current animation if existent,
+ * such that the end value will point to @param newEndValue or apply it directly if there's
+ * no animation.
+ */
public static <T extends View> void setProperty(final T view,
AnimatableProperty animatableProperty, float newEndValue,
AnimationProperties properties, boolean animated) {
int animatorTag = animatableProperty.getAnimatorTag();
ValueAnimator previousAnimator = ViewState.getChildTag(view, animatorTag);
if (previousAnimator != null || animated) {
- startAnimation(view, animatableProperty, newEndValue, properties);
+ startAnimation(view, animatableProperty, newEndValue, animated ? properties : null);
} else {
// no new animation needed, let's just apply the value
animatableProperty.getProperty().set(view, newEndValue);
@@ -60,8 +67,8 @@ public class PropertyAnimator {
}
int animatorTag = animatableProperty.getAnimatorTag();
ValueAnimator previousAnimator = ViewState.getChildTag(view, animatorTag);
- AnimationFilter filter = properties.getAnimationFilter();
- if (!filter.shouldAnimateProperty(property)) {
+ AnimationFilter filter = properties != null ? properties.getAnimationFilter() : null;
+ if (filter == null || !filter.shouldAnimateProperty(property)) {
// just a local update was performed
if (previousAnimator != null) {
// we need to increase all animation keyframes of the previous animator by the
@@ -82,6 +89,14 @@ public class PropertyAnimator {
}
Float currentValue = property.get(view);
+ AnimatorListenerAdapter listener = properties.getAnimationFinishListener(property);
+ if (currentValue.equals(newEndValue)) {
+ // Skip the animation!
+ if (listener != null) {
+ listener.onAnimationEnd(null);
+ }
+ return;
+ }
ValueAnimator animator = ValueAnimator.ofFloat(currentValue, newEndValue);
animator.addUpdateListener(
animation -> property.set(view, (Float) animation.getAnimatedValue()));
@@ -96,7 +111,6 @@ public class PropertyAnimator {
|| previousAnimator.getAnimatedFraction() == 0)) {
animator.setStartDelay(properties.delay);
}
- AnimatorListenerAdapter listener = properties.getAnimationFinishListener(property);
if (listener != null) {
animator.addListener(listener);
}