使用setState时可以制作小部件的模块化类吗?

问题描述 投票:0回答:3

我有一个简单的应用程序,其中包含一个按钮(“ 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 */

Button PressedButton Pressed again

flutter flutter-layout
3个回答
0
投票
/**
 * 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的状态管理库。希望这会有所帮助。


0
投票

我认为您应该在主类中保留显示弹出窗口的功能。我的意思是,您可以有两个单独的类来呈现两个小部件,即Button类在屏幕中呈现buttonPopup类在屏幕中呈现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!"),
        ),
      )
    );
  }
}

0
投票

最简单的解决方案是处理主页中的状态,您可以将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...。只需您可以通过任何小部件中发生的更改通知任何小部件。

© www.soinside.com 2019 - 2024. All rights reserved.