【问题标题】:How to access a widgets state from a stateful widget class Flutter如何从有状态小部件类 Flutter 访问小部件状态
【发布时间】:2021-05-19 15:47:44
【问题描述】:

对不起,如果这已经在其他地方得到了回答,但我是 Flutter 的新手。我在下面的小部件中有一个 toString 方法,它需要访问小部件的状态以输出字符串。小部件是一张卡片,包含一个文本字段和其他与文本相关的操作。要存储有关用户在卡片中输入内容的信息,我需要将所有数据放入 toString 返回的一个字符串中。

class TextCard extends StatefulWidget {
  _TextCardState cardState = _TextCardState();
  TextCard({String text = ""}) {
    cardState.textController.text = text;

  }
  @override
  _TextCardState createState() => cardState = new _TextCardState();

  String toString({DiagnosticLevel minLevel = DiagnosticLevel.debug}) {
    return delimiter2 +
        "TextCard" +delimiter3 +
        cardState.getText() +
        delimiter3 +
        (cardState.center.toString()) +
        delimiter3 +
        cardState.bold.toString() +
        delimiter3 +
        cardState.italic.toString() +
        delimiter3 +
        cardState.size.toString() +

        delimiter2;
  }
}

小部件还接受一个字符串值来设置文本字段在下面状态的初始值

class _TextCardState extends State<TextCard> {
  double size = 18;
  bool bold = false;
  bool italic = false;
  bool center = false;

  var textController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Container(
        height: _cardSizeY,
        width: _cardSizeX,
        child: Card(
            elevation: _elevation,
            child: Center(
                child: Column(children: [
              ListTile(leading: Icon(Icons.text_fields)),
              ButtonBar(children: [
                IconButton(
                  icon: Icon(Icons.format_bold),
                  onPressed: () {
                    updateText(size, !bold, italic, center);
                  },
                ),
                IconButton(
                  icon: Icon(Icons.format_italic),
                  onPressed: () {
                    updateText(size, bold, !italic, center);
                  },
                ),
                Slider(
                    value: size,
                    max: 80,
                    min: 1,
                    onChanged: (size) {
                      updateText(size, bold, italic, center);
                    })
              ]),
              TextField(
                  maxLines: null,
                  style: TextStyle(
                      fontWeight: (bold) ? FontWeight.bold : FontWeight.normal,
                      fontStyle: (italic) ? FontStyle.italic : FontStyle.normal,
                      fontSize: size),
                  textAlign: (center) ? TextAlign.center : TextAlign.start,
                  controller: textController,
                  decoration: InputDecoration(
                      border: OutlineInputBorder(
                          borderSide: BorderSide(color: Colors.grey),
                          borderRadius: BorderRadius.all(Radius.circular(10)))))
            ]))));
  }

  void updateText(double size, bool bold, bool italic, bool center) {
    setState(() {
      this.size = size;
      this.bold = bold;
      this.italic = italic;
      this.center = center;
    });
  }

  String getText() {
    return textController.value.text;
  }
}

当我运行此代码时,我收到错误,创建状态函数返回了一个旧的无效状态实例。 我已经考虑将文本控制器放入 _TextCardState() 类,但我无法更改 TextField 的初始值。

【问题讨论】:

    标签: flutter textfield statefulwidget


    【解决方案1】:

    所以我知道你在这里尝试做什么,但是有更好的方法可以从类外部访问文本字段的值。

    我建议使用状态管理解决方案,而不是从外部访问您的 toString 方法,该方法依赖于私有状态类的值,这将使这种方式更容易和更清洁。您还可以更轻松地访问所有需要的变量。

    您在此处所做的事情不是应该做的事情,这就是您收到这些状态错误的原因。

    _TextCardState cardState = _TextCardState();
    

    这是一种使用GetX 的方法。

    您的所有数据都将存在于下面的 GetX Controller 类中,并将用于您现在无状态的 TextCard 小部件。

    class Controller extends GetxController {
      var textController = TextEditingController();
      String textfieldString = '';
      double size = 18;
      bool bold = false;
      bool italic = false;
      bool center = false;
    
      @override
      void onInit() {
        super.onInit();
        // updates the value of textfieldString anytime the user types
        textController.addListener(() {
          textfieldString = textController.text;
          debugPrint(textController.text);
        });
      }
    
      // this method lives in this class and is accessible from anywhere. The
    // only thing not clear is what delimier2 is and where it comes from
    // toString is not a good name because that is an overridden method that lives 
    // in most Dart classes
    
       String buildString({DiagnosticLevel minLevel = DiagnosticLevel.debug}) {
        return delimiter2 +
            "TextCard" +delimiter3 +
            textfieldString +
            delimiter3 +
            (center.toString()) +
            delimiter3 +
            bold.toString() +
            delimiter3 +
            italic.toString() +
            delimiter3 +
            size.toString() +
    
            delimiter2;
      }
    
    // single responsibility methods as opposed to firing one big function 
    // multiple times when its only affecting one variable
    
      void toggleBold() {
        bold = !bold;
        update();
      }
    
      void toggleItalic() {
        italic = !italic;
        update();
      }
    
      void toggleCenter() {
        center = !center;
        update();
      }
    
      void updateSize(double sliderValue) {
        size = sliderValue;
        update();
      }
    }
    
    

    在运行您的应用程序之前将其放在您的 main 中。只要在您尝试访问控制器之前,就可以在任何地方完成。

      Get.put(Controller()); 
    

    这是你的TextCard 小部件

    class TextCard extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        final controller =
            Get.find<Controller>(); // finding the initalized controller
        return Container(
          height: _cardSizeY,
          width: _cardSizeX,
          child: Card(
            elevation: 20,
            child: Center(
              child: Column(
                children: [
                  ListTile(leading: Icon(Icons.text_fields)),
                  ButtonBar(children: [
                    IconButton(
                      icon: Icon(Icons.format_bold),
                      onPressed: () {
                        controller.toggleBold();
                      },
                    ),
                    IconButton(
                      icon: Icon(Icons.format_italic),
                      onPressed: () {
                        controller.toggleItalic(); // accessing method via controller
                      },
                    ),
                    // GetBuilder rebuilds children when value of controller variable changes
                    GetBuilder<Controller>(
                      builder: (_) {
                        return Slider(
                            value: controller
                                .size, // accessing size in other class via controller
                            max: 80,
                            min: 1,
                            onChanged: (value) {
                              controller.updateSize(value); 
                            });
                      },
                    )
                  ]),
                  GetBuilder<Controller>(
                    builder: (_) {
                      return TextField(
                        maxLines: null,
                        style: TextStyle(
                            fontWeight: (controller.bold)
                                ? FontWeight.bold
                                : FontWeight.normal,
                            fontStyle: (controller.italic)
                                ? FontStyle.italic
                                : FontStyle.normal,
                            fontSize: controller.size),
                        textAlign: (controller.center)
                            ? TextAlign.center
                            : TextAlign.start,
                        controller: controller.textController,
                        decoration: InputDecoration(
                          border: OutlineInputBorder(
                            borderSide: BorderSide(color: Colors.grey),
                            borderRadius: BorderRadius.all(
                              Radius.circular(10),
                            ),
                          ),
                        ),
                      );
                    },
                  )
                ],
              ),
            ),
          ),
        );
      }
    }
    

    因此,无论您在应用程序中的哪个位置需要该功能,都可以找到控制器并获得您的价值。

    final controller = Get.find<Controller>():
    final newString = controller.buildString();
    

    这将更容易并且使用更少的内存,因为TextCard 现在是无状态的。

    【讨论】:

      猜你喜欢
      • 2018-09-01
      • 1970-01-01
      • 2019-09-23
      • 1970-01-01
      • 2021-08-27
      • 2021-02-16
      • 2021-06-11
      • 2019-10-06
      • 1970-01-01
      相关资源
      最近更新 更多