Flutter - notify sibling widgets inside Column

与世无争的帅哥 提交于 2019-12-11 17:12:54

问题


I'm trying to create a functionality, where when I click on a FlatButton inside an Expanded widget, its flex changes to 2 and other siblings FlatButtons flex change to 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;
          });
        },
      ),
    );
  }
}

I was trying to find a way, maybe keep track of all of them in an array or something. I searched and found that InheritedWidget approach is for inherited widgets, not siblings.

I'm sure there's a clean way to do it. But just can't get my hands on it.


回答1:


Don't try to keep the state of whether it's selected in the button itself. As you've seen it's difficult to keep the state of 3 buttons in sync. Find a place higher up the widget tree where you can maintain that state once. In this case, it's in your App. Make App stateful so that it can remember the state and then your buttons don't need to remember it. They can be told whether they are selected (big) or unselected (small) in their constructor.

So, how does the button tell the parent that it's now become the selected one? There are various strategies, but they all involve:

  • calling a method that's been passed down
  • calling a method on an InheritedWidget
  • sending a message through a stream
  • etc

Try this:

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);
        },
      ),
    );
  }
}



回答2:


Here you have another way to do that , change your main widget to Stateful and your Button to 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),
          ),
        );
      }
    }


来源:https://stackoverflow.com/questions/55543070/flutter-notify-sibling-widgets-inside-column

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!