perf: reduce high-refresh ui churn

This commit is contained in:
kris
2026-04-04 01:16:48 +08:00
parent 31004c512a
commit 35bcf92d72
2 changed files with 36 additions and 56 deletions

View File

@@ -1,7 +1,5 @@
package com.hyzq.boss;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
@@ -13,7 +11,6 @@ import android.graphics.Typeface;
import android.graphics.drawable.GradientDrawable;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
@@ -1382,62 +1379,12 @@ public final class BossUi {
dp(context, 4)
);
dot.setBackground(drawable);
dot.setAlpha(0.35f);
dot.setScaleX(0.82f);
dot.setScaleY(0.82f);
final AnimatorSet[] animatorRef = new AnimatorSet[1];
dot.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
cancelConversationActivityAnimator(animatorRef);
animatorRef[0] = createConversationActivityAnimator(v, index);
animatorRef[0].start();
}
@Override
public void onViewDetachedFromWindow(View v) {
cancelConversationActivityAnimator(animatorRef);
v.animate().cancel();
v.setAlpha(0.35f);
v.setScaleX(0.82f);
v.setScaleY(0.82f);
}
});
dot.setAlpha(0.92f - (Math.min(index, 2) * 0.12f));
dot.setScaleX(1f);
dot.setScaleY(1f);
return dot;
}
private static AnimatorSet createConversationActivityAnimator(View dot, int index) {
long durationMs = 850L;
long startDelayMs = index * 120L;
ObjectAnimator alpha = ObjectAnimator.ofFloat(dot, View.ALPHA, 0.35f, 1f, 0.35f);
alpha.setDuration(durationMs);
alpha.setStartDelay(startDelayMs);
alpha.setRepeatCount(ObjectAnimator.INFINITE);
ObjectAnimator scaleX = ObjectAnimator.ofFloat(dot, View.SCALE_X, 0.82f, 1.1f, 0.82f);
scaleX.setDuration(durationMs);
scaleX.setStartDelay(startDelayMs);
scaleX.setRepeatCount(ObjectAnimator.INFINITE);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(dot, View.SCALE_Y, 0.82f, 1.1f, 0.82f);
scaleY.setDuration(durationMs);
scaleY.setStartDelay(startDelayMs);
scaleY.setRepeatCount(ObjectAnimator.INFINITE);
AnimatorSet pulse = new AnimatorSet();
pulse.setInterpolator(new AccelerateDecelerateInterpolator());
pulse.playTogether(alpha, scaleX, scaleY);
return pulse;
}
private static void cancelConversationActivityAnimator(AnimatorSet[] animatorRef) {
if (animatorRef[0] != null) {
animatorRef[0].cancel();
animatorRef[0] = null;
}
}
private static int resolveConversationContextColor(Context context, @Nullable String level) {
if (TextUtils.isEmpty(level)) {
return context.getColor(R.color.boss_text_soft);

View File

@@ -103,6 +103,39 @@ public class BossUiConversationRowTest {
assertEquals("上下文环本体应更细更轻", BossUi.dp(context, 16), ringWrap.getChildAt(0).getLayoutParams().height);
}
@Test
public void buildConversationRow_usesStaticActivityDotsForHighRefreshSmoothness() {
Context context = RuntimeEnvironment.getApplication();
WechatSurfaceMapper.ConversationRow row = new WechatSurfaceMapper.ConversationRow(
"硬件审计协作",
"Mac Studio",
"检查摄像头供电链路",
"09:42",
0,
"",
2,
false,
"M",
"W",
new WechatSurfaceMapper.GroupAvatarMember[0],
false,
null,
null,
-1,
false,
false
);
LinearLayout rowView = BossUi.buildConversationRow(context, row, null);
LinearLayout trailingColumn = (LinearLayout) rowView.getChildAt(2);
LinearLayout activityWrap = (LinearLayout) trailingColumn.getChildAt(1);
View firstDot = activityWrap.getChildAt(0);
assertEquals("高刷设备上活动点应保持静态,不再从低 alpha 开始做无限动画", 0.92f, firstDot.getAlpha(), 0.01f);
assertEquals("高刷设备上活动点不应缩放动画起步", 1f, firstDot.getScaleX(), 0.01f);
assertEquals("高刷设备上活动点不应缩放动画起步", 1f, firstDot.getScaleY(), 0.01f);
}
@Test
public void buildConversationRow_usesSubtlePinnedBackgroundWithoutPinnedBadge() {
Context context = RuntimeEnvironment.getApplication();