是否可以使用位于窗口小部件树中其他位置的按钮来更改另一个类的状态

时间:2018-05-20 21:05:10

标签: dart flutter

这是我的小部件树。当我在MemberSection课程中按RaisedButton时,我想更改AdminSection课程中的文本小部件。 MemberSectionAdminSection都在HomePage级。

enter image description here

下面是飞镖文件:

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: HomePage(),
    ),
  );
}

class HomePage extends StatelessWidget {
  final int count = 0;

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[MemberSection(count), AdminSection(count)],
      ),
    );
  }
}

class MemberSection extends StatefulWidget {
  MemberSection(this.count);

  final int count;

  @override
  _MemberSectionState createState() => new _MemberSectionState();
}

class _MemberSectionState extends State<MemberSection> {
  @override
  Widget build(BuildContext context) {
    return new Text('${widget.count} member(s)');//I need to change this widget
  }
}

class AdminSection extends StatefulWidget {
  AdminSection(this.count);

  final int count;

  @override
  _AdminSectionState createState() => new _AdminSectionState();
}

class _AdminSectionState extends State<AdminSection> {
  void incrementer() {
    setState(() {
      //widget.count++; //cannt do
    });
  }

  void decrementer() {
    setState(() {
      //widget.count--; //cannt do
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Column(
      children: <Widget>[
        Text('${widget.count} admin(s)'),//Also, I need to change this widget
        ButtonBar(
          children: <Widget>[
            RaisedButton(
              child: Text('add a member'),
              onPressed: incrementer,
            ),
            RaisedButton(
              child: Text('delete a member'),
              onPressed: decrementer,
            ),
          ],
        ),
      ],
    );
  }
}

注意:此示例用于演示我的问题。

我知道我可以在incrementer类中实现decrementerHomePage并将该函数传递给小部件但是根据这种情况无法完成,因为一个RaisedButton小部件位于小部件树的另一侧。

更新

链接的重复问题与我的问题不同,因为我没有在MemberSectionAdminSection实例化

1 个答案:

答案 0 :(得分:1)

是的,这是可能的。

最简单的方法是使用InheritedWidget

您可能记得方法of(context),例如:

MediaQuery.of(context).size
Navigator.of(context).pop()
Theme.of(context).canvasColor

这些是继承的小部件。您在应用中的任何位置使用of(),您可以访问您的主题,因为它们是继承的。使用of方法,您可以在实现窗口小部件树后更改窗口小部件树的状态。

因此,您的示例代码应如下所示:

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: MyApp(),
    ),
  );
}

//this is a newly added stateful widget to use inherited widget
class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int count = 0;

  void incrementer() {
    setState(() {
      count++;
    });
  }

  void decrementer() {
    setState(() {
      count--;
    });
  }

  @override
  Widget build(BuildContext context) {
    return CounterState(
      count: count,
      incrementer: incrementer,
      decrementer: decrementer,
      child: HomePage(),
    );
  }
}

//this is the inherited widget
class CounterState extends InheritedWidget {
  CounterState({Key key, this.count, this.incrementer, this.decrementer, Widget child})
      : super(key: key, child: child);

  final int count;
  final Function incrementer;
  final Function decrementer;

  @override
  bool updateShouldNotify(CounterState oldWidget) {
    return count != oldWidget.count;
  }

  static of(BuildContext context) {
    return context.inheritFromWidgetOfExactType(CounterState);
  }
}

//make below classes stateless(not must but useless)
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          MemberSection(),
          AdminSection()
        ],
      ),
    );
  }
}

class MemberSection extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counterState = CounterState.of(context);
    return new Text('${counterState.count} member(s)');
  }
}

class AdminSection extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counterState = CounterState.of(context);
    return new Column(
      children: <Widget>[
        Text('${counterState.count} admin(s)'),
        ButtonBar(
          children: <Widget>[
            RaisedButton(child: Text('add a member'), onPressed: counterState.incrementer,),
            RaisedButton(child: Text('delete a member'), onPressed: counterState.decrementer,),
          ],
        ),
      ],
    );
  }
}

可以找到一个很棒的教程here