所以我有一个注册页面,注册功能很好用。
现在,我只需要按一下“注册”按钮后的加载指示器即可。
我已经混合了所有可以想到的要在google中搜索的关键字,并且已经尝试了所有关键字,但无济于事。
这是我尝试过的事情:
使用 FutureBuilder :
RaisedButton(
onPressed: () async {
FutureBuilder<http.Response>(
future: registerUser(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text("SUCCESS");
}
if (snapshot.hasError) {
return Text("ERROR");
}
return new Center(
child: new CircularProgressIndicator());
},
);
},
color: Color(colorPrimary),
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0)),
child: Text("SignUp"),
)
在此方法中,方法被调用,但指示器未显示
使用库 progress_hud :
我认为这是可行的,但是即使我将其放在Center
小部件中,
它仍然会转到屏幕底部,并显示overlapping with pixels
错误。
还有其他更好的解决方案吗?还是应该只找到一种解决此重叠错误的方法?
感谢您的帮助!
答案 0 :(得分:1)
请使用软件包modal_progress_hud https://pub.dev/packages/modal_progress_hud
ModalProgressHUD必须作为第一个孩子放在脚手架下
我的工作代码段
@override
Widget build(BuildContext context) {
return Scaffold(
body: ModalProgressHUD(
inAsyncCall: _isLoading,
child: SingleChildScrollView(
child: Container(
...
完整的示例代码
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:modal_progress_hud/modal_progress_hud.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: LoginPage(
onSignIn: () => print('login successful!'),
),
);
}
}
class LoginPage extends StatefulWidget {
final VoidCallback _onSignIn;
LoginPage({@required onSignIn})
: assert(onSignIn != null),
_onSignIn = onSignIn;
@override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
// maintains validators and state of form fields
final GlobalKey<FormState> _loginFormKey = GlobalKey<FormState>();
// manage state of modal progress HUD widget
bool _isInAsyncCall = false;
bool _isInvalidAsyncUser = false; // managed after response from server
bool _isInvalidAsyncPass = false; // managed after response from server
String _username;
String _password;
bool _isLoggedIn = false;
// validate user name
String _validateUserName(String userName) {
if (userName.length < 8) {
return 'Username must be at least 8 characters';
}
if (_isInvalidAsyncUser) {
// disable message until after next async call
_isInvalidAsyncUser = false;
return 'Incorrect user name';
}
return null;
}
// validate password
String _validatePassword(String password) {
if (password.length < 8) {
return 'Password must be at least 8 characters';
}
if (_isInvalidAsyncPass) {
// disable message until after next async call
_isInvalidAsyncPass = false;
return 'Incorrect password';
}
return null;
}
void _submit() {
if (_loginFormKey.currentState.validate()) {
_loginFormKey.currentState.save();
// dismiss keyboard during async call
FocusScope.of(context).requestFocus(new FocusNode());
// start the modal progress HUD
setState(() {
_isInAsyncCall = true;
});
// Simulate a service call
Future.delayed(Duration(seconds: 1), () {
final _accountUsername = 'username1';
final _accountPassword = 'password1';
setState(() {
if (_username == _accountUsername) {
_isInvalidAsyncUser = false;
if (_password == _accountPassword) {
// username and password are correct
_isInvalidAsyncPass = false;
_isLoggedIn = true;
} else
// username is correct, but password is incorrect
_isInvalidAsyncPass = true;
} else {
// incorrect username and have not checked password result
_isInvalidAsyncUser = true;
// no such user, so no need to trigger async password validator
_isInvalidAsyncPass = false;
}
// stop the modal progress HUD
_isInAsyncCall = false;
});
if (_isLoggedIn)
// do something
widget._onSignIn();
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Modal Progress HUD Demo'),
backgroundColor: Colors.blue,
),
// display modal progress HUD (heads-up display, or indicator)
// when in async call
body: ModalProgressHUD(
child: SingleChildScrollView(
child: Container(
padding: const EdgeInsets.all(16.0),
child: buildLoginForm(context),
),
),
inAsyncCall: _isInAsyncCall,
// demo of some additional parameters
opacity: 0.5,
progressIndicator: CircularProgressIndicator(),
),
);
}
Widget buildLoginForm(BuildContext context) {
final TextTheme textTheme = Theme.of(context).textTheme;
// run the validators on reload to process async results
_loginFormKey.currentState?.validate();
return Form(
key: this._loginFormKey,
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
key: Key('username'),
decoration: InputDecoration(
hintText: 'enter username', labelText: 'User Name'),
style: TextStyle(fontSize: 20.0, color: textTheme.button.color),
validator: _validateUserName,
onSaved: (value) => _username = value,
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
key: Key('password'),
obscureText: true,
decoration: InputDecoration(
hintText: 'enter password', labelText: 'Password'),
style: TextStyle(fontSize: 20.0, color: textTheme.button.color),
validator: _validatePassword,
onSaved: (value) => _password = value,
),
),
Padding(
padding: const EdgeInsets.all(32.0),
child: RaisedButton(
onPressed: _submit,
child: Text('Login'),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: _isLoggedIn
? Text(
'Login successful!',
key: Key('loggedIn'),
style: TextStyle(fontSize: 20.0),
)
: Text(
'Not logged in',
key: Key('notLoggedIn'),
style: TextStyle(fontSize: 20.0),
),
),
],
),
);
}
}
答案 1 :(得分:0)
FutureBuilder
将其生成的主体放在其附加的小部件中。
否则,返回的Widget会去哪里?
材料脚手架示例
Scaffold(
appBar:AppBar(),
body: FutureBuilder(
future: registerUser(),
builder: (context,snapshot){
//...
}
)
)
问题是,您的未来必然会紧迫RaisedButton
。
其次,您可能最好使用StreamBuilder
,因为FutureBuilder
会在build方法中立即调用它的未来。
因此,改为调用BLoC / ViewModel / wathever以执行registerUser()
。
让registerUser()
返回一个Future<void>
(并将结果内部添加到Stream
中)。
然后观察Stream
的结果或错误。
对于Streams
/ Sinks
,可以使用StreamController<T>
。
//In your form Widget
RaisedButton(
onPressed: registerUser()
)
//In your Widget/BLoC/ViewModel
//Note that the Future can finish with errors from the http call
//call registerUser() with an onError callback to catch these.
//And the Stream can finish with errors(although this is unlikely here)
//the Stream.listen() can also have an onError callback
Future<void> registerUser() async {
var result = await http.post();
//then finally pass it to the stream
_stream.add(result);
}
答案 2 :(得分:0)
请使用包progress_dialog https://pub.dev/packages/progress_dialog
以下是我的工作代码片段。
pub.yaml
import 'package:fluttertoast/fluttertoast.dart';
import 'package:progress_dialog/progress_dialog.dart';
ProgressDialog progressDialog;
showProgress(BuildContext context, String message, bool isDismissible) async {
progressDialog = new ProgressDialog(context,
type: ProgressDialogType.Normal, isDismissible: isDismissible);
progressDialog.style(
message: message,
borderRadius: 10.0,
backgroundColor: Color(COLOR_PRIMARY),
progressWidget: Container(
padding: EdgeInsets.all(8.0),
child: CircularProgressIndicator(
backgroundColor: Colors.white,
)),
elevation: 10.0,
insetAnimCurve: Curves.easeInOut,
messageTextStyle: TextStyle(
color: Colors.white, fontSize: 19.0, fontWeight: FontWeight.w600));
await progressDialog.show();
}
updateProgress(String message) {
progressDialog.update(message: message);
}
hideProgress() async {
if(progressDialog!=null)
await progressDialog.hide();
}
helper.dart
import 'package:mygame/services/helper.dart';
...
RaisedButton(
onPressed: () async {
showProgress(context, 'Registering user, please wait...', true);
await registerUser().then((result) {
hideProgress();
pushAndRemoveUntil(context, HomePage(), false);
}).catchError((error) {
hideProgress();
Fluttertoast.showToast(
msg: "Signup failed:"+error.toString(),
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.green.shade700,
textColor: Colors.white,
fontSize: 16.0
);
print('Registration Error: $error');
});
},
color: Color(colorPrimary),
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0)),
child: Text("SignUp"),
)
登录.dart
df1 = pd.DataFrame({
'Product': ['AA', 'AA', 'BB', 'BB', 'BB'],
'Col1': [1, 2, 1, 2, 3],
'Col2': [2, 4, 2, 4, 6]})
print(df1)
df2 = pd.DataFrame({
'FX Rate': [1.5, 2.0, 3.0, 5.0, 10.0]})
print(df2)
df1 = df1.reset_index(drop=True)
df2 = df2.reset_index(drop=True)
for col in ['Col1', 'Col2']:
df1[col] = df1[col] * df2['FX Rate']
df1
(df1)
Product Col1 Col2
0 AA 1 2
1 AA 2 4
2 BB 1 2
3 BB 2 4
4 BB 3 6
(df2)
FX Rate
0 1.5
1 2.0
2 3.0
3 5.0
4 10.0
Out[1]:
Product Col1 Col2
0 AA 1.5 3.0
1 AA 4.0 8.0
2 BB 3.0 6.0
3 BB 10.0 20.0
4 BB 30.0 60.0