所有航路的Flutter通用背景图像

z9smfwbn  于 2022-11-26  发布在  Flutter
关注(0)|答案(2)|浏览(139)

我正在尝试添加一个背景图片,无论哪个路线处于活动状态,该图片都将始终存在。下面的示例是受this answer启发的,但只有路线“/"的背景才可见。我希望不必为每个路线设置背景图片。有什么建议吗?

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(),
    },
  );
}
gdx19jrr

gdx19jrr1#

更新的答案

为了获得背景图像,你可以简单地将MaterialApp Package 在DecoratedBox中。这比其他方法更可取(下面将进一步介绍),因为这会滥用builder,而builder是用于其他目的的:
一个构建器,用于在导航器上方插入小部件,或在路由器上方但在由WidgetsApp小部件创建的其他小部件下方插入小部件(当使用WidgetsApp.router构造器时),或用于完全替换导航器/路由器。
由于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')),
      ]
    );
  }
}

上一个答案

您可以使用MaterialApp上的builder字段来提供TransitionBuilder函数,该函数为所有路由定义通用 Package :

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')),
      ]
    );
  }
}

它将BuildContext以及当前渲染的路线child作为参数,并返回一个Widget,然后将其显示为路线。
此外,由于homeroutes的用法似乎有些混乱,因此以下是MaterialApp文档的片段:
1.对于/ route,如果非null,则使用home属性。
1.否则,如果路由表中有路由条目,则使用路由表。
1.否则,调用onGenerateRoute(如果提供)。它应为Home和routes未处理的任何有效路由返回非空值。
1.最后,如果所有其他操作都失败,则调用onUnknownRoute。
虽然你 * 可以 * 一起使用homeroutes,但我个人认为,除了initialRoute之外,只使用routes来指示哪个是第一个(除非它确实是默认的/)的路由会更清楚。

bis0qfac

bis0qfac2#

将其复制并粘贴到dartpad上以查看结果

import 'package:flutter/material.dart';

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

class BaseLayout extends StatelessWidget {
  final Widget? child;

  const BaseLayout({Key? key, @required this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 720,
      decoration: const BoxDecoration(
        image: DecorationImage(
            image: NetworkImage(
                "https://images.pexels.com/photos/440731/pexels-photo-440731.jpeg"),
            fit: BoxFit.fill),
      ),
      child: child,
    );
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Home')),
        body: BaseLayout(child: Home()),
      ),
      routes: <String, WidgetBuilder>{
        '/login': (BuildContext context) => Login(),
        '/register': (BuildContext context) => Register(),
        '/home': (BuildContext context) => Home(),
      },
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const Text('HOMEPAGE', style: TextStyle(fontSize: 32)),
        const SizedBox(height: 12),
        ElevatedButton(
          child: const Text('Login'),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => Scaffold(
                    appBar: AppBar(title: const Text('Login')),
                    body: BaseLayout(child: Login())),
              ),
            );
          },
        ),
        const SizedBox(height: 12),
        ElevatedButton(
          child: const Text('Register'),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                  builder: (context) => BaseLayout(child: Register())),
            );
          },
        ),
        const SizedBox(height: 12),
        ElevatedButton(
          child: const Text('No Background Image Screen'),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => NoBackground()),
            );
          },
        ),
      ],
    );
  }
}

class Login extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text(
          'Login',
          style: Theme.of(context).textTheme.headline4,
        ),
        const SizedBox(height: 12),
        ElevatedButton(
          child: const Text('Back to Homepage'),
          onPressed: () {
            Navigator.pop(context);
          },
        ),
      ],
    );
  }
}

class Register extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text(
          'Register!',
          style: Theme.of(context).textTheme.headline4,
        ),
        const SizedBox(height: 12),
        ElevatedButton(
          child: const Text('Back to Homepage'),
          onPressed: () {
            Navigator.pop(context);
          },
        ),
      ],
    );
  }
}

class NoBackground extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const Text(
          'No Background Image!',
          style: TextStyle(color: Colors.white),
        ),
        const SizedBox(height: 12),
        ElevatedButton(
          child: const Text('Back to Homepage'),
          onPressed: () {
            Navigator.pop(context);
          },
        ),
      ],
    );
  }
}

使用scaffold应用程序栏完成,无背景图像示例

**检查要点:**完整代码here

相关问题