##はじめに
この記事では以下の画像のような,ボタンを押すことでWidgetを切り替える方法について説明しています。
##この記事が参考になるかもしれない人
- コピペで動くソースコードをいじることによってFlutterについて学習したい人
- FlutterでWidgetの切り替えを行いたい人
- StackでWidgetを重ねることによる実装が行いたい人
- Offstageによる実装を行いたい人
- 自分
##前提知識
- Columnで鉛直方向にWidgetを並べることができる。
-
mainAxisAlignment: MainAxisAlignment.center
でColumnに対し真ん中で鉛直方向に並べさせることができる。 - StackでWidgetを重ねることができる。(Columnは鉛直方向,Rowは水平方向)
- StatefulWidgetは変数の変更など動的な操作をする時に使う。
##1.OffStageでWidgetを表示したり非表示にしたりできる
OffstageはレイアウトWidgetであり、表示/非表示を設定したいWidgetをchildに入れる。また,offstageに真偽値を指定し、falseの時に表示される。しかし、false/trueはいずれも固定されているものなので,表示/非表示を設定したいのであれば,ここにはbool型の変数を用いるべきだろう。
また,注意したいのがOffStageに格納されたWidgetは非表示にされた場合子要素のWidget自体が存在していないものとして扱われる。つまり、Columnなどの連続したものの中の一つにOffstageを入れた場合,非表示となったWidgetの部分は他のWidgetが詰めて配置されることとなる。
Offstage(
offstage: show,
child: Container(
width: 100,
height: 100,
color: Colors.red,
),
)
##2.Offstageだと詰められてしまうので,Stackを用意して対策する。
上述した通り,Offstageで書いた要素はパラメータoffstageがtrueの時元から存在していなかったものとして扱われてしまう。なので,その時には別のWidget(たとえば子要素が何もないContainer)を用意する必要がある。
Stack(
children: <Widget>[
Offstage(
offstage: show,
child: Container(
width: 100,
height: 100,
color: Colors.red,
),
),
Offstage(
offstage: !show,
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
],
),
Stackの子要素集合にそれぞれOffstageWidgetのパラメータoffstageが偽の時と真の時を用意することで、配置がずれることなく表示/非表示を設定することができる。
##ソースコード
コピペで動きます。(2020.10.6)
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool show = false;
void showChange() {
setState(() {show = !show;});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Stack(
children: <Widget>[
Offstage(
offstage: show,
child: Container(
width: 100,
height: 100,
color: Colors.red,
),
),
Offstage(
offstage: !show,
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
],
),
Container(
width: 100,
height: 100,
child: RaisedButton(
child: Text("変更"),
onPressed: showChange
),
),
],
),
),
),
);
}
}