August 13, 2024
親から子のフィールドにアクセス
#
GlobalKey を使う
#
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: MyParentWidget(),
));
}
class MyParentWidget extends StatelessWidget {
MyParentWidget({super.key});
final myChildWidgetKey = GlobalKey<MyChildWidgetState>();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Text('${myChildWidgetKey.currentState?.count ?? 0}'),
IconButton(
icon: const Icon(Icons.add),
onPressed: () {
myChildWidgetKey.currentState?.increment();
// myChildWidgetKey.currentState?.increment(); を呼び出しても、MyParentWidget 自身は再ビルドされず、
// myChildWidgetKey.currentState?.count の更新が画面に反映されない
// MyParentWidget 自身を再ビルドするために markNeedsBuild(); を呼び出す
(context as Element).markNeedsBuild();
},
),
MyChildWidget(
key: myChildWidgetKey,
),
],
),
);
}
}
class MyChildWidget extends StatefulWidget {
const MyChildWidget({super.key});
@override
State<MyChildWidget> createState() => MyChildWidgetState();
}
class MyChildWidgetState extends State<MyChildWidget> {
int count = 0;
void increment() {
setState(() {
count++;
});
}
@override
Widget build(BuildContext context) {
return const SizedBox();
}
}
子から親のフィールドにアクセス
#
親からプロップスを受け取る
#
import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(
home: MyParentWidget(),
));
}
class MyParentWidget extends StatefulWidget {
const MyParentWidget({super.key});
@override
State<MyParentWidget> createState() => _MyParentWidgetState();
}
class _MyParentWidgetState extends State<MyParentWidget> {
int _count = 0;
void _increment() {
setState(() {
_count++;
});
}
@override
Widget build(BuildContext context) {
return MyChildWidget(
count: _count,
increment: _increment,
);
}
}
class MyChildWidget extends StatelessWidget {
const MyChildWidget({
super.key,
required this.count,
required this.increment,
});
final int count;
final VoidCallback increment;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Text('$count'),
IconButton(
icon: const Icon(Icons.add),
onPressed: increment,
),
],
),
);
}
}
import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(
home: MyParentWidget(),
));
}
class MyInheritedWidget extends InheritedWidget {
const MyInheritedWidget({
super.key,
required this.count,
required this.increment,
required super.child,
});
final int count;
final VoidCallback increment;
@override
bool updateShouldNotify(MyInheritedWidget oldWidget) {
return true;
}
static MyInheritedWidget of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>()!;
}
}
class MyParentWidget extends StatefulWidget {
const MyParentWidget({super.key});
@override
State<MyParentWidget> createState() => _MyParentWidgetState();
}
class _MyParentWidgetState extends State<MyParentWidget> {
int _count = 0;
void _increment() {
setState(() {
_count++;
});
}
@override
Widget build(BuildContext context) {
return MyInheritedWidget(
count: _count,
increment: _increment,
child: const MyChildWidget(),
);
}
}
class MyChildWidget extends StatelessWidget {
const MyChildWidget({super.key});
@override
Widget build(BuildContext context) {
final counter = MyInheritedWidget.of(context);
return Scaffold(
body: Column(
children: [
Text('${counter.count}'),
IconButton(
icon: const Icon(Icons.add),
onPressed: counter.increment,
),
],
),
);
}
}
findAncestorStateOfType で親にアクセスする
#
import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(
home: MyParentWidget(),
));
}
class MyParentWidget extends StatefulWidget {
const MyParentWidget({super.key});
@override
State<MyParentWidget> createState() => MyParentWidgetState();
}
class MyParentWidgetState extends State<MyParentWidget> {
int count = 0;
void increment() {
setState(() {
count++;
});
}
@override
Widget build(BuildContext context) {
// const をつけると count が変わっても再ビルドされないため const を外す
// ignore: prefer_const_constructors
return MyChildWidget();
}
}
class MyChildWidget extends StatelessWidget {
const MyChildWidget({super.key});
@override
Widget build(BuildContext context) {
final state = context.findAncestorStateOfType<MyParentWidgetState>()!;
return Scaffold(
body: Column(
children: [
Text('${state.count}'),
IconButton(
icon: const Icon(Icons.add),
onPressed: state.increment,
),
],
),
);
}
}
GlobalKey を使う
#
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: MyParentWidget(),
));
}
final myParentWidgetKey = GlobalKey<MyParentWidgetState>();
class MyParentWidget extends StatefulWidget {
MyParentWidget() : super(key: myParentWidgetKey);
@override
State<MyParentWidget> createState() => MyParentWidgetState();
}
class MyParentWidgetState extends State<MyParentWidget> {
int count = 0;
void increment() {
setState(() {
count++;
});
}
@override
Widget build(BuildContext context) {
// const をつけると count が変わっても再ビルドされないため const を外す
// ignore: prefer_const_constructors
return MyChildWidget();
}
}
class MyChildWidget extends StatelessWidget {
const MyChildWidget({super.key});
@override
Widget build(BuildContext context) {
final state = myParentWidgetKey.currentState!;
return Scaffold(
body: Column(
children: [
Text('${state.count}'),
IconButton(
icon: const Icon(Icons.add),
onPressed: state.increment,
),
],
),
);
}
}
その他参考
#
- widget と subwidget 間で直接参照の仕方 | GitHub Gist