Flutter应用入口插件entry的使用

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

Flutter应用入口插件entry的使用

插件简介

entry

Entry

Pub Package Platform

CodeFactor CodeFactor

Entry 是一个用于简化Flutter中Widget动画显示的包。它允许你轻松地让组件以动画的形式出现或消失,而不仅仅是简单地显示。

构造函数

默认构造函数

Entry({key, delay, duration, curve, visible, opacity, scale, xOffset, yOffset, angle, child})

默认情况下,这个构造函数是静止不动的。它包括所有命名构造函数可用的所有参数。

命名构造函数

Entry 提供了四个命名构造函数:

  1. Entry.all({visible, opacity, scale, xOffset, yOffset, angle})
    • .all 使用除了anglexOffset之外的所有动画。
  2. Entry.opacity({opacity})
  3. Entry.scale({scale})
  4. Entry.offset({xOffset, yOffset})

注意:key, delay, duration, curve, visiblechild 参数在上面省略了。

组合使用

你可以将一个Entry包裹在另一个Entry中,通过调整参数可以创造出无限可能的效果。

组合效果示例

entry

网格构建器

固定交叉轴数量

使用Entry与网格构建器结合可以创建交错效果:

  • 包裹生成的子组件为Entry widget
  • delay值乘以index % crossAxisCount

这样,同一行的组件会依次出现。

交错效果示例

entry

随机化

你可以设置delay和/或duration为随机数,使动画看起来更加独立。

delay: Duration(milliseconds: random.nextInt(300))
随机化效果示例

entry

示例代码

下面是一个完整的示例代码,展示了如何使用entry插件的不同功能:

import 'dart:math';

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

void main() => runApp(ExampleApp());

/// Custom card used for every example
class CustomCard extends StatelessWidget {
  const CustomCard(this.label, {Key? key}) : super(key: key);
  final String label;
  @override
  Widget build(BuildContext context) {
    return Card(
      child: Container(
        color: Colors.grey[300],
        width: 128,
        height: 128,
        child: Center(
          child: Text(
            label,
            style: const TextStyle(fontSize: 16),
          ),
        ),
      ),
    );
  }
}

/// Example app widget
class ExampleApp extends StatefulWidget {
  const ExampleApp({Key? key}) : super(key: key);

  @override
  State<ExampleApp> createState() => _ExampleAppState();
}

class _ExampleAppState extends State<ExampleApp> {
  /// List of the tabs titles
  final tabs = [
    "Constructors",
    "Entry combinations",
    "Staggered builds",
    "Randomization"
  ];

  /// Random instance
  final random = Random();

  var visible = true;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: SafeArea(
        child: DefaultTabController(
          length: tabs.length,
          child: Scaffold(
            backgroundColor: Colors.white,
            appBar: TabBar(
              isScrollable: true,
              tabs: [
                for (var tab in tabs)
                  Padding(
                    padding: const EdgeInsets.all(8),
                    child: Text(
                      tab,
                      style: const TextStyle(color: Colors.black),
                    ),
                  ),
              ],
            ),
            body: TabBarView(
              children: [
                // Constructors
                Column(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    Wrap(
                      alignment: WrapAlignment.center,
                      runAlignment: WrapAlignment.center,
                      children: [
                        Entry.all(
                          visible: visible,
                          duration: const Duration(seconds: 1),
                          child: const CustomCard("Entry.all()"),
                        ),
                        Entry.opacity(
                          visible: visible,
                          duration: const Duration(seconds: 1),
                          child: const CustomCard("Entry.opacity()"),
                        ),
                        Entry.scale(
                          visible: visible,
                          duration: const Duration(seconds: 1),
                          child: const CustomCard("Entry.scale()"),
                        ),
                        Entry.offset(
                          visible: visible,
                          duration: const Duration(seconds: 1),
                          child: const CustomCard("Entry.offset()"),
                        ),
                      ],
                    ),
                    Center(
                        child: ElevatedButton(
                      onPressed: () => setState(() => visible = !visible),
                      child: Text("visible : $visible"),
                    )),
                  ],
                ),
                // Entry combinations
                Center(
                  child: Wrap(
                    children: [
                      // Example 1
                      Entry(
                        xOffset: -1000,
                        scale: 20,
                        delay: const Duration(milliseconds: 300),
                        duration: const Duration(milliseconds: 700),
                        curve: Curves.ease,
                        child: Entry(
                          opacity: .5,
                          angle: 3.1415,
                          scale: .5,
                          delay: const Duration(milliseconds: 900),
                          duration: const Duration(milliseconds: 500),
                          curve: Curves.decelerate,
                          child: const CustomCard("Example 1"),
                        ),
                      ),
                      // Example 2
                      Entry(
                        delay: const Duration(milliseconds: 300),
                        duration: const Duration(milliseconds: 300),
                        opacity: 0,
                        yOffset: -1000,
                        curve: Curves.easeInOutCubic,
                        child: Entry(
                          delay: const Duration(milliseconds: 450),
                          duration: const Duration(milliseconds: 600),
                          curve: Curves.decelerate,
                          scale: 0.5,
                          angle: 1.5707,
                          child: const CustomCard("Example 2"),
                        ),
                      ),
                      // Example 3
                      Entry(
                        delay: const Duration(milliseconds: 300),
                        duration: const Duration(milliseconds: 700),
                        yOffset: 1000,
                        xOffset: 1000,
                        angle: -4.1415,
                        curve: Curves.fastOutSlowIn,
                        child: Entry(
                          delay: const Duration(milliseconds: 1000),
                          duration: const Duration(milliseconds: 250),
                          curve: Curves.easeOut,
                          opacity: 0.5,
                          scale: 0.5,
                          child: const CustomCard("Example 3"),
                        ),
                      ),
                    ],
                  ),
                ),

                // Staggered builds
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 16.0),
                  child: GridView.builder(
                    itemCount: 100,
                    gridDelegate:
                        const SliverGridDelegateWithFixedCrossAxisCount(
                      crossAxisCount: 3,
                    ),
                    itemBuilder: (context, index) => Entry.all(
                      delay: Duration(milliseconds: (200 * (index % 3))),
                      child: CustomCard("Card n°$index"),
                    ),
                  ),
                ),
                // Randomization
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 16.0),
                  child: GridView.builder(
                    itemCount: 100,
                    gridDelegate:
                        const SliverGridDelegateWithFixedCrossAxisCount(
                      crossAxisCount: 3,
                    ),
                    itemBuilder: (context, index) => Entry.all(
                      delay: Duration(milliseconds: random.nextInt(300)),
                      child: CustomCard("Card n°$index"),
                    ),
                  ),
                ),
              ],
            ),
            floatingActionButton: Builder(
              builder: (context) {
                return FloatingActionButton(
                  child: const Icon(Icons.refresh),
                  onPressed: () async {
                    // Re-initializes the whole page to show the animations again
                    Navigator.of(context).pop();
                    Navigator.push(
                      context,
                      PageRouteBuilder(
                        pageBuilder: (_, __, ___) => const ExampleApp(),
                        transitionDuration: Duration.zero,
                      ),
                    );
                  },
                );
              },
            ),
          ),
        ),
      ),
    );
  }
}

以上代码展示了如何使用entry插件的各种功能,包括不同的构造函数、组合动画、交错布局以及随机化效果。希望这能帮助你在Flutter项目中更好地利用动画来提升用户体验。


更多关于Flutter应用入口插件entry的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter应用入口插件entry的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter应用中,entry 插件通常用于定义应用的入口点,尤其是在处理多入口场景时非常有用。虽然Flutter本身并没有一个官方名为 entry 的插件,但我们可以理解为如何在Flutter中配置和管理多个入口点。

在Flutter中,你可以通过配置 android/app/src/main/AndroidManifest.xmlios/Runner/Info.plist 文件,以及使用 flutter_native_splash 等第三方库来设置应用的启动画面和入口。不过,对于多入口点的实现,通常是通过路由管理来实现的,比如使用 flutter_navigatorflutter_deep_linking 等库。

下面是一个使用 flutter_navigator 库来管理多入口点的示例代码:

  1. 添加依赖: 在你的 pubspec.yaml 文件中添加 flutter_navigator 依赖:

    dependencies:
      flutter:
        sdk: flutter
      flutter_navigator: ^x.y.z  # 替换为最新版本号
    
  2. 配置路由: 创建一个路由配置文件,比如 routes.dart,来定义你的路由和入口点:

    import 'package:flutter/material.dart';
    import 'package:flutter_navigator/flutter_navigator.dart';
    import 'your_first_screen.dart';
    import 'your_second_screen.dart';
    
    Map<String, WidgetBuilder> getRoutes() {
      return {
        '/': (context) => YourFirstScreen(),
        '/second': (context) => YourSecondScreen(),
      };
    }
    
    void configureRoutes(NavigatorState navigator) {
      FlutterNavigator.instance
        .setRoutes(getRoutes())
        .setInitialRoute('/');
    }
    
  3. main.dart 中使用路由

    import 'package:flutter/material.dart';
    import 'routes.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      [@override](/user/override)
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Multi Entry Example',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          navigatorKey: FlutterNavigator.navigatorKey,  // 使用FlutterNavigator的navigatorKey
          onGenerateRoute: (settings) {
            final routeName = settings.name ?? '/';
            final route = FlutterNavigator.instance.getRoute(routeName);
            return MaterialPageRoute(builder: route, settings: settings);
          },
          initialRoute: '/',
        );
      }
    }
    
    [@override](/user/override)
    void initState() {
      super.initState();
      WidgetsBinding.instance.addPostFrameCallback((_) => configureRoutes(FlutterNavigator.navigator!));
    }
    

    注意:在上面的代码中,WidgetsBinding.instance.addPostFrameCallback 用于在应用框架构建完成后配置路由,确保 Navigator 已经初始化。

  4. 启动应用: 现在,你可以通过URL来启动不同的入口点。例如,在Android上,你可以通过Intent来启动特定的路由:

    Intent intent = FlutterActivity
        .withCachedEngine("my_engine_id")
        .build(context)
        .putExtra("flutter_entrypoint", "/second");
    startActivity(intent);
    

    在iOS上,你可以通过URL Scheme来启动特定的路由:

    let url = URL(string: "yourappscheme://second")!
    UIApplication.shared.open(url, options: [:], completionHandler: nil)
    

    注意:上述iOS代码示例假设你已经配置了URL Scheme,并且你的Flutter应用能够处理这些URL。

通过这种方式,你可以实现Flutter应用中的多入口点管理。虽然没有一个名为 entry 的官方插件,但你可以使用路由管理库来实现类似的功能。

回到顶部