From 50912b10c9c8231bab05b9f0459c681d76dd6081 Mon Sep 17 00:00:00 2001 From: fengjignqi <15192412330@163.com> Date: Tue, 19 May 2026 18:03:35 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A6=96=E9=A1=B5=E8=AE=BE=E5=A4=87=E5=88=97?= =?UTF-8?q?=E8=A1=A8,=E4=B8=8A=E6=8B=89=E5=8A=A0=E8=BD=BD=EF=BC=8C?= =?UTF-8?q?=E4=B8=8B=E6=8B=89=E5=88=B7=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../custom/view/CustomRefreshHeader.java | 62 ++++++++++++++++--- 1 file changed, 55 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/ckkj/water/custom/view/CustomRefreshHeader.java b/app/src/main/java/com/ckkj/water/custom/view/CustomRefreshHeader.java index 627b58a..4772b4a 100644 --- a/app/src/main/java/com/ckkj/water/custom/view/CustomRefreshHeader.java +++ b/app/src/main/java/com/ckkj/water/custom/view/CustomRefreshHeader.java @@ -32,6 +32,10 @@ public class CustomRefreshHeader extends RelativeLayout implements RefreshHeader private ImageView ivRefresh; private ObjectAnimator rotateAnimator; + // 用于 onMoving 中的动态效果 + private float mLastPercent = 0f; + // 记录当前缩放值,避免重复设置 + private float mCurrentScale = 1f; public CustomRefreshHeader(Context context) { super(context); @@ -47,11 +51,14 @@ public class CustomRefreshHeader extends RelativeLayout implements RefreshHeader LayoutInflater.from(context).inflate(R.layout.view_refresh_header, this); ivRefresh = findViewById(R.id.ivRefresh); + // 开启硬件加速,提升动画性能 + setLayerType(LAYER_TYPE_HARDWARE, null); + // 初始化 ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(ivRefresh, "rotation", 0f, 360f); rotateAnimator.setDuration(1500); rotateAnimator.setRepeatCount(ValueAnimator.INFINITE); - rotateAnimator.setInterpolator(new LinearInterpolator()); // 匀速旋转 + rotateAnimator.setInterpolator(new LinearInterpolator()); } @NonNull @@ -72,16 +79,36 @@ public class CustomRefreshHeader extends RelativeLayout implements RefreshHeader @Override public int onFinish(@NonNull RefreshLayout layout, boolean success) { if (rotateAnimator != null && rotateAnimator.isRunning()) { - // 为了平滑停止,先设置减速插值器,再 cancel 动画 rotateAnimator.setInterpolator(new DecelerateInterpolator()); postDelayed(() -> { if (rotateAnimator != null) { rotateAnimator.cancel(); - rotateAnimator.setInterpolator(new LinearInterpolator()); // 恢复为匀速 + rotateAnimator.setInterpolator(new LinearInterpolator()); } - }, 300); // 给一点缓冲时间 + }, 300); } - return 500; // 动画停止后延迟 500ms 收起 Header + // 动画过渡回正常大小 + animateToNormalScale(); + return 500; + } + + /** + * 平滑动画过渡回正常大小 + */ + private void animateToNormalScale() { + if (ivRefresh == null) return; + + float startScale = mCurrentScale; + ValueAnimator scaleAnimator = ValueAnimator.ofFloat(startScale, 1f); + scaleAnimator.setDuration(300); + scaleAnimator.setInterpolator(new DecelerateInterpolator()); + scaleAnimator.addUpdateListener(animation -> { + float value = (float) animation.getAnimatedValue(); + ivRefresh.setScaleX(value); + ivRefresh.setScaleY(value); + mCurrentScale = value; + }); + scaleAnimator.start(); } // --- 必须实现的方法 --- @@ -107,7 +134,24 @@ public class CustomRefreshHeader extends RelativeLayout implements RefreshHeader @SuppressLint("RestrictedApi") @Override - public void onMoving(boolean isDragging, float percent, int offset, int height, int maxDragHeight) {} + public void onMoving(boolean isDragging, float percent, int offset, int height, int maxDragHeight) { + // 只在拖动过程中处理,避免过度计算 + if (percent != mLastPercent) { + mLastPercent = percent; + + // 1. 动态缩放效果:从 0.5 放大到 1.2 + // 使用 clamp 限制范围:percent 0~1 -> scale 0.5~1.2 + float targetScale = 0.5f + (0.7f * Math.min(percent, 1.0f)); + if (Math.abs(targetScale - mCurrentScale) > 0.01f) { + mCurrentScale = targetScale; + ivRefresh.setScaleX(targetScale); + ivRefresh.setScaleY(targetScale); + } + + // 2. 透明度渐变效果(可选) + // ivRefresh.setAlpha(Math.min(percent * 1.5f, 1.0f)); + } + } @SuppressLint("RestrictedApi") @Override @@ -125,6 +169,10 @@ public class CustomRefreshHeader extends RelativeLayout implements RefreshHeader @SuppressLint("RestrictedApi") @Override public void onStateChanged(@NonNull RefreshLayout refreshLayout, @NonNull RefreshState oldState, @NonNull RefreshState newState) { - + // 状态切换时平滑恢复 + if (newState == RefreshState.PullDownCanceled) { + // 用户取消下拉,恢复到初始状态 + animateToNormalScale(); + } } } \ No newline at end of file