我有一个简单的应用程序,其中包含一个按钮(“ Button!”),按下该按钮会使容器(“ Button Pressed!”)出现并消失。我想重构代码,以便拥有MyButton类和MyPopup类,但是我遇到了无法在GestureDetector中调用_setPressed的问题,因此我不知道如何使这种功能起作用。
是否可以以此方式编写代码,或者是否必须一起声明涉及状态的任何内容?
原始内容:
/**
* MyHomePage stuff
*/
class MyHomePage extends StatefulWidget {
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool pressed = false;
Widget build(BuildContext context) {
return Column(
children: <Widget>[
GestureDetector(
onTap: () {
_setPressed();
},
child: Container(
height: 36.0,
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Colors.lightGreen[500],
),
child: Center(
child: Text('Button!'),
),
),
),
Visibility( visible: pressed,
child: Container (
height: 36.0,
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(0.5),
color: Colors.amber[500],
),
child: Center(
child: Text("Button Pressed!"),
),
)),
],
);
}
void _setPressed() {
setState(() {
pressed = !pressed;
});
}
}
/* end MyHomePage */
或多或少我想要它看起来像:
/**
* MyHomePage stuff
*/
class MyHomePage extends StatefulWidget {
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool pressed = false;
Widget popup = MyPopup();
Widget build(BuildContext context) {
return Column(
children: <Widget>[
MyButton(),
MyPopup(),
],
);
}
}
/* end MyHomePage */
/**
* Popup stuff
*/
class MyPopup extends StatefulWidget {
_MyPopupState createState() => _MyPopupState();
}
class _MyPopupState extends State<MyPopup> {
bool pressed = false;
Widget build(BuildContext) {
return Visibility(
visible: pressed,
child: Container(
height: 36.0,
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(0.5),
color: Colors.amber[500],
),
child: Center(
child: Text("Button Pressed!"),
),
));
}
void setPressed() {
setState(() {
pressed = !pressed;
});
}
}
/* end popup */
/**
* MyButton stuff
*/
class MyButton extends StatelessWidget {
Widget build (BuildContext context) {
GestureDetector(
onTap: () {
popup.setPressed();
},
child: Container(
height: 36.0,
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Colors.lightGreen[500],
),
child: Center(
child: Text('Button!'),
),
),
);
}
}
/* end MyButton */
/**
* MyHomePage stuff
*/
class MyHomePage extends StatefulWidget {
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool pressed = false;
Widget popup = MyPopup();
Widget build(BuildContext context) {
return MultiProvider(
provider: [
ChangeNotifierProvider<Status>.value(
value: Status(),
)],
child: Column(
children: <Widget>[
MyButton(),
MyPopup(),
],),
);
}
}
/* end MyHomePage */
/**
* Popup stuff
*/
class MyPopup extends StatelessWidget {
Widget build(BuildContext) {
final _status = Provider.of<Status>(context);
return Visibility(
visible: status.isDisplayed,
child: Container(
height: 36.0,
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(0.5),
color: Colors.amber[500],
),
child: Center(
child: Text("Button Pressed!"),
),
));
}
void setPressed() {
status.setIsDisplayed(!status.isDisplayed);
}
}
/* end popup */
/**
* MyButton stuff
*/
class MyButton extends StatelessWidget {
Widget build (BuildContext context) {
final _status = Provider.of<Status>(context);
GestureDetector(
onTap: () {
status.setIsDisplayed(!status.isDisplayed);
},
child: Container(
height: 36.0,
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Colors.lightGreen[500],
),
child: Center(
child: Text('Button!'),
),
),
);
}
}
/* end MyButton */
class Status extends ChangeNotifier {
bool _isDisplayed = false;
bool get isDisplayed => _isDisplayed;
void setIsDisplayed(bool value) {
_isDisplayed = value;
notifyListeners();
}
您必须安装提供程序库,该库是Flutter的状态管理库。希望这会有所帮助。
我认为您应该在主类中保留显示弹出窗口的功能。我的意思是,您可以有两个单独的类来呈现两个小部件,即Button
类在屏幕中呈现button
和Popup
类在屏幕中呈现Container
。
然后您应该基于轻击操作显示弹出窗口,应将此逻辑保留在主类中。
这里是代码:
class MyHomePage extends StatefulWidget {
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool pressed = false;
Widget build(BuildContext context) {
return Column(
children: <Widget>[
GestureDetector(
onTap: () {
_setPressed();
},
child: MyButton(),
),
MyPopup(isPressed: pressed),
],
);
}
void _setPressed() {
setState(() {
pressed = !pressed;
});
}
}
class MyButton extends StatelessWidget {
Widget build (BuildContext context) {
return Container(
height: 36.0,
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Colors.lightGreen[500],
),
child: Center(
child: Text('Button!'),
),
);
}
}
class MyPopup extends StatefulWidget {
bool isPressed;
MyPopup({this.isPressed});
_MyPopupState createState() => _MyPopupState();
}
class _MyPopupState extends State<MyPopup> {
Widget build(BuildContext context) {
return Visibility(
visible: widget.isPressed,
child: Container(
height: 36.0,
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(0.5),
color: Colors.amber[500],
),
child: Center(
child: Text("Button Pressed!"),
),
)
);
}
}
最简单的解决方案是处理主页中的状态,您可以将onTap函数传递给自定义按钮,并在点击时设置状态,然后通过将按下的变量传递给popUp来进行更新。
import 'package:flutter/material.dart';
/**
* MyHomePage stuff
*/
class MyHomePage extends StatefulWidget {
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool pressed = false;
Widget build(BuildContext context) {
return Column(
children: <Widget>[
MyButton(
onTap: () {
setState(() {
pressed = !pressed;
});
},
),
MyPopup(
pressed: pressed,
),
],
);
}
}
/* end MyHomePage */
/**
* Popup stuff
*/
class MyPopup extends StatefulWidget {
final bool pressed;
const MyPopup({@required this.pressed});
_MyPopupState createState() => _MyPopupState();
}
class _MyPopupState extends State<MyPopup> {
Widget build(BuildContext) {
return Visibility(
visible: widget.pressed,
child: Container(
height: 36.0,
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(0.5),
color: Colors.amber[500],
),
child: Center(
child: Text("Button Pressed!"),
),
));
}
}
/* end popup */
/**
* MyButton stuff
*/
class MyButton extends StatelessWidget {
final Function() onTap;
const MyButton({@required this.onTap});
Widget build(BuildContext context) {
GestureDetector(
onTap: this.onTap,
child: Container(
height: 36.0,
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Colors.lightGreen[500],
),
child: Center(
child: Text('Button!'),
),
),
);
}
}
/* end MyButton */
另一个解决方案是使用状态管理,例如BLOC或Provider或MobX...。只需您可以通过任何小部件中发生的更改通知任何小部件。