如何在Flutter中将图片资源设置为屏幕背景?
解决Flutter登录页面矢量图背景显示问题
我想把一张矢量图设为Flutter登录页面的屏幕背景,但直接把Image.asset加到Column的children里时,图片会显示在页面交互元素的上方。现有代码、当前效果和期望效果如下:
import 'package:ehatid_driver_app/signup.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'Welcome/components/body.dart'; class LoginScreen extends StatefulWidget { const LoginScreen({ Key? key, }) : super(key: key); @override State<LoginScreen> createState() => _LoginScreenState(); } class _LoginScreenState extends State<LoginScreen> { //text controller final _emailController = TextEditingController(); final _passwordController = TextEditingController(); Future signIn() async { await FirebaseAuth.instance.signInWithEmailAndPassword( email: _emailController.text.trim(), password: _passwordController.text.trim(), ); } @override void dispose() { _emailController.dispose(); _passwordController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Color(0xFFFFFCEA), body: SafeArea( child: Center( child: SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset("assets/images/illus14.png", width: 250 ), Text( "Sign in to your account", style: TextStyle(fontFamily: 'Montserrat', fontSize: 28, letterSpacing: -2, fontWeight: FontWeight.bold), ), SizedBox(height: 10), Text( "Welcome Back! Ready for your next ride?", textAlign: TextAlign.center, style: TextStyle(fontFamily: 'Montserrat', fontSize: 13, color: Color(0xff272727), letterSpacing: -0.5, fontWeight: FontWeight.w500), ), SizedBox(height: 30), Padding( padding: const EdgeInsets.symmetric(horizontal: 25), child: Container( decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( color: Color(0xffeeeeee), blurRadius: 10, offset: Offset(0,4) ), ], borderRadius: BorderRadius.circular(15), ), child: Padding( padding: const EdgeInsets.only(left: 20), child: TextField( controller: _emailController, decoration: InputDecoration( border: InputBorder.none, hintText: "Email", ), ), ), ), ), SizedBox(height:10), Padding( padding: const EdgeInsets.symmetric(horizontal: 25), child: TextField( controller: _passwordController, obscureText: true, decoration: InputDecoration( enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.white), borderRadius: BorderRadius.circular(15), ), focusedBorder: OutlineInputBorder( borderSide: BorderSide(color: Color(0xFFFED90F),), borderRadius: BorderRadius.circular(15), ), hintText: "Password", fillColor: Colors.white, filled: true, ), ), ), SizedBox(height: 20), Padding( padding: const EdgeInsets.symmetric(horizontal: 25), child: GestureDetector( onTap: signIn, child: Container( padding: EdgeInsets.all(20), decoration: BoxDecoration( color: Color(0xFFFED90F), borderRadius: BorderRadius.circular(50), ), child: Center( child: Text( "Sign in", style: TextStyle( color: Colors.white, fontFamily: 'Montserrat', fontSize: 16 ), ), ), ), ), ), SizedBox(height: 20), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text("Don't have an account yet?", style: TextStyle( color: Color(0xFF494949), fontFamily: 'Montserrat', fontSize: 16, letterSpacing: -0.5, fontWeight: FontWeight.w500 ), ), TextButton( onPressed: () { Navigator.pushReplacement(context, MaterialPageRoute( builder: (_) => SignUpPage(), ), ); }, child: Text("Register", style: TextStyle(fontFamily: 'Montserrat', fontSize: 16, letterSpacing: -0.5, fontWeight: FontWeight.w600, decoration: TextDecoration.underline, color:Color(0xFFFEDF3F), ), ), ), ], ), ], ), ), ), ), ); } }
当前页面效果:
期望实现的效果:
解决方案
要让矢量图作为背景显示在交互元素下方,核心是用Stack组件实现图层分层,把背景图放在底层,交互内容放在上层。修改后的完整代码如下:
import 'package:ehatid_driver_app/signup.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'Welcome/components/body.dart'; class LoginScreen extends StatefulWidget { const LoginScreen({ Key? key, }) : super(key: key); @override State<LoginScreen> createState() => _LoginScreenState(); } class _LoginScreenState extends State<LoginScreen> { //text controller final _emailController = TextEditingController(); final _passwordController = TextEditingController(); Future signIn() async { await FirebaseAuth.instance.signInWithEmailAndPassword( email: _emailController.text.trim(), password: _passwordController.text.trim(), ); } @override void dispose() { _emailController.dispose(); _passwordController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Color(0xFFFFFCEA), body: SafeArea( child: Stack( children: [ // 背景图:放在Stack最底层 Positioned.fill( child: Image.asset( "assets/images/illus14.png", fit: BoxFit.cover, // 如果需要调整透明度可以添加: // color: Colors.black.withOpacity(0.1), // colorBlendMode: BlendMode.darken, ), ), // 交互内容:放在背景图上方 Center( child: SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "Sign in to your account", style: TextStyle(fontFamily: 'Montserrat', fontSize: 28, letterSpacing: -2, fontWeight: FontWeight.bold), ), SizedBox(height: 10), Text( "Welcome Back! Ready for your next ride?", textAlign: TextAlign.center, style: TextStyle(fontFamily: 'Montserrat', fontSize: 13, color: Color(0xff272727), letterSpacing: -0.5, fontWeight: FontWeight.w500), ), SizedBox(height: 30), Padding( padding: const EdgeInsets.symmetric(horizontal: 25), child: Container( decoration: BoxDecoration( color: Colors.white, boxShadow: [ BoxShadow( color: Color(0xffeeeeee), blurRadius: 10, offset: Offset(0,4) ), ], borderRadius: BorderRadius.circular(15), ), child: Padding( padding: const EdgeInsets.only(left: 20), child: TextField( controller: _emailController, decoration: InputDecoration( border: InputBorder.none, hintText: "Email", ), ), ), ), ), SizedBox(height:10), Padding( padding: const EdgeInsets.symmetric(horizontal: 25), child: TextField( controller: _passwordController, obscureText: true, decoration: InputDecoration( enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.white), borderRadius: BorderRadius.circular(15), ), focusedBorder: OutlineInputBorder( borderSide: BorderSide(color: Color(0xFFFED90F),), borderRadius: BorderRadius.circular(15), ), hintText: "Password", fillColor: Colors.white, filled: true, ), ), ), SizedBox(height: 20), Padding( padding: const EdgeInsets.symmetric(horizontal: 25), child: GestureDetector( onTap: signIn, child: Container( padding: EdgeInsets.all(20), decoration: BoxDecoration( color: Color(0xFFFED90F), borderRadius: BorderRadius.circular(50), ), child: Center( child: Text( "Sign in", style: TextStyle( color: Colors.white, fontFamily: 'Montserrat', fontSize: 16 ), ), ), ), ), ), SizedBox(height: 20), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text("Don't have an account yet?", style: TextStyle( color: Color(0xFF494949), fontFamily: 'Montserrat', fontSize: 16, letterSpacing: -0.5, fontWeight: FontWeight.w500 ), ), TextButton( onPressed: () { Navigator.pushReplacement(context, MaterialPageRoute( builder: (_) => SignUpPage(), ), ); }, child: Text("Register", style: TextStyle(fontFamily: 'Montserrat', fontSize: 16, letterSpacing: -0.5, fontWeight: FontWeight.w600, decoration: TextDecoration.underline, color:Color(0xFFFEDF3F), ), ), ), ], ), ], ), ), ), ], ), ), ); } }
关键改动说明
- 用
Stack替代原来的直接嵌套,实现背景和内容的分层显示 Positioned.fill让背景图铺满整个SafeArea区域,BoxFit.cover保证图片按比例适配屏幕,不会拉伸变形- 移除了原来
Column里的Image.asset,把背景图独立放在Stack的第一个子元素(底层) - 保留了原有的交互内容结构,确保所有输入框、按钮等元素正常可交互
内容的提问来源于stack exchange,提问作者annyeongk
相关产品推荐
相关产品推荐

