Flutter页面拖拽路由插件draggable_route的使用

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

Flutter页面拖拽路由插件draggable_route的使用

draggable_route 是一个非常方便的Flutter插件,它提供了可拖拽的路由动画,类似于Instagram中的路由切换效果。本文将详细介绍如何使用该插件,并提供完整的示例代码。

功能特性

  • 从源小部件展开打开页面
  • 关闭时返回到源小部件并带有动画效果
  • 支持通过拖拽关闭页面
  • 如果没有源小部件,则页面会消失

开始使用

首先,需要在项目的 pubspec.yaml 文件中添加 draggable_route 依赖:

dart pub add draggable_route

使用方法

不带源小部件的路由

在这种情况下,页面将以自适应方式打开。当用户返回时,页面会以动画形式消失。同时支持通过拖拽来关闭页面。

Navigator.of(context).push(
  DraggableRoute(
    builder: (context) => const Page(),
  ),
);

带源小部件的路由

在这种情况下,页面会从小部件源点展开,并在关闭时收缩回源小部件。注意:提供的上下文不应包含 GlobalKey 的子元素,因为源小部件会在穿梭动画期间被重新创建。

Navigator.of(context).push(
  DraggableRoute(
    source: context,
    builder: (context) => const Page(),
  ),
);

示例代码

下面是一个完整的示例,展示了如何使用 draggable_route 插件实现不同类型的页面切换效果。

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

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

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: SizedBox(
          width: double.infinity,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Builder(
                builder: (context) {
                  return GestureDetector(
                    onTap: () => Navigator.of(context).push(
                      DraggableRoute(
                        source: context,
                        builder: (context) => const PageB(),
                      ),
                    ),
                    child: const SizedBox(
                      width: 300,
                      height: 200,
                      child: Card(
                        child: Center(child: Text('Open with Source')),
                      ),
                    ),
                  );
                },
              ),
              Builder(builder: (context) {
                return GestureDetector(
                  onTap: () => Navigator.of(context).push(
                    DraggableRoute(
                      builder: (context) => const PageB(),
                    ),
                  ),
                  child: const SizedBox(
                    width: 300,
                    height: 200,
                    child: Card(
                      child: Center(child: Text('Open without Source')),
                    ),
                  ),
                );
              }),
              Builder(
                builder: (context) {
                  return GestureDetector(
                    onTap: () => Navigator.of(context).push(
                      DraggableRoute(
                        source: context,
                        builder: (context) => const ScrollablePage(),
                      ),
                    ),
                    child: const SizedBox(
                      width: 300,
                      height: 200,
                      child: Card(
                        child: Center(child: Text('Open Scrollable')),
                      ),
                    ),
                  );
                },
              ),
              Builder(
                builder: (context) {
                  return GestureDetector(
                    onTap: () => Navigator.of(context).push(
                      DraggableRoute(
                        builder: (context) => const ScrollablePage(),
                      ),
                    ),
                    child: const SizedBox(
                      width: 300,
                      height: 200,
                      child: Card(
                        child: Center(
                          child: Text('Open Scrollable without Source'),
                        ),
                      ),
                    ),
                  );
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.green.shade100,
      body: SizedBox(
        width: double.infinity,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () => Navigator.pop(context),
              child: const Text("Return"),
            ),
            const SizedBox(height: 24),
          ],
        ),
      ),
    );
  }
}

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.green.shade100,
      body: SafeArea(
        child: SizedBox(
          width: double.infinity,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: () => Navigator.pop(context),
                child: const Text("Return"),
              ),
              const SizedBox(height: 24),
              Expanded(
                child: ListView.builder(
                  itemCount: 100,
                  clipBehavior: Clip.none,
                  itemBuilder: (context, index) {
                    if (index % 3 == 0) {
                      return SizedBox(
                        height: 120,
                        width: MediaQuery.of(context).size.width,
                        child: ListView.builder(
                          itemCount: 100,
                          clipBehavior: Clip.none,
                          scrollDirection: Axis.horizontal,
                          itemBuilder: (context, index) => ColoredBox(
                            color: Colors.yellow,
                            child: SizedBox(
                              height: 120,
                              width: 60,
                              child: Center(child: Text(index.toString())),
                            ),
                          ),
                        ),
                      );
                    }

                    return ColoredBox(
                      color: Colors.purple,
                      child: ListTile(
                        title: Text(index.toString()),
                      ),
                    );
                  },
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

更多关于Flutter页面拖拽路由插件draggable_route的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter页面拖拽路由插件draggable_route的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用draggable_route插件来实现页面拖拽路由的一个简单示例。draggable_route插件允许你通过拖拽动作在Flutter应用中导航页面。

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

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

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

接下来,我们创建一个简单的Flutter应用,展示如何使用draggable_route插件。

主应用文件 (main.dart)

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      onGenerateRoute: _generateRoute,
      initialRoute: '/',
    );
  }

  Route<dynamic> _generateRoute(RouteSettings settings) {
    switch (settings.name) {
      case '/':
        return _createDraggableRoute(
          builder: (_) => HomePage(),
          settings: settings,
        );
      case '/second':
        return _createDraggableRoute(
          builder: (_) => SecondPage(),
          settings: settings,
        );
      default:
        return MaterialPageRoute(builder: (_) => Scaffold(body: Center(child: Text('404'))));
    }
  }

  DraggablePageRoute<dynamic> _createDraggableRoute({
    required RouteSettings settings,
    required WidgetBuilder builder,
  }) {
    return DraggablePageRoute<dynamic>(
      settings: settings,
      builder: builder,
      barrierDismissible: true,
      fullscreenDialog: false,
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home Page'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pushNamed(context, '/second');
          },
          child: Text('Go to Second Page'),
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Second Page'),
      ),
      body: Center(
        child: Text('You can drag this page down to go back!'),
      ),
    );
  }
}

解释

  1. 依赖管理

    • pubspec.yaml文件中添加draggable_route依赖。
  2. 路由管理

    • 使用MaterialApponGenerateRoute属性来管理路由。
    • _generateRoute方法根据路由名称生成相应的页面路由。
  3. 创建可拖拽路由

    • _createDraggableRoute方法封装了DraggablePageRoute的创建,这样可以在不同地方重用。
    • DraggablePageRoute用于创建可拖拽的页面路由。
  4. 页面内容

    • HomePage包含一个按钮,点击按钮时会导航到SecondPage
    • SecondPage显示一个文本,提示用户可以通过拖拽返回。

通过上述代码,你就可以在Flutter应用中实现页面拖拽路由的功能。当用户从屏幕底部向上拖动SecondPage时,页面将返回至HomePage

回到顶部