【问题标题】:Flutter: How do I reset navigation stack on a Flutter engine?Flutter:如何重置 Flutter 引擎上的导航堆栈?
【发布时间】:2023-02-14 19:48:32
【问题描述】:

我正在尝试将 Flutter 模块添加到本机 iOS 应用程序。但是,我遇到了一个问题,即在多次呈现 FlutterViewController 时维护 Flutter 的导航堆栈(即显示详细信息屏幕而不是登录页面)。

使用 Flutter 引擎时如何重置导航堆栈?

这是我的演示代码。

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      initialRoute: 'example',
      routes: {
        'example': (context) => const LandingPage(),
      },
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Landing screen')),
      body: Center(
        child: TextButton(
          child: const Text('Go to details'),
          onPressed: () => _navigateToDetails(context),
        ),
      ),
    );
  }

  void _navigateToDetails(BuildContext context) {
    Navigator.of(context).push(
      MaterialPageRoute(builder: (context) => const DetailsPage()),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Details screen')),
      body: const Center(child: Text('Details')),
    );
  }
}

这是我的原生 Swift 代码。

@main
class AppDelegate: FlutterAppDelegate {
    
    lazy var sharedEngine = FlutterEngine(name: "shared")

    override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        sharedEngine.run();
        GeneratedPluginRegistrant.register(with: sharedEngine);
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}

class ViewController: UIViewController {

    @IBAction private func onButtonTapped(_ sender: UIButton) {
        let page = FlutterViewController(
            engine: AppDelegate.current.sharedEngine,
            nibName: nil,
            bundle: nil
        )
        present(page, animated: true)
    }
}

【问题讨论】:

    标签: swift flutter flutter-add-to-app


    【解决方案1】:

    我最终通过手动关闭模态解决了这个问题。

    只有在 iOS 上运行时,我才向 AppBar 添加了一个关闭按钮,它会调用 MethodChannel 上的方法。我创建了一个自定义 ViewController,它将监听对 dismiss_modal 的调用。关键是通过将modalPresentationStyle 设置为.overCurrentContext 来呈现此模态。

    class LandingPage extends StatelessWidget {
    
      static const platform = MethodChannel('dev.example/native_channel');
      
      const LandingPage({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('Landing screen'),
            leading: _closeButton,
          ),
          body: Center(
            child: TextButton(
              child: const Text('Go to details'),
              onPressed: () => _navigateToDetails(context),
            ),
          ),
        );
      }
    
      Widget? get _closeButton {
        if (defaultTargetPlatform != TargetPlatform.iOS) {
          return null;
        }
        return IconButton(
          icon: const Icon(Icons.close),
          onPressed: () => _dismissModal(),
        );
      }
    
      void _dismissModal() async {
        try {
          await platform.invokeMethod('dismiss_modal');
        } on PlatformException {
          return;
        }
      }
    
      void _navigateToDetails(BuildContext context) {
        Navigator.of(context).push(
          MaterialPageRoute(builder: (context) => const DetailsPage()),
        );
      }
    }
    
    class CustomFlutterViewController: FlutterViewController {
    
        private lazy var methodChannel = FlutterMethodChannel(
            name: "dev.example/native_channel",
            binaryMessenger: binaryMessenger
        )
    
        override func viewDidLoad() {
            super.viewDidLoad()
            methodChannel.setMethodCallHandler { [weak self] methodCall, result in
                switch methodCall.method {
                case "dismiss_modal":
                    self?.dismiss(animated: true)
                    result(nil)
                default:
                    result(FlutterMethodNotImplemented)
                }
            }
        }
    }
    
    class ViewController: UIViewController {
    
        @IBAction private func onButtonTapped(_ sender: UIButton) {
            let viewController = CustomFlutterViewController(
                engine: AppDelegate.current.sharedEngine,
                nibName: nil,
                bundle: nil
            )
            viewController.modalPresentationStyle = .overCurrentContext
            present(viewController, animated: true)
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-04-26
      • 1970-01-01
      • 1970-01-01
      • 2020-11-06
      • 2019-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-30
      相关资源
      最近更新 更多