Flutter锚点定位插件flutter_anchorlable的使用

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

Flutter锚点定位插件flutter_anchorlable的使用

flutter_anchorlable 是一个用于Flutter的插件,它提供了可自由滚动的小部件及其控制器,并以键作为锚点。通过这个插件,你可以轻松实现页面内滚动到指定位置的功能。

安装

在你的Flutter项目的pubspec.yaml文件中添加以下依赖:

dependencies:
  flutter_anchorlable: <latest_version>

然后,在你的库中添加以下导入:

import 'package:flutter_anchorlable/flutter_anchorlable.dart';

使用

创建控制器

AnchorlableController 是一个控制器,它允许你滚动由附加客户端拥有的小部件。通过指定 initialAnchorKey,可以指定附加客户端的初始滚动位置。

final controller = AnchorlableController();

跳转到指定锚点

jumpToAnchor 方法可以让页面直接跳转到指定的锚点。

controller.jumpToAnchor(anchorKey);

动画滚动到指定锚点

animateToAnchor 方法可以为带有目标键的小部件执行动画滚动。如果你不确定选择哪种曲线(Curve),可以参考 Flutter官方文档

onPressed: () async {
  await controller.animateToAnchor(anchor,
                duration: const Duration(seconds: 1),
                curve: Curves.fastOutSlowIn);
}

垂直排列小部件

AnchorlableScrollColumn 可以用来垂直排列小部件。它需要一个 KeyAnchorlableController。通过使用 AnchorlableController,可以滚动带有 Key 的小部件。

final controller = AnchorlableController();
const anchorKey = GlobalObjectKey('anchor');
AnchorlableScrollColumn(
  controller: controller,
  children: [
    Container(
      child: Text(
        key: anchorKey,
        'Widgets you want to anchor',
      ),
    ),
    // 其他子组件
  ],
);

水平排列小部件

AnchorlableScrollRowAnchorlableScrollColumn 的横向版本。

final controller = AnchorlableController();
const anchorKey = GlobalObjectKey('anchor');
AnchorlableScrollRow(
  controller: controller,
  children: [
    Container(
      child: Text(
        key: anchorKey,
        'Widgets you want to anchor',
      ),
    ),
    // 其他子组件
  ],
);

CustomScrollView 配合使用

AnchorlableSliverColumn 是一个可以与 CustomScrollView 一起使用的锚点小部件。与 AnchorlableScrollColumn 不同,它需要一些额外的工作来处理 AnchorlableController

final controller = AnchorlableController();
const anchorKey = GlobalObjectKey('anchor');
CustomScrollView(
  controller: controller,
  slivers: [
    AnchorlableSliverColumn(
      children: [
        Container(
          child: Text(
            key: anchorKey,
            'Widgets you want to anchor',
          ),
        ),
        // 其他子组件
      ],
    ),
  ],
);

AnchorlableSliverRowAnchorlableSliverColumn 的横向版本。

示例代码

下面是一个完整的示例,展示了如何使用 flutter_anchorlable 实现一个简单的个人作品集网站:

import 'package:flutter/material.dart';
import 'package:flutter_anchorlable/flutter_anchorlable.dart';
import 'package:url_launcher/url_launcher.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Hiyoko's Portfolio",
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    final anchorlableBodyController = AnchorlableController();

    Widget animateJumpButton(String data, GlobalKey anchor) => TextButton(
          onPressed: () async {
            await anchorlableBodyController.animateToAnchor(anchor,
                duration: const Duration(seconds: 1),
                curve: Curves.fastOutSlowIn);
          },
          child: Text(
            data,
            style: const TextStyle(fontSize: 30, color: Colors.black),
          ),
        );

    Widget Footer() {
      return Container(
        height: 100,
        width: MediaQuery.of(context).size.width,
        key: contactKey,
        alignment: Alignment.bottomLeft,
        color: Colors.black,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            const Text(
              'Contact Me',
              style: TextStyle(color: Colors.white, fontSize: 32),
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.end,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                IconButton(
                  iconSize: 50,
                  icon: const Icon(Icons.web, color: Colors.white),
                  onPressed: () async {
                    await launchUrl(Uri.parse('https://zenn.dev/antman'));
                  },
                ),
                IconButton(
                  iconSize: 50,
                  icon: const Icon(Icons.github, color: Colors.white),
                  onPressed: () async {
                    await launchUrl(Uri.parse('https://github.com/yama-yeah'));
                  },
                ),
              ],
            ),
          ],
        ),
      );
    }

    Widget Header() {
      return Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          const Text("Hiyoko's Portfolio", style: TextStyle(fontSize: 32)),
          Padding(
            padding: const EdgeInsets.only(right: 40),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                animateJumpButton('works', worksKey),
                animateJumpButton('Intro', introKey),
                animateJumpButton('Contact', contactKey),
              ],
            ),
          ),
        ],
      );
    }

    Widget work(String data, String imageUrl, String url) => TextButton(
          onPressed: () async => await launchUrl(Uri.parse(url)),
          child: Column(
            children: [
              Text(data, style: const TextStyle(fontSize: 48)),
              Image.network(
                imageUrl,
                width: 400,
              ),
            ],
          ),
        );

    return Scaffold(
      body: AnchorlableScrollColumn(
        shrinkWrap: true,
        controller: anchorlableBodyController,
        children: [
          Header(),
          const SizedBox(height: 60),
          const Text(
            key: introKey,
            'Hello My name is Hiyoko!!!',
            style: TextStyle(fontSize: 32),
          ),
          const Text(
            'I like a Humbugger!!!',
            style: TextStyle(fontSize: 32),
          ),
          const Text(
            'Welcome to my site',
            style: TextStyle(fontSize: 32),
          ),
          const SizedBox(height: 60),
          SizedBox(
            height: 1100,
            child: Column(
              key: worksKey,
              children: [
                const Text(
                  'There are My Works',
                  style: TextStyle(fontSize: 32),
                ),
                Row(
                  children: [
                    work(
                      'Maho',
                      'https://user-images.githubusercontent.com/82094614/190878311-8049c43e-360f-449c-85d2-3958aa5754f.png',
                      'https://github.com/yama-yeah/Maho',
                    ),
                    work(
                      'glassmorphism_widget',
                      'https://user-images.githubusercontent.com/82094614/147371522-76db6662-3945-4470-bad3-1dfec306ccd1.png',
                      'https://github.com/yama-yeah/glassmorphism_widgets',
                    ),
                    work(
                      'flutter_anchorlable',
                      'https://user-images.githubusercontent.com/82094614/190932053-f3228df0-d264-4427-a17b-bce43f130fa7.gif',
                      'https://github.com/yama-yeah/flutter_anchorlable',
                    ),
                  ],
                ),
              ],
            ),
          ),
          const SizedBox(height: 60),
          Footer(),
        ],
      ),
    );
  }
}

final anchorlableBodyController = AnchorlableController();
const introKey = GlobalObjectKey('intro');
const worksKey = GlobalObjectKey('works');
const contactKey = GlobalObjectKey('contact');

更多关于Flutter锚点定位插件flutter_anchorlable的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter锚点定位插件flutter_anchorlable的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何使用 flutter_anchorable 插件在 Flutter 中实现锚点定位的示例代码。这个插件允许你在滚动视图中定位到特定的锚点。

首先,确保你已经在 pubspec.yaml 文件中添加了 flutter_anchorable 依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_anchorable: ^x.y.z  # 请替换为最新版本号

然后,运行 flutter pub get 来获取依赖。

以下是一个简单的示例,展示如何使用 flutter_anchorable 插件:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Anchorable Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Anchorable Demo'),
        ),
        body: AnchorableListViewDemo(),
      ),
    );
  }
}

class AnchorableListViewDemo extends StatefulWidget {
  @override
  _AnchorableListViewDemoState createState() => _AnchorableListViewDemoState();
}

class _AnchorableListViewDemoState extends State<AnchorableListViewDemo> {
  final List<String> items = List.generate(100, (index) => "Item $index");
  AnchorableController? _anchorableController;

  @override
  void initState() {
    super.initState();
    _anchorableController = AnchorableController();
    // 自动滚动到第50项
    Future.delayed(Duration.zero, () {
      _anchorableController?.scrollToAnchor("item-50");
    });
  }

  @override
  void dispose() {
    _anchorableController?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: AnchorableListView(
        controller: _anchorableController,
        children: List.generate(items.length, (index) {
          return Anchorable(
            key: ValueKey("item-$index"),
            anchorId: "item-$index",
            child: ListTile(
              title: Text(items[index]),
            ),
          );
        }),
      ),
    );
  }
}

代码解释:

  1. 依赖添加:确保在 pubspec.yaml 中添加了 flutter_anchorable 依赖。

  2. AnchorableListViewDemo:创建了一个包含 100 个项目的列表视图。

  3. AnchorableController:初始化 AnchorableController 来控制锚点滚动。

  4. Auto Scroll:在 initState 中,使用 Future.delayed(Duration.zero, ...) 来立即(在下一个事件循环中)滚动到第 50 项。这模拟了页面加载后自动滚动到特定位置的效果。

  5. AnchorableListView:使用 AnchorableListView 包装列表,并通过 Anchorable 包装每个列表项,设置唯一的 anchorId

  6. 滚动到锚点:通过 _anchorableController?.scrollToAnchor("item-50") 方法滚动到指定的锚点。

注意事项:

  • 确保每个 AnchorableanchorId 是唯一的。
  • 可以在用户交互(如按钮点击)时调用 scrollToAnchor 方法来实现动态滚动。

这个示例展示了如何使用 flutter_anchorable 插件在 Flutter 应用中实现锚点定位功能。你可以根据需要进一步定制和扩展这个示例。

回到顶部