我正在使用Flutter SDK和Dart制作移动应用程序,到目前为止,我只获得了一个简单的用户登录表单,其上方的主要小部件是一个ListView,顶部的小部件为Card小部件,其中包含图像。用作徽标,我的问题是,加载此徽标大约需要1到2秒钟,而且看起来非常难看。我的意思是,当我启动应用程序时,在启动屏幕之后,我在Card小部件上看到的全部是空白,然后在1到2秒钟后出现我的图片,非常引人注目。
我阅读了很多方法来避免这种情况,但是似乎没有任何效果,最常见的方法是使用precacheImage方法来预加载图像,但是那似乎不起作用,我还尝试了在构建版本时进行此操作,并且发生了同样的事情,我必须澄清这个徽标的尺寸非常小(100kB)。
到目前为止,这是我代码的一部分,该HomeState类只是Home状态小部件的State,该状态小部件是Scaffold小部件的主体,而Scaffold小部件是MaterialApp的宿主,这是主屏幕,因此在启动后屏幕上这是加载的第一件事,
class HomeState extends State<Home> {
var _minPad = 5.0;
var _formKey = GlobalKey<FormState>();
TextEditingController username = TextEditingController();
TextEditingController password = TextEditingController();
ImageProvider logo;
@override
void didChangeDependencies() async {
logo = AssetImage('images/logo_rienpa.png');
await precacheImage(logo, context);
super.didChangeDependencies();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Center(
child: Text('Rutinas de Mantenimiento',
textAlign: TextAlign.center))),
body: loginForm(),
backgroundColor: Colors.blue,
);
}
Form loginForm() {
TextStyle titleStyle = Theme.of(context).textTheme.title;
return Form(
key: _formKey,
child: Padding(
padding: EdgeInsets.all(_minPad * 4),
child: Center(
child: ListView(
children: <Widget>[
getLogo(),
Padding(
padding:
EdgeInsets.only(top: _minPad * 8, bottom: _minPad * 2),
child: TextFormField(
controller: username,
keyboardType: TextInputType.text,
style: titleStyle,
validator: (String value) {
if (value.isEmpty) {
return 'Por favor, ingresa tu nombre de usuario';
}
},
decoration: InputDecoration(
labelText: 'Usuario',
labelStyle: titleStyle,
hintText: 'Ingresa tu usuario',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0))),
)),
Padding(
padding:
EdgeInsets.only(top: _minPad * 2, bottom: _minPad * 4),
child: TextFormField(
controller: password,
obscureText: true,
style: titleStyle,
validator: (String value) {
if (value.isEmpty) {
return 'Por favor, ingresa una contraseña';
}
},
decoration: InputDecoration(
labelText: 'Contraseña',
labelStyle: titleStyle,
hintText: 'Contraseña personal',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0))),
),
),
Padding(
padding: EdgeInsets.only(
top: _minPad * 2,
bottom: _minPad * 2,
right: _minPad * 20,
left: _minPad * 20),
child: RaisedButton(
color: Theme.of(context).primaryColor,
textColor: Colors.white,
child: Text(
"Ingresar",
textScaleFactor: 1.5,
),
onPressed: () {
setState(() {
if (_formKey.currentState.validate()) {
//code
}
});
}),
),
Padding(
padding:
EdgeInsets.only(top: _minPad * 10, bottom: _minPad * 2),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"No tienes un usuario?, registrate ",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
),
InkWell(
child: Text(
'aqui',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
decoration: TextDecoration.underline),
),
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) {
return Register();
}));
},
),
Text(
".",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
)
],
))
],
),
),
));
}
Widget getLogo() {
Image logoImage = Image(image: logo, width: 250.0, height: 167.0,);
return Padding(
padding: EdgeInsets.only(right: _minPad * 5, left: _minPad * 5),
child: Card(
color: Colors.white,
elevation: 8.0,
child: logoImage,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(30.0)),
));
}
}
更新
根据要求,这是我的完整代码,它们是三个文件。
main.dart:
import 'package:flutter/material.dart';
import 'package:rutinas_de_mantenimiento/screens/home.dart';
void main() => runApp(MainApp());
class MainApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
precacheImage(AssetImage('images/logo_rienpa.png'), context);
return MaterialApp(
title: "Rutinas de Mantenimiento",
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blueGrey, primaryColor: Colors.blueGrey),
home: Home(),
);
}
}
home.dart(加载图像的地方)
import 'package:flutter/material.dart';
import 'package:rutinas_de_mantenimiento/screens/register.dart';
class Home extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return HomeState();
}
}
class HomeState extends State<Home> {
var _minPad = 5.0;
var _formKey = GlobalKey<FormState>();
TextEditingController username = TextEditingController();
TextEditingController password = TextEditingController();
ImageProvider logo = AssetImage('images/logo_rienpa.png');
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Center(
child: Text('Rutinas de Mantenimiento',
textAlign: TextAlign.center))),
body: loginForm(),
backgroundColor: Colors.blue,
);
}
Form loginForm() {
TextStyle titleStyle = Theme.of(context).textTheme.title;
return Form(
key: _formKey,
child: Padding(
padding: EdgeInsets.all(_minPad * 4),
child: Center(
child: ListView(
children: <Widget>[
getLogo(),
Padding(
padding:
EdgeInsets.only(top: _minPad * 8, bottom: _minPad * 2),
child: TextFormField(
controller: username,
keyboardType: TextInputType.text,
style: titleStyle,
validator: (String value) {
if (value.isEmpty) {
return 'Por favor, ingresa tu nombre de usuario';
}
},
decoration: InputDecoration(
labelText: 'Usuario',
labelStyle: titleStyle,
hintText: 'Ingresa tu usuario',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0))),
)),
Padding(
padding:
EdgeInsets.only(top: _minPad * 2, bottom: _minPad * 4),
child: TextFormField(
controller: password,
obscureText: true,
style: titleStyle,
validator: (String value) {
if (value.isEmpty) {
return 'Por favor, ingresa una contraseña';
}
},
decoration: InputDecoration(
labelText: 'Contraseña',
labelStyle: titleStyle,
hintText: 'Contraseña personal',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0))),
),
),
Padding(
padding: EdgeInsets.only(
top: _minPad * 2,
bottom: _minPad * 2,
right: _minPad * 20,
left: _minPad * 20),
child: RaisedButton(
color: Theme.of(context).primaryColor,
textColor: Colors.white,
child: Text(
"Ingresar",
textScaleFactor: 1.5,
),
onPressed: () {
setState(() {
if (_formKey.currentState.validate()) {
//code
}
});
}),
),
Padding(
padding:
EdgeInsets.only(top: _minPad * 10, bottom: _minPad * 2),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"No tienes un usuario?, registrate ",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
),
InkWell(
child: Text(
'aqui',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
decoration: TextDecoration.underline),
),
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) {
return Register();
}));
},
),
Text(
".",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
)
],
))
],
),
),
));
}
Widget getLogo() {
Image logoImage = Image(image: logo, width: 250.0, height: 167.0,);
return Padding(
padding: EdgeInsets.only(right: _minPad * 5, left: _minPad * 5),
child: Card(
color: Colors.white,
elevation: 8.0,
child: logoImage,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(30.0)),
));
}
}
还有resgister.dart,我认为这不是必需的,但是就可以了
import 'package:flutter/material.dart';
class Register extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return RegisterState();
}
}
class RegisterState extends State<Register> {
var _formKey = GlobalKey<FormState>();
TextEditingController fullName = TextEditingController();
TextEditingController username = TextEditingController();
TextEditingController password = TextEditingController();
TextEditingController confirmPwd = TextEditingController();
TextEditingController email = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Center(
child: Text(
'Rutinas de Mantenimiento',
textAlign: TextAlign.center,
),
),
automaticallyImplyLeading: false,
),
body: registerForm(),
backgroundColor: Colors.blue,
);
}
Form registerForm() {
var _minPad = 5.0;
TextStyle titleStyle = Theme.of(context).textTheme.title;
return Form(
key: _formKey,
child: Padding(
padding: EdgeInsets.all(_minPad * 4),
child: Center(
child: ListView(
children: <Widget>[
Text(
"Registro de usuario",
textAlign: TextAlign.center,
style: TextStyle(
decoration: null,
fontSize: 35.0,
color: Colors.white),
),
Padding(
padding:
EdgeInsets.only(top: _minPad * 14, bottom: _minPad * 2),
child: TextFormField(
controller: fullName,
style: titleStyle,
textAlign: TextAlign.center,
validator: (String value) {
if (value.isEmpty) {
return 'Por favor ingresa tu nombre completo';
}
},
decoration: InputDecoration(
hintText: "Nombre completo", hintStyle: titleStyle),
),
),
Padding(
padding: EdgeInsets.only(top: _minPad * 2, bottom: _minPad * 2),
child: TextFormField(
controller: username,
style: titleStyle,
textAlign: TextAlign.center,
validator: (String value) {
if (value.isEmpty) {
return 'Por favor ingresa un usuario';
}
},
decoration: InputDecoration(
hintText: "Nombre de usuario", hintStyle: titleStyle),
),
),
Padding(
padding: EdgeInsets.only(top: _minPad * 2, bottom: _minPad * 2),
child: TextFormField(
controller: email,
style: titleStyle,
textAlign: TextAlign.center,
validator: (String value) {
if (value.isEmpty) {
return 'Por favor ingresa tu Email';
}
},
decoration:
InputDecoration(hintText: "Email", hintStyle: titleStyle),
),
),
Padding(
padding: EdgeInsets.only(top: _minPad * 2, bottom: _minPad * 2),
child: TextFormField(
controller: password,
obscureText: true,
style: titleStyle,
textAlign: TextAlign.center,
validator: (String value) {
if (value.isEmpty) {
return 'Por favor ingresa una contraseña';
}
},
decoration: InputDecoration(
hintText: "Contraseña", hintStyle: titleStyle),
),
),
Padding(
padding: EdgeInsets.only(top: _minPad * 2, bottom: _minPad * 2),
child: TextFormField(
controller: confirmPwd,
obscureText: true,
style: titleStyle,
textAlign: TextAlign.center,
validator: (String value) {
if (value.isEmpty) {
return 'Por favor repita su contraseña';
}
},
decoration: InputDecoration(
hintText: "Confirme contraseña", hintStyle: titleStyle),
),
),
Padding(
padding: EdgeInsets.only(
top: _minPad * 4,
bottom: _minPad * 2,
right: _minPad * 20,
left: _minPad * 20),
child: RaisedButton(
color: Theme.of(context).primaryColor,
textColor: Colors.white,
child: Text(
"Registrar",
textScaleFactor: 1.5,
),
onPressed: () {
setState(() {
if (_formKey.currentState.validate()) {
//code
}
});
}),
)
],
),
),
),
);
}
}
答案 0 :(得分:1)
我的抽屉背景图像有相同的问题,我用precache图像解决了,我想您在错误的地方使用了precacheimage。您需要了解,为了正确显示图像,您需要在应用启动时而不是在启动状态之前加载图像。 试试这个:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
precacheImage(AssetImage("images/logo_rienpa.png"), context);
return MaterialApp(
title: 'Fethi',
theme: ThemeData(
primarySwatch: Colors.lightBlue,
),
home: new HomeState(),
);
}
}
在HomeState页面上,您不需要使用didChangeDependencies(),只需在定义中声明图像即可,如下所示:
ImageProvider logo = AssetImage("images/logo_rienpa.png");
答案 1 :(得分:0)
我有一个类似的问题,对我来说,我将图像从5000 x 5000缩小到250 x 250,因为它们的大小不比应用程序文件中的大小从11mb增大到75kb,然后在Photoshop中我也将其导出为一个较小的文件(8位),大约35kb。我会尝试jpeg的,但是我需要透明的背景!但是文件大小的大量减少对我有所帮助。