Flutter - UIKit开发相关指南 - 导航

导航

两个页面之间切换

UIKit中,使用UINavigationController来管理视图。Flutter中通过NavigatorRoutes来实现相似的功能。

一个Route是一个应用中屏幕或页的抽象,Navigator是一个Widget来管理这些RoutesRoute可以粗略的认为是一个UIViewControllerNavigator类似iOS中的UINavigationController,可以pushpopRoutes。

切页面有两种方法

  • 指定一个路由的映射表
  • 直接导航到一个Route
指定路由表 - pushName
dart 复制代码
import 'package:flutter/material.dart';
import 'package:navigation/second_route.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "导航示例",
      home: Builder(
        builder:
            (context) => Scaffold(
              appBar: AppBar(title: Text("导航")),
              body: Center(
                child: ElevatedButton(
                  onPressed: () {
                    // 2. 跳转到SecondRoute
                    Navigator.of(context).pushNamed('/second');
                  },
                  child: const Text("到第二个页面"),
                ),
              ),
            ),
      ),
      // 1.建立映射表 "/second"指向SecondRoute()
      routes: {'/second': (context) => const SecondRoute()},
    );
  }
}
dart 复制代码
import "package:flutter/cupertino.dart";
import "package:flutter/material.dart";

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

  @override
  // 3. 显示
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("第二个路由页面")),
      body: Center(
        child: CupertinoButton(
          onPressed: () {
            // 4.点击返回
            Navigator.pop(context);
          },
          child: const Text("返回"),
        ),
      ),
    );
  }
}
返回 - pop

Flutter中使用如下代码实现pop功能

dart 复制代码
# 或 Navigator.pop()
SystemNavigator.pop()

在iOS上约等于如下的实现

objc 复制代码
UIViewController* viewController = [UIApplication sharedApplication].keyWindow.rootViewController;
if ([viewController isKindOfClass:[UINavigationController class]]) {
  [((UINavigationController*)viewController) popViewControllerAnimated:NO];
}
指定路由表 - push

在push方法中直接用builder跳转,而不需要通过路由表

dart 复制代码
import 'package:flutter/material.dart';
import 'package:navigation/second_route.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "导航示例",
      home: Builder(
        builder:
            (context) => Scaffold(
              appBar: AppBar(title: Text("导航")),
              body: Center(
                child: ElevatedButton(
                  onPressed: () {
                    // 点击直接指定跳转的界面
                    Navigator.of(context).push(
                      MaterialPageRoute(
                        builder: (context) => const SecondRoute(),
                      ),
                    );
                  },
                  child: const Text("到另一个页面"),
                ),
              ),
            ),
      ),
    );
  }
}
指定路由表 - go_router

go_router是一个用于Flutter声明式的路由包,使用Router API为不同屏幕间进行切换

sh 复制代码
$ flutter pub add go_router

会在pubspec.yaml文件中添加go_router依赖包,并下载

dart 复制代码
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:navigation/second_route.dart';

void main() {
  runApp(MaterialApp.router(title: '导航', routerConfig: _router));
}

// 1.定义路由信息
final _router = GoRouter(
  routes: [
    GoRoute(path: '/', builder: (context, state) => const FirstScreen()),
    GoRoute(path: '/second', builder: (context, state) => const SecondRoute()),
  ],
);

class FirstScreen extends StatelessWidget {
  const FirstScreen({super.key});
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('第一个界面')),
      body: Center(
        child: ElevatedButton(
          child: const Text('使用go_router跳转'),
          // 2.指定跳转界面
          onPressed: () => context.go('/second'),
        ),
      ),
    );
  }
}
dart 复制代码
import "package:flutter/cupertino.dart";
import "package:flutter/material.dart";
import "package:go_router/go_router.dart";

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("第二个路由页面")),
      body: Center(
        child: CupertinoButton(
          onPressed: () {
            // 3. 点击返回根目录
            context.go('/');
          },
          child: const Text("返回"),
        ),
      ),
    );
  }
}

导航到其它应用

在UIKit中使用URL scheme来实现。Flutter可以使用类似 url_launcher 的插件来实现。

Android iOS Linux macOS Web Windows
支持 SDK 16+ 12.0+ Any 10.14+ Any Window 10+
sh 复制代码
$ flutter pub add url_launcher
加载Web界面
dart 复制代码
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';

final Uri _url = Uri.parse('https://flutter.cn');

void main() => runApp(
      const MaterialApp(
        home: Material(
          child: Center(
            child: ElevatedButton(
              onPressed: _launchUrl,
              child: Text('Show Flutter homepage'),
            ),
          ),
        ),
      ),
    );

Future<void> _launchUrl() async {
  if (!await launchUrl(_url)) {
    throw Exception('Could not launch $_url');
  }
}
加载其它应用

Info.plist添加允许打开短信和电话的配置

plist 复制代码
<key>LSApplicationQueriesSchemes</key>
<array>
  <string>sms</string>
  <string>tel</string>
</array>
dart 复制代码
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';

final Uri _url = Uri.parse('tel://10000');

void main() => runApp(
  const MaterialApp(
    home: Material(
      child: Center(
        child: ElevatedButton(
          // 1. 绑定对应方法
          onPressed: _launchUrl,
          child: Text('Show Flutter homepage'),
        ),
      ),
    ),
  ),
);

Future<void> _launchUrl() async {
  // 2. 确认是否能打开对应url,已添加到plist文件
  if (await canLaunchUrl(_url)) {
    if (!await launchUrl(_url)) {
      throw Exception('Could not launch $_url');
    }
  }
}

参考

  1. 给 UIKit 开发者的 Flutter 指南
  2. url_launcher
相关推荐
代码s贝多芬的音符14 小时前
ios android 小程序 蓝牙 CRC16_MODBUS
android·ios·小程序
非专业程序员Ping15 小时前
从0到1自定义文字排版引擎:原理篇
ios·swift·assembly·font
2501_9159090615 小时前
“绑定 HTTPS” 的工程全流程 从证书配置到真机验证与故障排查
网络协议·http·ios·小程序·https·uni-app·iphone
2501_9159184116 小时前
iOS 混淆实战 多工具组合完成 IPA 混淆、加固与工程化落地(iOS混淆|IPA加固|无源码混淆|Ipa Guard|Swift Shield)
android·ios·小程序·https·uni-app·iphone·webview
—Qeyser17 小时前
使用 Flutter 的 Positioned 控件实现精准布局
flutter
游戏开发爱好者818 小时前
如何系统化掌握 iOS 26 App 耗电管理,多工具协作
android·macos·ios·小程序·uni-app·cocoa·iphone
weixin_4046113420 小时前
鸿蒙flutter 老项目到新项目的遇到迁移坑点
flutter·华为·harmonyos
2501_9159214320 小时前
运营日志驱动,在 iOS 26 上掌握 App 日志管理实践
android·macos·ios·小程序·uni-app·cocoa·iphone
cding20 小时前
Flutter 开发环境搭建
android·flutter
马拉萨的春天21 小时前
iOS的多线程下数据安全和内存泄漏以及工具使用监测内存泄漏
macos·ios·cocoa·多线程