こんにちは、パスワードを忘れた場合の画面を設計し、ボタンのクリック時にFirebaseを統合しました。ユーザーがボタンをクリックしたときにCircularProgressIndicator
を表示し、firebaseの実行が終了したらそれを閉じます。
誰もこれを行う方法を知っていますか? CircularProgressIndicator
をデバイスの中央に置きたいです。
class ForgotPasswordScreen extends StatelessWidget {
final emailController = new TextEditingController();
final authHandler = new Auth();
@override
Widget build(BuildContext context) {
return new Scaffold(body: Container(
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
color: Colors.white,
),
child: new Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Row(
children: <Widget>[
new Expanded(
child: new Padding(
padding: const EdgeInsets.only(left: 40.0),
child: new Text(
"EMAIL",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.redAccent,
fontSize: 15.0,
),
),
),
),
],
),
new Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(left: 40.0, right: 40.0, top: 10.0),
alignment: Alignment.center,
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Colors.redAccent,
width: 0.5,
style: BorderStyle.solid),
),
),
padding: const EdgeInsets.only(left: 0.0, right: 10.0),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Expanded(
child: TextField(
controller: emailController,
textAlign: TextAlign.left,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'PLEASE ENTER YOUR EMAIL',
hintStyle: TextStyle(color: Colors.grey),
),
),
),
],
),
),
Divider(
height: 24.0,
),
new Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(left: 30.0, right: 30.0, top: 20.0),
alignment: Alignment.center,
child: new Row(
children: <Widget>[
new Expanded(
child: new FlatButton(
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
color: Colors.redAccent,
onPressed: () => authHandler.sendPasswordResetEmail(emailController.text).then((void nothing) {
print("done");
}).catchError((e) => print(e)),
child: new Container(
padding: const EdgeInsets.symmetric(
vertical: 20.0,
horizontal: 20.0,
),
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Expanded(
child: Text(
"FORGOT PASSWORD",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold),
),
),
],
),
),
),
),
],
),
),
],
),
));
}
}
さて、最初にコードを少し変更する必要があります。
Stateless
からStateful
に変更して、ウィジェットの状態を管理し、isLoading
という名前のグローバル変数を配置します。その変数を使用して、ボタンを押したときにisLoading
trueを設定し、完了後にisLoading
falseを設定できます。
build
メソッド内に検証を追加して、isLoading
がtrueの場合に循環進行を表示し、そうでない場合はフィールドを表示します。
ここにコードサンプル:
class ForgotPasswordScreen extends StatefulWidget {
@override
ForgotPasswordScreenState createState() {
return new ForgotPasswordScreenState();
}
}
class ForgotPasswordScreenState extends State<ForgotPasswordScreen> {
final emailController = new TextEditingController();
final authHandler = new Auth();
bool isLoading = false;
@override
Widget build(BuildContext context) {
return new Scaffold(
body: Container(
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
color: Colors.white,
),
child: isLoading
? Center(
child: CircularProgressIndicator(),
)
: new Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Row(
children: <Widget>[
new Expanded(
child: new Padding(
padding: const EdgeInsets.only(left: 40.0),
child: new Text(
"EMAIL",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.redAccent,
fontSize: 15.0,
),
),
),
),
],
),
new Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(
left: 40.0, right: 40.0, top: 10.0),
alignment: Alignment.center,
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Colors.redAccent,
width: 0.5,
style: BorderStyle.solid),
),
),
padding: const EdgeInsets.only(left: 0.0, right: 10.0),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Expanded(
child: TextField(
controller: emailController,
textAlign: TextAlign.left,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'PLEASE ENTER YOUR EMAIL',
hintStyle: TextStyle(color: Colors.grey),
),
),
),
],
),
),
Divider(
height: 24.0,
),
new Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(
left: 30.0, right: 30.0, top: 20.0),
alignment: Alignment.center,
child: new Row(
children: <Widget>[
new Expanded(
child: new FlatButton(
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
color: Colors.redAccent,
onPressed: () {
setState(() {
isLoading = true;
});
authHandler
.sendPasswordResetEmail(
emailController.text)
.then((void nothing) {
print("done");
setState(() {
isLoading = false;
});
}).catchError((e) => print(e));
},
child: new Container(
padding: const EdgeInsets.symmetric(
vertical: 20.0,
horizontal: 20.0,
),
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Expanded(
child: Text(
"FORGOT PASSWORD",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold),
),
),
],
),
),
),
),
],
),
),
],
)));
}
}
この質問は少し古いですが、先物参照のためにもう1つオプションを登録します。 3つのクラスを作成します。 ModalRoundedProgressBarと呼ばれるものは、CricularProgressBarIndicatorの表示と非表示、ウィジェットレイアウトを作成するModalRoundedProgressBarStateクラス、最後に、必要なときに必要なときに円形のプログレスバーを表示および非表示できるProgressBarHandlerというハンドルクラスを呼び出します。コードにはいくつかのコメントがあります
class ModalRoundedProgressBar extends StatefulWidget {
final double _opacity;
final String _textMessage; // optional message to show
final Function _handlerCallback; // callback that will give a handler object to change widget state.
ModalRoundedProgressBar({
@required Function handleCallback(ProgressBarHandler handler),
String message = "", // some text to show if needed...
double opacity = 0.7, // opacity default value
}) : _textMessage = message,
_opacity = opacity,
_handlerCallback = handleCallback;
@override
State createState() => _ModalRoundedProgressBarState();
}
//StateClass ...
class _ModalRoundedProgressBarState extends State<ModalRoundedProgressBar> {
bool _isShowing = false; // member that control if a rounded progressBar will be showing or not
@override
void initState() {
super.initState();
/* Here we create a handle object that will be sent for a widget that creates a ModalRounded ProgressBar.*/
ProgressBarHandler handler = ProgressBarHandler();
handler.show = this.show; // handler show member holds a show() method
handler.dismiss = this.dismiss; // handler dismiss member holds a dismiss method
widget._handlerCallback(handler); //callback to send handler object
}
@override
Widget build(BuildContext context) {
//return a simple stack if we don't wanna show a roundedProgressBar...
if (!_isShowing) return Stack();
// here we return a layout structre that show a roundedProgressBar with a simple text message
return Material(
color: Colors.transparent,
child: Stack(
children: <Widget>[
Opacity(
opacity: widget._opacity,
//ModalBarried used to make a modal effect on screen
child: ModalBarrier(
dismissible: false,
color: Colors.black54,
),
),
Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CircularProgressIndicator(),
Text(widget._textMessage),
],
),
),
],
),
);
}
// method do change state and show our CircularProgressBar
void show() {
setState(() => _isShowing = true);
}
// method to change state and hide our CIrcularProgressBar
void dismiss() {
setState(() => _isShowing = false);
}
}
// handler class
class ProgressBarHandler {
Function show; //show is the name of member..can be what you want...
Function dismiss;
}
次に、このウィジェットをScreenウィジェットに実装するだけです。簡単な実装例を作成します。
class YourScreen extends StatelessWidget{
//handler that we will use to show and hide widget
ProgressBarHandler _handler;
@override
Widget build(BuildContext context){
var scaffold = Scaffold(
appBar: AppBar(title: Text("Title"),),
body: _buildYourBodyLayout(),
);
var progressBar = ModalRoundedProgressBar(
//getting the handler
handleCallback: (handler) { _handler = handler;},
);
return Stack(
children: <Widget>[
scaffold,
progressBar,
],
);
}
// some code.... when you need to show a progres you will call: _handler.show();
//when you want hide the progressbar ou call: _handler.dismiss();
}
このアプローチでは、再利用可能なコンポーネントがあり、丸みのある進行状況バーを表示または非表示にするためだけにすべての画面レイアウトを再作成する必要はありません。
私の悪い英語でごめんなさい...これが誰かの助けになることを願っています。