Flutter滚动物理效果插件snap_scroll_physics的使用

Flutter滚动物理效果插件snap_scroll_physics的使用

当构建可滚动视图时,有时你希望滚动停止在特定的偏移量处,或者避免在某些区域内停止。此包允许你在任何 Flutter 滚动视图中实现这种行为。

这种行为可以在任何使用 UIKit/SwiftUI 导航栏的 iOS 应用中看到,也可以在一些流行的定制头部应用中看到,比如 Twitter、Chrome、Gmail、Google Photos、Apple Music、Facebook 等!

snap_scroll

physics: SnapScrollPhysics(
    snaps: [
        Snap(200, distance: 50), // 如果预期滚动停止在 150-250 之间,则滚动将停在 200
        Snap(200, leadingDistance: 50), // 如果预期滚动停止在 150-200 之间,则滚动将停在 200
        Snap(200, trailingDistance: 50), // 如果预期滚动停止在 150-200 之间,则滚动将停在 200
        Snap.avoidZone(0, 200), // 如果预期滚动停止在 0-200 之间,滚动将在 0-99 之间停在 0,在 100-200 之间停在 200
        Snap.avoidZone(0, 200, delimiter: 50), // 如果预期滚动停止在 0-200 之间,滚动将在 0-49 之间停在 0,在 50-200 之间停在 200
    ]
),
physics: SnapScrollPhysics.cupertinoAppBar, // 默认值适用于 Cupertino 应用程序栏

重要!遗憾的是,滚动物理属性不是实时更新的,因此如果你更改了这些值,它们不会自动更新。请参阅Issue 80051

这可以通过以下方式临时解决,但在生产环境中如果没有运行时需要更改的情况,这是不建议的:

List<Snap> getSnaps() {
    return [
       Snap(200), // 热重载有效
    ];
}

[@override](/user/override)
Widget build(BuildContext context) {
    return CustomScrollView(
      physics: SnapScrollPhysics.builder(getSnaps),
      slivers: [
       // ....
      ],
    );
}

示例代码

以下是完整的示例代码:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:snap_scroll_physics/snap_scroll_physics.dart';
import 'examples/material.dart';
import 'examples/cupertino.dart';
import 'examples/music.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int index = 0;

  [@override](/user/override)
  Widget build(BuildContext context) {
    bool showBottomBar = true;
    return Scaffold(
      body: [
        () => MaterialExamplePage(),
        () => CupertinoExamplePage(),
        () => MusicExamplePage(),
      ][index](),
      bottomNavigationBar: showBottomBar ? BottomNavigationBar(
        currentIndex: index,
        onTap: (index) => setState(() => this.index = index),
        items: [
          BottomNavigationBarItem(
            label: 'Material',
            icon: Icon(Icons.adb),
          ),
          BottomNavigationBarItem(
            label: 'Cupertino',
            icon: Icon(Icons.tab),
          ),
          BottomNavigationBarItem(
            label: 'Music',
            icon: Icon(Icons.music_note),
          )
        ],
      ) : null,
    );
  }
}

更多关于Flutter滚动物理效果插件snap_scroll_physics的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter滚动物理效果插件snap_scroll_physics的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


snap_scroll_physics 是一个用于 Flutter 的自定义滚动物理插件,它可以帮助你在滚动列表时实现“吸附”效果。这个效果通常用于需要精确对齐到某个位置的场景,比如让 ListView 的 item 自动对齐到屏幕中心。

安装

首先,你需要在 pubspec.yaml 文件中添加 snap_scroll_physics 依赖:

dependencies:
  flutter:
    sdk: flutter
  snap_scroll_physics: ^0.1.0 # 请检查最新版本

然后运行 flutter pub get 来安装依赖。

使用

以下是一个简单的例子,展示如何在 ListView 中使用 SnapScrollPhysics

import 'package:flutter/material.dart';
import 'package:snap_scroll_physics/snap_scroll_physics.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('SnapScrollPhysics Example'),
        ),
        body: Center(
          child: ListView.builder(
            physics: SnapScrollPhysics(
              itemExtent: 100.0, // 每个 item 的高度
              velocityFactor: 0.5, // 滚动速度因子
            ),
            itemCount: 20,
            itemBuilder: (context, index) {
              return Container(
                height: 100.0,
                color: index % 2 == 0 ? Colors.blue : Colors.green,
                child: Center(
                  child: Text(
                    'Item $index',
                    style: TextStyle(fontSize: 24, color: Colors.white),
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );
  }
}

参数说明

  • itemExtent: 每个 item 的高度(或宽度,如果是水平滚动)。这是必须指定的,因为它用于计算滚动位置。
  • velocityFactor: 滚动速度因子,控制滚动的速度。默认值为 1.0,值越小滚动速度越慢。
  • snapToStart: 是否在滚动结束时吸附到第一个 item。
  • snapToEnd: 是否在滚动结束时吸附到最后一个 item。
  • snapToAlignment: 吸附对齐方式,可以设置为 0.01.0 之间的值,表示吸附到 item 的某个位置。例如,0.5 表示吸附到 item 的中心。

自定义吸附行为

你还可以通过继承 SnapScrollPhysics 来自定义吸附行为。例如:

class CustomSnapScrollPhysics extends SnapScrollPhysics {
  CustomSnapScrollPhysics({double itemExtent}) : super(itemExtent: itemExtent);

  [@override](/user/override)
  CustomSnapScrollPhysics applyTo(ScrollPhysics ancestor) {
    return CustomSnapScrollPhysics(itemExtent: itemExtent);
  }

  [@override](/user/override)
  Simulation createBallisticSimulation(
      ScrollMetrics position, double velocity) {
    // 自定义吸附逻辑
    final simulation = super.createBallisticSimulation(position, velocity);
    if (simulation != null) {
      return simulation;
    }
    // 添加自定义逻辑
    return null;
  }
}
回到顶部