【Flutter】
状態管理
provider + ChangeNotifier
provider = 親Widgetから子Widgetへのデータ受け渡しを行うためのパッケージ
ChangeNotifier = 変更通知が行えるクラス(Flutterが標準で提供している)
providerの中にChangeNotifierProviderというクラスがあり、ChangeNotifierの変更をlistenし、子Widgetへと変更を通知することができる
- インスタンス化して子に渡す場合
Provider(
create: (context) => MyWidget(),
child: ...
)
- すでに生成されたインスタンスを渡す場合
MyWidget myWidget = MyWidget()
Provider.value(
value: myWidget,
child: ...
)
Provider()
(またはProvider.value()
)で渡した値は、Provider.of(context)
で、コンテキストから参照できる。
提供側で使用するクラスによっては値が動的に変化する。(ChangeNotifierProviderやStreamProviderなど)
その変更を下位のWidgetで監視するためには、Provider.of(context, listen: true)
とする。(デフォルトはlisten=true
なのでわざわざ書かなくてよい。)
逆に変更を監視する必要がなく、Widgetのリビルドを避けたい場合はlisten: false
にする。
provider v4.1.0から、Provider.ofの代わりに、BuildContextのExtentionメソッドが追加されている。
Provider.of(context, listen: false)
=> context.read()
Provider.of(context, listen: true)
=> context.watch()
複数あるデータのうち一部のみを選択的に監視するためにはSelector()
を使用する。
provider v4.1.0からはより簡潔に書ける方法としてcontext.select()
がある。
画面遷移
名前付きルート
画面の差し替え
この方法で遷移すると前の画面には戻れない。
Navigator.of(context).pushReplacementNamed('/hoge');
Navigator.pushReplacementNamed(context, '/hoge');
スタック
- 画面が順に積まれていくため、前の画面に戻ることができる。
Navigator.of(context).pushNamed("/hoge");
Navigator.pushNamed(context, '/hoge');
// 前の画面に戻る
Navigator.of(context).pop();
Navigator.pop(context);
- 指定した画面まで戻る。
Navigator.popUntil(context, ModalRoute.withName("/hoge"));
- 指定した画面までpopして、新規画面をpushする。
// '/'まで戻って、Hoge()を表示
Navigator.of(context).pushNamedAndRemoveUntil(
'/hoge',
ModalRoute.withName('/'),
);
Navigator.pushNamedAndRemoveUntil(
context,
'/hoge',
ModalRoute.withName('/'),
);
// 全画面popして、Hoge()を表示
Navigator.of(context).pushNamedAndRemoveUntil(
'/hoge',
(route) => false,
);
Navigator.pushNamedAndRemoveUntil(
context,
'/hoge',
(route) => false,
);
名前で指定しない場合
MaterialPageRouteでルートを取得する
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return SecondPage();
},
),
);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return SecondPage();
},
),
);
- 指定した画面までpopして、新規画面をpushする。
// '/'まで戻って、Hoge()を表示
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (BuildContext context) => Hoge()),
(Route<dynamic> route) => route is Hoge,
);
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (BuildContext context) => Hoge()),
(Route<dynamic> route) => route is Hoge,
);
// 全画面popして、Hoge()を表示
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (BuildContext context) => Hoge()),
(Route<dynamic> route) => route is Hoge,
);
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (BuildContext context) => Hoge()),
(Route<dynamic> route) => route is Hoge,
);
漢字が中華フォントにならないようにする
flutter_localizationsパッケージをインストール
import 'package:flutter_localizations/flutter_localizations.dart';
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
// ここから
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
Locale('ja'),
],
// ここまで
...
}
``
クリックイベントを付与する
クリックイベントを付与するためのWidget(GestureDetector, InkWell, InkResponse)でラップする。
GestureDetector(
onTap: () { ... },
child: Card( ...
テーマの色
iPhoneのシミュレータでソフトウェアキーボードが表示できないとき
Simulatorメニューバー > I/O > Keyboard > Connect Hardware Keyboardのチェックを外す。
キーボードを表示したときのWidgetのサイズについて
画面下から出てくるモーダル
isScrollControlled: trueと、子Widgetのheightを設定することで任意の高さにできる。
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) => Container(
height: MediaQuery.of(context).size.height * 0.85,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(25.0),
topRight: const Radius.circular(25.0),
),
),
child: ...