在Flutter中实现排行榜滑动阻尼效果

在Flutter中实现排行榜滑动阻尼效果

在开发排行榜模块时,UI提出了一个需求,希望滑动时能够增加阻尼效果,每次只能滑动一个Item的宽度,若未达到边界则回弹。这种效果类似于 PageView 的滑动体验,能够更好地限制滑动范围,并提供更为流畅的体验。

预览效果

效果大致如下图所示:

实现方法

针对这种需求,我们可以通过自定义 ScrollPhysics 来实现。下面是具体实现代码。

自定义 ScrollPhysics

首先,我们创建一个名为 CustomScrollPhysics 的类,继承自 ScrollPhysics。在该类中,我们通过对滑动进行控制,来实现指定宽度的滑动,并在未达到滑动目标时回弹。

dart 复制代码
import 'package:flutter/material.dart';

// 自定义滑动吸附布局
class CustomScrollPhysics extends ScrollPhysics {
  final double itemDimension;

  const CustomScrollPhysics({required this.itemDimension, super.parent});

  @override
  CustomScrollPhysics applyTo(ScrollPhysics? ancestor) {
    return CustomScrollPhysics(itemDimension: itemDimension, parent: buildParent(ancestor));
  }

  double _getPage(ScrollMetrics position) {
    return position.pixels / itemDimension;
  }

  double _getPixels(double page) {
    return page * itemDimension;
  }

  double _getTargetPixels(ScrollMetrics position, Tolerance tolerance, double velocity) {
    double page = _getPage(position);
    if (velocity < -tolerance.velocity) {
      page -= 0.5;
    } else if (velocity > tolerance.velocity) {
      page += 0.5;
    }
    return _getPixels(page.roundToDouble());
  }

  @override
  Simulation? createBallisticSimulation(ScrollMetrics position, double velocity) {
    // 如果超出范围且不返回,使用父级的物理模拟以返回到边界
    if ((velocity <= 0.0 && position.pixels <= position.minScrollExtent) ||
        (velocity >= 0.0 && position.pixels >= position.maxScrollExtent)) {
      return super.createBallisticSimulation(position, velocity);
    }
    final Tolerance tolerance = this.tolerance;
    final double target = _getTargetPixels(position, tolerance, velocity);
    if (target != position.pixels) {
      return ScrollSpringSimulation(spring, position.pixels, target, velocity, tolerance: tolerance);
    }
    return null;
  }

  @override
  bool get allowImplicitScrolling => false;
}

参数解释

复制代码
•	itemDimension:定义每次滑动的最大距离,这里可以设置为单个Item的宽度。
•	_getTargetPixels:根据滑动的速度和方向,计算滑动的最终位置,若未达到边界则回弹。
•	createBallisticSimulation:负责创建弹簧效果的模拟,确保每次滑动达到指定的距离。

使用 CustomScrollPhysics

将 CustomScrollPhysics 应用到需要此效果的 ListView 中即可。以下是 ListView 的代码示例:

dart 复制代码
ListView.separated(
  padding: EdgeInsets.only(left: 12.w, right: lastItemRightPadding),
  scrollDirection: Axis.horizontal,
  physics: CustomScrollPhysics(itemDimension: columnItemWidth + 20.w),
  // 其他参数...
);

在这里,itemDimension 指定了滑动的宽度,每次滑动将固定一个Item的宽度(在示例中设置为屏幕宽度的2/3),从而实现预期效果。

总结

通过自定义 ScrollPhysics,我们成功地在排行榜模块中实现了阻尼效果,让滑动体验更具限制性和弹性。此方法适用于各种需要自定义滑动物理的场景,不仅提升了视觉效果,也让用户操作更加直观。

相关推荐
西西学代码5 小时前
Charge-BleDevice
flutter
子非鱼942711 小时前
07-Flutter 鸿蒙实战 07:故事集列表与缓存设计
学习·flutter·缓存·华为·harmonyos
子非鱼942713 小时前
08-Flutter 鸿蒙实战 08:故事详情页,编辑、删除、重新生成与底部弹层
flutter·华为·harmonyos
子非鱼942714 小时前
06-Flutter 鸿蒙实战 06:上传后处理流程,照片识别、故事生成和状态刷新
学习·flutter·华为·harmonyos
sTone8737517 小时前
写时复制COW的第一性理解
android·c++·flutter
nicepainkiller17 小时前
codex 逆向 flutter
flutter·flutter 逆向
帅次17 小时前
Android 高级工程师面试:Flutter 路由导航 近1年高频追问 18 题
android·flutter·面试
浮江雾18 小时前
Flutter第七节-----快捷键创建组件与flutter中的点击事件
flutter
想你依然心痛1 天前
【共创季稿事节】HarmonyOS 7.0 应用框架(ArkUI-X)跨平台能力深度探索
flutter·react native·arkui-x·跨平台渲染·harmonyos 7.0·arkrender·组件兼容性
SoaringHeart1 天前
Flutter最佳实践:键盘辅助视图输入框天添加图片附件
前端·flutter