Flutter嵌套滚动管理插件nested_scroll_controller的使用

发布于 1周前 作者 gougou168 来自 Flutter

Flutter嵌套滚动管理插件nested_scroll_controller的使用

介绍

nested_scroll_controller 是一个用于控制 NestedScrollView 的小库,就像控制普通的滚动视图一样。它允许你执行以下操作:

  • 动画到某个偏移量或索引
  • 跳转到某个偏移量或索引
  • 添加监听器以获取总偏移量

使用方法

以下是使用 NestedScrollController 的五个主要步骤:

  1. 创建 NestedScrollController
  2. NestedScrollView 的控制器设置为 nestedScrollController
  3. NestedScrollView 的主体部分用 LayoutBuilder 包裹。
  4. 启用滚动和中心滚动(如果需要)。
  5. 在任何地方使用 NestedScrollController

下面是完整的示例代码:

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

/// 一个简单的示例应用程序,演示 [NestedScrollController] 的基本用法。
///
/// 下面的代码是从 [https://api.flutter.dev/flutter/widgets/NestedScrollView-class.html] 复制并修改的。
/// 唯一的修改是为了清晰地展示 [NestedScrollController] 的使用。

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

final double itemExtent = 48.0;

class TestApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "NestedScrollController 示例",
      home: ExamplePage(),
    );
  }
}

class ExamplePage extends StatelessWidget {
  List<String> get _tabs => ["One", "Two"];

  /// 1. 创建 [NestedScrollController]
  final NestedScrollController nestedScrollController = NestedScrollController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: DefaultTabController(
        length: _tabs.length,
        child: NestedScrollView(
          /// 2. 将控制器传递给 [NestedScrollView]
          controller: nestedScrollController,
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            return <Widget>[
              SliverOverlapAbsorber(
                handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
                sliver: SliverAppBar(
                  title: const Text('Books'),
                  pinned: true,
                  expandedHeight: 200.0,
                  forceElevated: innerBoxIsScrolled,
                  bottom: TabBar(
                    tabs: _tabs.map((String name) => Tab(text: name)).toList(),
                  ),
                ),
              ),
            ];
          },

          /// 3. 使用 [LayoutBuilder] 包裹 [NestedScrollView.body]
          body: LayoutBuilder(
            builder: (BuildContext context, BoxConstraints constraints) {
              /// 4. 提供 [NestedScrollController] 上下文和约束条件
              nestedScrollController.enableScroll(context);
              nestedScrollController.enableCenterScroll(constraints);

              return TabBarView(
                children: _tabs.map((String name) {
                  return SafeArea(
                    top: false,
                    bottom: false,
                    child: CustomScrollView(
                      key: PageStorageKey<String>(name),
                      slivers: <Widget>[
                        SliverOverlapInjector(
                          handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
                        ),
                        SliverPadding(
                          padding: const EdgeInsets.all(8.0),
                          sliver: SliverFixedExtentList(
                            itemExtent: itemExtent,
                            delegate: SliverChildBuilderDelegate(
                              (BuildContext context, int index) {
                                return ListTile(
                                  title: Text('Item $index'),
                                  onTap: () {
                                    /// 5. 使用 [NestedScrollController]
                                    nestedScrollController.nestedAnimateTo(index * itemExtent);
                                  },
                                );
                              },
                              childCount: 30,
                            ),
                          ),
                        ),
                      ],
                    ),
                  );
                }).toList(),
              );
            },
          ),
        ),
      ),
    );
  }
}

添加监听器

你可以像对普通滚动控制器那样添加和移除监听器:

nestedScrollController.addListener(() {
  print("外部: ${nestedScrollController.offset}");
  print("内部: ${nestedScrollController.innerOffset}");
  print("总计: ${nestedScrollController.totalOffset}");
});

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

1 回复

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


当然,关于Flutter中的nested_scroll_controller插件的使用,这里提供一个简单的代码示例来展示如何管理嵌套滚动。nested_scroll_controller插件主要用于处理Flutter中复杂的嵌套滚动场景,比如在一个可滚动的页面中嵌套另一个可滚动的列表。

首先,确保你已经在pubspec.yaml文件中添加了nested_scroll_view依赖(注意,虽然名字相似,但nested_scroll_controller实际上并不是Flutter官方或广泛使用的包名,这里我们假设你指的是处理嵌套滚动的通用方法,Flutter官方提供了一些处理嵌套滚动的机制,比如NestedScrollView)。然而,为了说明目的,我将展示如何使用NestedScrollViewSliverAppBar来管理嵌套滚动,这是Flutter原生支持的一种常见方式。

dependencies:
  flutter:
    sdk: flutter

接下来,在你的Dart文件中实现嵌套滚动视图:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Nested Scroll Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: NestedScrollExample(),
    );
  }
}

class NestedScrollExample extends StatefulWidget {
  @override
  _NestedScrollExampleState createState() => _NestedScrollExampleState();
}

class _NestedScrollExampleState extends State<NestedScrollExample> {
  final NestedScrollViewController _nestedScrollController =
      NestedScrollViewController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: NestedScrollView(
        controller: _nestedScrollController,
        headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
          return <Widget>[
            SliverAppBar(
              title: Text('Nested Scroll Example'),
              floating: true,
              pinned: true,
              snap: false,
              expandedHeight: 200.0,
              flexibleSpace: FlexibleSpaceBar(
                centerTitle: true,
                title: Text('Scroll Down'),
                background: Image.network(
                  'https://via.placeholder.com/1500x600',
                  fit: BoxFit.cover,
                ),
              ),
            ),
          ];
        },
        body: Builder(
          builder: (BuildContext context) {
            return ListView.builder(
              itemCount: 50,
              itemBuilder: (BuildContext context, int index) {
                return ListTile(
                  title: Text('Item $index'),
                );
              },
            );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // Scroll to the top of the inner list
          _nestedScrollController.scrollTo(0.0,
              preferPosition: AutoscrollPosition.begin);
        },
        tooltip: 'Scroll to Top',
        child: Icon(Icons.arrow_upward),
      ),
    );
  }
}

在这个例子中:

  • NestedScrollView 被用来创建一个支持嵌套滚动的视图。
  • headerSliverBuilder 参数用于构建头部,这里我们使用了 SliverAppBar,它支持响应滚动事件并改变其外观(比如折叠或展开)。
  • ListView.builder 被用作内部滚动视图,生成了一个包含50个条目的列表。
  • NestedScrollViewController 允许我们控制嵌套滚动的行为,比如在这个例子中,我们用它来实现滚动到列表顶部的功能。

注意,虽然这个示例没有直接使用名为nested_scroll_controller的插件(因为这个名字可能指向一个不存在的或特定用途的插件),但它展示了Flutter原生如何处理嵌套滚动的一种常见和强大的方式。如果你确实在寻找一个特定的第三方插件来处理嵌套滚动,请确保查阅该插件的官方文档以获取准确的使用指南和示例代码。

回到顶部