Remove direct-share target row animations and limit to one row.
The animation---which was responsible for causing relayouts that would in turn bind views, which involved package manager roundtrips---would lock out interaction with the rest of the share sheet for at least 400ms while the animation ran (often much longer if services were slow to start or respond). Now the main UI is never blocked, and direct share targets can take as long as they like (up to 2sec) before appearing. It's really fast now, basically. Bug: 67622422 Bug: 63521992 Test: atest com.android.internal.app.ChooserActivityTest Change-Id: I21826e282226f2b2ce6d3d1b5862dbfc449f5918
This commit is contained in:
committed by
Daniel Sandler
parent
8997b7e4c9
commit
62aad00c6c
@@ -76,6 +76,7 @@ import android.widget.Space;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.app.ResolverActivity;
|
||||
import com.android.internal.app.ResolverActivity.TargetInfo;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
@@ -932,7 +933,7 @@ public class ChooserActivity extends ResolverActivity {
|
||||
public static final int TARGET_SERVICE = 1;
|
||||
public static final int TARGET_STANDARD = 2;
|
||||
|
||||
private static final int MAX_SERVICE_TARGETS = 8;
|
||||
private static final int MAX_SERVICE_TARGETS = 4;
|
||||
private static final int MAX_TARGETS_PER_SERVICE = 4;
|
||||
|
||||
private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>();
|
||||
@@ -1189,123 +1190,20 @@ public class ChooserActivity extends ResolverActivity {
|
||||
}
|
||||
}
|
||||
|
||||
static class RowScale {
|
||||
private static final int DURATION = 400;
|
||||
|
||||
float mScale;
|
||||
ChooserRowAdapter mAdapter;
|
||||
private final ObjectAnimator mAnimator;
|
||||
|
||||
public static final FloatProperty<RowScale> PROPERTY =
|
||||
new FloatProperty<RowScale>("scale") {
|
||||
@Override
|
||||
public void setValue(RowScale object, float value) {
|
||||
object.mScale = value;
|
||||
object.mAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float get(RowScale object) {
|
||||
return object.mScale;
|
||||
}
|
||||
};
|
||||
|
||||
public RowScale(@NonNull ChooserRowAdapter adapter, float from, float to) {
|
||||
mAdapter = adapter;
|
||||
mScale = from;
|
||||
if (from == to) {
|
||||
mAnimator = null;
|
||||
return;
|
||||
}
|
||||
|
||||
mAnimator = ObjectAnimator.ofFloat(this, PROPERTY, from, to)
|
||||
.setDuration(DURATION);
|
||||
mAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mAdapter.onAnimationStart();
|
||||
}
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mAdapter.onAnimationEnd();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public RowScale setInterpolator(Interpolator interpolator) {
|
||||
if (mAnimator != null) {
|
||||
mAnimator.setInterpolator(interpolator);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public float get() {
|
||||
return mScale;
|
||||
}
|
||||
|
||||
public void startAnimation() {
|
||||
if (mAnimator != null) {
|
||||
mAnimator.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void cancelAnimation() {
|
||||
if (mAnimator != null) {
|
||||
mAnimator.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ChooserRowAdapter extends BaseAdapter {
|
||||
private ChooserListAdapter mChooserListAdapter;
|
||||
private final LayoutInflater mLayoutInflater;
|
||||
private final int mColumnCount = 4;
|
||||
private RowScale[] mServiceTargetScale;
|
||||
private final Interpolator mInterpolator;
|
||||
private int mAnimationCount = 0;
|
||||
|
||||
public ChooserRowAdapter(ChooserListAdapter wrappedAdapter) {
|
||||
mChooserListAdapter = wrappedAdapter;
|
||||
mLayoutInflater = LayoutInflater.from(ChooserActivity.this);
|
||||
|
||||
mInterpolator = AnimationUtils.loadInterpolator(ChooserActivity.this,
|
||||
android.R.interpolator.decelerate_quint);
|
||||
|
||||
wrappedAdapter.registerDataSetObserver(new DataSetObserver() {
|
||||
@Override
|
||||
public void onChanged() {
|
||||
super.onChanged();
|
||||
final int rcount = getServiceTargetRowCount();
|
||||
if (mServiceTargetScale == null
|
||||
|| mServiceTargetScale.length != rcount) {
|
||||
RowScale[] old = mServiceTargetScale;
|
||||
int oldRCount = old != null ? old.length : 0;
|
||||
mServiceTargetScale = new RowScale[rcount];
|
||||
if (old != null && rcount > 0) {
|
||||
System.arraycopy(old, 0, mServiceTargetScale, 0,
|
||||
Math.min(old.length, rcount));
|
||||
}
|
||||
|
||||
for (int i = rcount; i < oldRCount; i++) {
|
||||
old[i].cancelAnimation();
|
||||
}
|
||||
|
||||
for (int i = oldRCount; i < rcount; i++) {
|
||||
final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f)
|
||||
.setInterpolator(mInterpolator);
|
||||
mServiceTargetScale[i] = rs;
|
||||
}
|
||||
|
||||
// Start the animations in a separate loop.
|
||||
// The process of starting animations will result in
|
||||
// binding views to set up initial values, and we must
|
||||
// have ALL of the new RowScale objects created above before
|
||||
// we get started.
|
||||
for (int i = oldRCount; i < rcount; i++) {
|
||||
mServiceTargetScale[i].startAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@@ -1313,39 +1211,10 @@ public class ChooserActivity extends ResolverActivity {
|
||||
public void onInvalidated() {
|
||||
super.onInvalidated();
|
||||
notifyDataSetInvalidated();
|
||||
if (mServiceTargetScale != null) {
|
||||
for (RowScale rs : mServiceTargetScale) {
|
||||
rs.cancelAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private float getRowScale(int rowPosition) {
|
||||
final int start = getCallerTargetRowCount();
|
||||
final int end = start + getServiceTargetRowCount();
|
||||
if (rowPosition >= start && rowPosition < end) {
|
||||
return mServiceTargetScale[rowPosition - start].get();
|
||||
}
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
public void onAnimationStart() {
|
||||
final boolean lock = mAnimationCount == 0;
|
||||
mAnimationCount++;
|
||||
if (lock) {
|
||||
mResolverDrawerLayout.setDismissLocked(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void onAnimationEnd() {
|
||||
mAnimationCount--;
|
||||
if (mAnimationCount == 0) {
|
||||
mResolverDrawerLayout.setDismissLocked(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return (int) (
|
||||
@@ -1360,9 +1229,9 @@ public class ChooserActivity extends ResolverActivity {
|
||||
(float) mChooserListAdapter.getCallerTargetCount() / mColumnCount);
|
||||
}
|
||||
|
||||
// There can be at most one row of service targets.
|
||||
public int getServiceTargetRowCount() {
|
||||
return (int) Math.ceil(
|
||||
(float) mChooserListAdapter.getServiceTargetCount() / mColumnCount);
|
||||
return (int) mChooserListAdapter.getServiceTargetCount() == 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1485,8 +1354,7 @@ public class ChooserActivity extends ResolverActivity {
|
||||
}
|
||||
|
||||
final int oldHeight = holder.row.getLayoutParams().height;
|
||||
holder.row.getLayoutParams().height = Math.max(1,
|
||||
(int) (holder.measuredRowHeight * getRowScale(rowPosition)));
|
||||
holder.row.getLayoutParams().height = Math.max(1, holder.measuredRowHeight);
|
||||
if (holder.row.getLayoutParams().height != oldHeight) {
|
||||
holder.row.requestLayout();
|
||||
}
|
||||
@@ -1728,7 +1596,7 @@ public class ChooserActivity extends ResolverActivity {
|
||||
final View v = mChooserRowAdapter.getView(pos, mCachedView, mListView);
|
||||
int height = ((RowViewHolder) (v.getTag())).measuredRowHeight;
|
||||
|
||||
offset += (int) (height * mChooserRowAdapter.getRowScale(pos));
|
||||
offset += (int) (height);
|
||||
|
||||
if (vt >= 0) {
|
||||
mCachedViewType = vt;
|
||||
|
||||
Reference in New Issue
Block a user