Flutter-通知列内的同级小部件

时间:2019-04-05 20:41:46

标签: mobile flutter observer-pattern flutter-layout

我正在尝试创建一种功能,当我在FlatButton小部件内单击Expanded时,其flex会更改为 2 兄弟姐妹FlatButton的弹性更改为 1

enter image description here

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方法适用于继承的小部件,而不是兄弟姐妹。

我敢肯定有一种干净的方法可以做到这一点。但是我无法动手。

2 个答案:

答案 0 :(得分:1)

这里有另一种方法,将主窗口小部件更改为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),
          ),
        );
      }
    }

答案 1 :(得分:1)

不要尝试保持按钮本身是否处于选中状态。如您所见,很难使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);
        },
      ),
    );
  }
}