summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2023-03-23 18:57:24 +0000
committer Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> 2023-03-23 18:57:24 +0000
commit2ca1722eed8806dafd814e61bbdd0578fdda90cc (patch)
tree17d803ce60c108f7e83d753bf2d06c05d32219e0
parentbd116374228ddfc1b2a4e40d70484636837d007e (diff)
parent85ff8d76831e01c3a9b3a04db0ec480094505b7e (diff)
Merge "Update Chooser icon animation; animate labels" into udc-dev am: 85ff8d7683
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/modules/IntentResolver/+/22214716 Change-Id: I4ca94e88814c4b2816e64ea32ce791f4161e1b83 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--java/src/com/android/intentresolver/ChooserListAdapter.java23
-rw-r--r--java/src/com/android/intentresolver/ItemRevealAnimationTracker.kt70
-rw-r--r--java/src/com/android/intentresolver/ResolverListAdapter.java18
3 files changed, 94 insertions, 17 deletions
diff --git a/java/src/com/android/intentresolver/ChooserListAdapter.java b/java/src/com/android/intentresolver/ChooserListAdapter.java
index dab44577..ceeed6f0 100644
--- a/java/src/com/android/intentresolver/ChooserListAdapter.java
+++ b/java/src/com/android/intentresolver/ChooserListAdapter.java
@@ -98,6 +98,8 @@ public class ChooserListAdapter extends ResolverListAdapter {
// Sorted list of DisplayResolveInfos for the alphabetical app section.
private List<DisplayResolveInfo> mSortedList = new ArrayList<>();
+ private final ItemRevealAnimationTracker mAnimationTracker = new ItemRevealAnimationTracker();
+
// For pinned direct share labels, if the text spans multiple lines, the TextView will consume
// the full width, even if the characters actually take up less than that. Measure the actual
// line widths and constrain the View's width based upon that so that the pin doesn't end up
@@ -243,6 +245,15 @@ public class ChooserListAdapter extends ResolverListAdapter {
}
+ @Override
+ protected boolean rebuildList(boolean doPostProcessing) {
+ mAnimationTracker.reset();
+ mSortedList.clear();
+ boolean result = super.rebuildList(doPostProcessing);
+ notifyDataSetChanged();
+ return result;
+ }
+
private void createPlaceHolders() {
mServiceTargets.clear();
for (int i = 0; i < mMaxRankedTargets; ++i) {
@@ -266,7 +277,17 @@ public class ChooserListAdapter extends ResolverListAdapter {
}
holder.bindLabel(info.getDisplayLabel(), info.getExtendedInfo(), alwaysShowSubLabel());
- holder.bindIcon(info, /*animate =*/ true);
+ mAnimationTracker.animateLabel(holder.text, info);
+ if (holder.text2.getVisibility() == View.VISIBLE) {
+ mAnimationTracker.animateLabel(holder.text2, info);
+ }
+ holder.bindIcon(info);
+ if (info.getDisplayIconHolder().getDisplayIcon() != null) {
+ mAnimationTracker.animateIcon(holder.icon, info);
+ } else {
+ holder.icon.clearAnimation();
+ }
+
if (info.isSelectableTargetInfo()) {
// direct share targets should append the application name for a better readout
DisplayResolveInfo rInfo = info.getDisplayResolveInfo();
diff --git a/java/src/com/android/intentresolver/ItemRevealAnimationTracker.kt b/java/src/com/android/intentresolver/ItemRevealAnimationTracker.kt
new file mode 100644
index 00000000..d3e07c6b
--- /dev/null
+++ b/java/src/com/android/intentresolver/ItemRevealAnimationTracker.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 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.intentresolver
+
+import android.view.View
+import android.view.animation.AlphaAnimation
+import android.view.animation.LinearInterpolator
+import android.view.animation.Transformation
+import com.android.intentresolver.chooser.TargetInfo
+
+private const val IMAGE_FADE_IN_MILLIS = 150L
+
+internal class ItemRevealAnimationTracker {
+ private val iconProgress = HashMap<TargetInfo, Record>()
+ private val labelProgress = HashMap<TargetInfo, Record>()
+
+ fun reset() {
+ iconProgress.clear()
+ labelProgress.clear()
+ }
+
+ fun animateIcon(view: View, info: TargetInfo) = animateView(view, info, iconProgress)
+ fun animateLabel(view: View, info: TargetInfo) = animateView(view, info, labelProgress)
+
+ private fun animateView(view: View, info: TargetInfo, map: MutableMap<TargetInfo, Record>) {
+ val record = map.getOrPut(info) {
+ Record()
+ }
+ if ((view.animation as? RevealAnimation)?.record === record) return
+
+ view.clearAnimation()
+ if (record.alpha >= 1f) {
+ view.alpha = 1f
+ return
+ }
+
+ view.startAnimation(RevealAnimation(record))
+ }
+
+ private class Record(var alpha: Float = 0f)
+
+ private class RevealAnimation(val record: Record) : AlphaAnimation(record.alpha, 1f) {
+ init {
+ duration = (IMAGE_FADE_IN_MILLIS * (1f - record.alpha)).toLong()
+ interpolator = LinearInterpolator()
+ }
+
+ override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
+ super.applyTransformation(interpolatedTime, t)
+ // One TargetInfo can be simultaneously bou into multiple UI grid items; make sure
+ // that the alpha value only increases. This should not affect running animations, only
+ // a starting point for a new animation when a different view is bound to this target.
+ record.alpha = minOf(1f, maxOf(record.alpha, t.alpha))
+ }
+ }
+}
diff --git a/java/src/com/android/intentresolver/ResolverListAdapter.java b/java/src/com/android/intentresolver/ResolverListAdapter.java
index b0586f2d..f090f3a2 100644
--- a/java/src/com/android/intentresolver/ResolverListAdapter.java
+++ b/java/src/com/android/intentresolver/ResolverListAdapter.java
@@ -18,7 +18,6 @@ package com.android.intentresolver;
import static android.content.Context.ACTIVITY_SERVICE;
-import android.animation.ObjectAnimator;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -43,7 +42,6 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.view.animation.DecelerateInterpolator;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
@@ -926,7 +924,6 @@ public class ResolverListAdapter extends BaseAdapter {
*/
@VisibleForTesting
public static class ViewHolder {
- private static final long IMAGE_FADE_IN_MILLIS = 150;
public View itemView;
public Drawable defaultItemViewBackground;
@@ -964,23 +961,12 @@ public class ResolverListAdapter extends BaseAdapter {
itemView.setContentDescription(description);
}
- public void bindIcon(TargetInfo info) {
- bindIcon(info, false);
- }
-
/**
- * Bind view holder to a TargetInfo, run icon reveal animation, if required.
+ * Bind view holder to a TargetInfo.
*/
- public void bindIcon(TargetInfo info, boolean animate) {
+ public void bindIcon(TargetInfo info) {
Drawable displayIcon = info.getDisplayIconHolder().getDisplayIcon();
- boolean runAnimation = animate && (icon.getDrawable() == null) && (displayIcon != null);
icon.setImageDrawable(displayIcon);
- if (runAnimation) {
- ObjectAnimator animator = ObjectAnimator.ofFloat(icon, "alpha", 0.0f, 1.0f);
- animator.setInterpolator(new DecelerateInterpolator(1.0f));
- animator.setDuration(IMAGE_FADE_IN_MILLIS);
- animator.start();
- }
if (info.isSuspended()) {
icon.setColorFilter(getSuspendedColorMatrix());
} else {