我正在尝试在其小部件之外设置一个 StatefulBuilder
小部件状态。大多数示例和可用文档都显示了在小部件内部使用的 setState
方法,但是我想知道是否可以从 StatefulBuilder
小部件外部调用此类方法。举个例子:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'StackOverflow Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'StackOverflow Example'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return new GestureDetector(
//Change one of the icon's color using the tap down function
onTapDown: (TapDownDetails details) {
return changeColor(details);
},
child: Scaffold(
appBar: AppBar(
title: Text('Example'),
),
body: Center(
child: Column(children: [
//This widget should be rebuilt
StatefulBuilder(
builder: (BuildContext context, StateSetter setState)
{
Color _iconColor = Colors.black;
return Icon(
Icons.money,
size: 50,
color: _iconColor,
);
}
),
//This icon should not be rebuilt
Icon(
Icons.euro,
size: 50,
color: Colors.black,
),
]),
),
),
);
}
void changeColor(TapDownDetails details) {
//Rebuilt StatefulBuilder widget here, but how?
setState(() {
_iconColor = Colors.green;
});
}
}
目前我收到一个错误,因为 _iconColor
中使用了 setState
变量。我也知道可能无法在小部件之外访问它。如果是这种情况,在不诉诸重建整个 StatefulWidget
的情况下更改图标颜色的更好解决方案是什么?
感谢您的时间。
答案 0 :(得分:2)
您可以使用 ValueListenableBuilder
小部件。
示例:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'StackOverflow Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'StackOverflow Example'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
ValueNotifier _iconColor = ValueNotifier<Color>(Colors.black);
@override
Widget build(BuildContext context) {
return new GestureDetector(
//Change one of the icon's color using the tap down function
onTapDown: (TapDownDetails details) {
return changeColor(details);
},
child: Scaffold(
appBar: AppBar(
title: Text('Example'),
),
body: Center(
child: Column(children: [
//This widget should be rebuilt
ValueListenableBuilder(
valueListenable: _iconColor,
builder: (ctx, value, child) {
return Icon(
Icons.money,
size: 50,
color: value,
);
}
),
//This icon should not be rebuilt
Icon(
Icons.euro,
size: 50,
color: Colors.black,
),
]),
),
),
);
}
void changeColor(TapDownDetails details) =>
_iconColor.value = Colors.green
}
答案 1 :(得分:1)
如果您一定要使用 StatefulBuilder
,这是实现您的意图的一种方法。
基本上,我们正在存储从 StateSetter
接收到的 StatefulBuilder.builder
class Sample extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return SampleState();
}
}
class SampleState extends State<Sample> {
StateSetter internalSetter;
Color color = Colors.black;
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(title: Text('Sample')),
body: Column(
children: [
GestureDetector(
onTap: () {
setState(() {
color = Colors.deepOrange;
});
},
child: Text('Press'),
),
StatefulBuilder(builder: (context, setter) {
internalSetter = setter;
return Container(
height: 100,
width: 100,
color: color,
);
}),
Undisturbed(),
],
),
);
}
}
class Undisturbed extends StatelessWidget {
@override
Widget build(BuildContext context) {
print("Undisturbed is built");
return Container(
width: 100,
height: 100,
color: Colors.red,
);
}
}