Flutter - уведомлять родственные виджеты внутри столбца - PullRequest
0 голосов
/ 05 апреля 2019

Я пытаюсь создать функциональность, в которой, когда я нажимаю FlatButton внутри виджета Expanded, его flex меняется на 2 и другие гибкие изменения FlatButton sна 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 ]

1 голос
/ 06 апреля 2019

Не пытайтесь сохранить состояние того, выбран ли он в самой кнопке.Как вы уже видели, сложно синхронизировать состояние трех кнопок.Найдите место выше дерева виджетов, где вы сможете поддерживать это состояние один раз.В этом случае это в вашем приложении.Сделайте приложение с состоянием, чтобы оно могло помнить состояние, и тогда ваши кнопки не должны помнить его.Им можно сказать, выбран ли (большой) или невыбранный (маленький) в своем конструкторе.

Итак, как кнопка сообщает родителю, что она теперь стала выбранной?Существуют различные стратегии, но все они включают в себя:

  • вызов метода, который был передан
  • вызов метода 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);
        },
      ),
    );
  }
}
1 голос
/ 06 апреля 2019

Здесь у вас есть другой способ сделать это: замените основной виджет на 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),
          ),
        );
      }
    }
.
...