Flutter - 通知 Column 内的兄弟小部件

Flutter - notify sibling widgets inside Column

我正在尝试创建一个功能,当我点击 Expanded 小部件内的 FlatButton 时,它的 flex 变为 2 和其他兄弟姐妹 FlatButton 灵活更改为 1

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Directionality(
      textDirection: TextDirection.ltr,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          new ButtonWidget(text: "Hello",selectedColor: Colors.yellow),
          new ButtonWidget(text: "This is", selectedColor: Colors.red),
          new ButtonWidget(text: "Button", selectedColor: Colors.blue),
        ],
      ),
    );
  }
}

class ButtonWidget extends StatefulWidget {
  String text;
  MaterialColor selectedColor;

  ButtonWidget({this.text, this.selectedColor});

  createState() =>
      ButtonState(text: this.text, selectedColor: this.selectedColor);
}

class ButtonState extends State<ButtonWidget> {
  String text;
  MaterialColor selectedColor;
  int _flexValue = 1;

  ButtonState({this.text, this.selectedColor});

  @override
  Widget build(BuildContext context) {
    return Expanded(
      flex: _flexValue,
      child: FlatButton(
        color: selectedColor,
        child: Text(
          text,
        ),
        onPressed: () {
          setState(() {
            _flexValue = 2;
          });
        },
      ),
    );
  }
}

我试图找到一种方法,也许可以在数组或其他东西中跟踪所有这些。我搜索并发现 InheritedWidget 方法适用于继承的小部件,而不是兄弟。

我相信有一种干净的方法可以做到这一点。但是就是拿不到。

这里有另一种方法,将主小部件更改为 Stateful,将按钮更改为 Stateless

 class MyApp2 extends StatefulWidget {
      @override
      _MyApp2State createState() => _MyApp2State();
    }

    class _MyApp2State extends State<MyApp2> {
      int selectedIndex = -1;

      onIndexChanged(int index){
              setState(() {
                selectedIndex = index;
              });
      }

      @override
      Widget build(BuildContext context) {
        return Directionality(
          textDirection: TextDirection.ltr,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              new ButtonWidget(
                index: 1,
                text: "Hello",
                selectedColor: Colors.yellow,
                selectedIndex: selectedIndex,
                onChanged: onIndexChanged
              ),
              new ButtonWidget(
                  index: 2,
                  text: "This is",
                  selectedColor: Colors.red,
                  selectedIndex: selectedIndex,
                  onChanged: onIndexChanged),
              new ButtonWidget(
                  index: 3,
                  text: "Button",
                  selectedColor: Colors.blue,
                  selectedIndex: selectedIndex,
                  onChanged: onIndexChanged),
            ],
          ),
        );
      }
    }

    class ButtonWidget extends StatelessWidget {
      final String text;
      final MaterialColor selectedColor;
      final int index;
      final ValueChanged<int> onChanged;
      final int selectedIndex;
      ButtonWidget(
          {this.text,
          this.selectedColor,
          this.index,
          this.onChanged,
          this.selectedIndex});

      @override
      Widget build(BuildContext context) {
        return Expanded(
          flex: selectedIndex != null && selectedIndex == index ? 2 : 1,
          child: FlatButton(
            color: selectedColor,
            child: Text(
              text,
            ),
            onPressed: () => onChanged(index),
          ),
        );
      }
    }

不要试图在按钮本身中保持是否被选中的状态。如您所见,很难使 3 个按钮的状态保持同步。在小部件树上找到一个可以维护该状态一次的位置。在这种情况下,它在您的应用程序中。使应用程序有状态,以便它可以记住状态,然后您的按钮就不需要记住它。可以在构造函数中告知它们是被选中(大)还是未被选中(小)。

那么,按钮如何告诉父级它现在已被选中?有多种策略,但它们都涉及:

  • 调用传递下来的方法
  • 在 InheritedWidget 上调用方法
  • 通过流发送消息
  • 等等

试试这个:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  State createState() => MyAppState();
}

class MyAppState extends State<MyApp> {
  int selected = 0;

  @override
  Widget build(BuildContext context) {
    return Directionality(
      textDirection: TextDirection.ltr,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          ButtonWidget(0, flexValue(0), 'Hello', Colors.yellow, onClick),
          ButtonWidget(1, flexValue(1), 'This is', Colors.red, onClick),
          ButtonWidget(2, flexValue(2), 'Button', Colors.blue, onClick),
        ],
      ),
    );
  }

  void onClick(int i) {
    setState(() {
      selected = i;
    });
  }

  int flexValue(int index) => (index == selected) ? 2 : 1;
}

class ButtonWidget extends StatelessWidget {
  ButtonWidget(this.index, this._flexValue, this.text, this.selectedColor,
      this.notifyClick);

  final Function notifyClick;
  final int index;
  final int _flexValue;
  final String text;
  final MaterialColor selectedColor;

  @override
  Widget build(BuildContext context) {
    return Expanded(
      flex: _flexValue,
      child: FlatButton(
        color: selectedColor,
        child: Text(
          text,
        ),
        onPressed: () {
          notifyClick(index);
        },
      ),
    );
  }
}