Flutter 从相关小部件更改状态 class

Flutter change state from related widget class

让我们假设一个class“SpecialButton”及其状态-Class“SpecialButtonState”

class SpecialButton extends StatefulWidget {
  bool active = false;
  SpecialButton({Key key}) : super(key: key);
  @override
  SpecialButtonState createState() => SpecialButtonState();
}

class SpecialButtonState extends State<SpecialButton> {
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        decoration:
            BoxDecoration(color: this.widget.active ? COLOR_1 : COLOR_2),
        child: null);
  }
}

在父窗口小部件中,我管理了几个这样的按钮。因此,我想给他们分配一个状态。我尝试的解决方案是在 SpecialButton class 中引入一个标志“active”,我可以很容易地从父窗口小部件将其设置为 true 或 false。然后我可以在状态 class 的构建函数中使用它来为按钮着色。不幸的是,这并不完全有效,因为它不会立即更新按钮(它需要某种状态更新,例如通过将鼠标悬停在元素上)。

我的第二个想法是将此标志作为 SpecialButtonState 的适当状态引入 class

class SpecialButton extends StatefulWidget {
  SpecialButton({Key key}) : super(key: key);
  @override
  SpecialButtonState createState() => SpecialButtonState();
}

class SpecialButtonState extends State<SpecialButton> {
  bool active;

  @override
  void initState() {
    super.initState();
    this.active = false;
  }

  activate() {
    this.setState(() {
      active = true;
    });
  }

  deactivate() {
    this.setState(() {
      active = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        decoration: BoxDecoration(color: this.active ? COLOR_1 : COLOR_2),
        child: null);
  }
}

据我所知,这是使用 flutter 的正确方法,但似乎我无法从 SpecialButton Class 或父级 Class 包含小部件。

所以我的问题是:如何(直接或间接通过函数)从相应的 StatefulWidget Class 或包含它的 Parent Widget 修改 State?

在 Stack Overflow 上已经有一些类似的问题,我可以在其中找到关于使用或不使用全局键的提示,我发现这种行为具有误导性。此外,由于 flutter 的快速发展,它们可能已经过时,所以我再次针对这个确切的用例问这个(类似的)问题。

编辑:我忘了提到这个标志在创建后将被更改是至关重要的,因此它将在其生命周期内多次更改。这需要重新绘制小部件。

SpecialButton 情况下,没有必要使用有状态小部件。您可以使用无状态小部件和键处理 active 标志。示例代码:


class SomeParent extends StatefulWidget {
  const SomeParent({Key key}) : super(key: key);

  @override
  State<SomeParent> createState() => SomeParentState();
}

class SomeParentState extends State<SomeParent> {
  bool _button1IsActive = false;
  bool _button2IsActive = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          SpecialButton(
            key: UniqueKey(),
            active: _button1IsActive,
          ),
          SizedBox(height: 8),
          SpecialButton(
            key: UniqueKey(),
            active: _button2IsActive,
          ),
          SizedBox(height: 16),
          TextButton(
            child: Text('Toggle button 1'),
            onPressed: () {
              setState(() {
                _button1IsActive = !_button1IsActive;
              });
            },
          ),
          SizedBox(height: 8),
          TextButton(
            child: Text('Toggle button 2'),
            onPressed: () {
              setState(() {
                _button2IsActive = !_button2IsActive;
              });
            },
          ),
        ],
      ),
    );
  }
}

class SpecialButton extends StatelessWidget {
  final bool active;

  const SpecialButton({Key key, this.active = false}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 40,
      width: 40,
      decoration: BoxDecoration(color: active ? Colors.red : Colors.blue),
    );
  }
}

SomeParent是我的幻想,只是举个例子。不知道你的 parent 是什么。 键在这里很重要。他们告诉小部件树何时应该重建具有相同类型(例如SpecialButton)的特定小部件。

请尝试此方法,它应该有效。

正如 nvoigt 所说,您的按钮甚至可以是无状态小部件,但它们的父级应该是有状态的,您应该为它们提供相应的值。例如:

import 'package:flutter/material.dart';

class Parent extends StatefulWidget {
  @override
  _ParentState createState() => _ParentState();
}

class _ParentState extends State<Parent> {
  bool isEnabled = false;
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        StateLessButton1(isEnabled: isEnabled),
        StateLessButton1(isEnabled: !isEnabled),
        FloatingActionButton(onPressed: (){
          setState(() {
                      isEnabled = !isEnabled;
                    });
        })
      ],
      
    );
  }
}

现在这取决于您何时更改该值。如果您想在按钮内更改它,我建议您使用 class 和 ChangeNotifier 以及其中的一个函数来更改值。否则我建议不要将你的树分成多个文件