Flutter 所有路由的通用背景图

Mic*_*ael 0 flutter

我正在尝试添加背景图像,无论哪条路线处于活动状态,该背景图像始终存在。我下面的示例受到这个答案的启发,但背景仅对路线“/”可见。我希望不必为每条路线设置背景图像。有什么建议么?

Widget build(BuildContext context) {
  return MaterialApp(
    title: 'Flutter Demo',
    home: const BoxDecoration(
      image: DecorationImage(
          image: AssetImage("assets/images/camping-background.png"),
          fit: BoxFit.cover),
    ),
    routes: <String, WidgetBuilder>{
      '/login': (BuildContext context) => const Login(),
      '/register': (BuildContext context) => const Register(),
      '/home': (BuildContext context) => const Home(),
    },
  );
}
Run Code Online (Sandbox Code Playgroud)

gei*_*aos 5

更新的答案

为了获得背景图像,您可以简单地将 MaterialApp 包装在 DecoratedBox 中。这比其他方法(下面进一步概述)更可取,因为这种滥用builder是为了其他目的:

用于在导航器上方插入小部件的构建器,或者(当使用 WidgetsApp.router 构造函数时)在路由器上方但在 WidgetsApp 小部件创建的其他小部件下方,或者用于完全替换导航器/路由器。

由于MaterialApp仅配置非渲染小部件并且DecoratedBox不依赖于它们中的任何一个,因此它可以简单地充当应用程序其余部分的父小部件以实现所需的效果。

import 'package:flutter/material.dart';

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

class Example extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DecoratedBox(
      decoration:  const BoxDecoration(
          image: DecorationImage(
            image: NetworkImage("https://flutter.github.io/assets-for-api-docs/assets/widgets/owl-2.jpg"),
            fit: BoxFit.cover,
          ),
        ),
      child: MaterialApp(
        title: 'Flutter Demo',
        initialRoute: '/login',
        routes: <String, WidgetBuilder>{
          '/login': (BuildContext context) => Login(),
          '/home': (BuildContext context) => Home(),
        },
      ),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const Text('Home'),
        ElevatedButton(onPressed: () => Navigator.of(context).pop(), child: const Text('Go back')),
      ]
    );
  }
}

class Login extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const Text('Login'),
        ElevatedButton(onPressed: () => Navigator.of(context).pushNamed('/home'), child: const Text('Login')),
      ]
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

之前的回答

您可以使用builderon 字段MaterialApp提供一个 TransitionBuilder 函数,该函数为所有路由定义一个公共包装器:

import 'package:flutter/material.dart';

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

class Example extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      builder: (context, child) => DecoratedBox(
        decoration: const BoxDecoration(
          image: DecorationImage(
            image: NetworkImage("https://flutter.github.io/assets-for-api-docs/assets/widgets/owl-2.jpg"),
            fit: BoxFit.cover,
          ),
        ),
        child: child,
      ),
      initialRoute: '/login',
      routes: <String, WidgetBuilder>{
        '/login': (BuildContext context) => Login(),
        '/home': (BuildContext context) => Home(),
      },
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const Text('Home'),
        ElevatedButton(onPressed: () => Navigator.of(context).pop(), child: const Text('Go back')),
      ]
    );
  }
}

class Login extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const Text('Login'),
        ElevatedButton(onPressed: () => Navigator.of(context).pushNamed('/home'), child: const Text('Login')),
      ]
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

它采用BuildContext当前渲染的路线作为child参数,并返回一个小部件,然后将其显示为路线。


home另外,由于and的使用似乎存在一些混乱routes,这里是文档的摘录MaterialApp

  1. 对于 / 路由,使用 home 属性(如果非空)。
  2. 否则,如果路由表有路由条目,则使用路由表。
  3. 否则,将调用 onGenerateRoute(如果提供)。对于 home 和 paths 未处理的任何有效路由,它应该返回一个非空值。
  4. 最后,如果所有其他方法都失败,则调用 onUnknownRoute 。

虽然您可以home将和一起使用,但我个人认为,除了指示哪个是第一个(除非确实是默认值)之外routes,仅使用路由会更清楚地了解发生了什么。routesinitialRoute/