从appbar.actions

时间:2019-06-03 14:03:51

标签: flutter widget state

我在理解如何从动态AppBar操作按钮更新窗口小部件时遇到问题。这是我为了说明问题而更改的“新应用”。 在生产应用程序中,我需要根据抽屉式脚手架主体中当前显示的页面小部件显示某些操作按钮。

class ActionWidget extends StatefulWidget {
  final action = IconButton(
    icon: Icon(Icons.add),
    onPressed: () {
      //state.action();
    },
  );

  @override
  State<StatefulWidget> createState() {
    return ActionWidgetState();
  }
}

class ActionWidgetState extends State<ActionWidget> {
  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text(
            'You have pushed the button this many times:',
          ),
          Text(
            '$_counter',
            style: Theme.of(context).textTheme.display1,
          ),
        ],
      ),
    );
  }

  void action() {
    setState(() {
      _counter++;
    });
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    final actionWidget = ActionWidget();
    return Scaffold(
      appBar: AppBar(
        actions: <Widget>[
          actionWidget.action,
        ],
      ),
      body: actionWidget,
    );
  }
}

触发onPressed动作时如何更新小部件状态?我目前的解决方法是这种方法(显然不是最佳选择)

class MeasurePage extends PageWidget {
  MeasurePageState state;

  @override
  State createState() => state = MeasurePageState();
...
    onPressed: () {
      state.search(context);
    },

编辑。另一个带有抽屉菜单的示例可以更好地演示该问题

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final actionWidgets = List<ActionWidget>.from([ActionWidget(1), ActionWidget(2)]);
  var selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: actionWidgets[selectedIndex],
      appBar: AppBar(
        actions: <Widget>[actionWidgets[selectedIndex].getAction()],
      ),
      drawer: Drawer(
        child: Column(
          children: <Widget>[
            Container(
              height: 33,
            ),
            FlatButton(
              child: Text('instance 1'),
              onPressed: () {
                Navigator.of(context).pop(); // close the drawer
                this.setState(() {
                  selectedIndex = 0;
                });
              },
            ),
            FlatButton(
              child: Text('instance 2'),
              onPressed: () {
                Navigator.of(context).pop(); // close the drawer
                this.setState(() {
                  selectedIndex = 1;
                });
              },
            ),
          ],
        ),
      ),
    );
  }
}

class ActionWidget extends StatefulWidget {
  final actionWidgetState;
  final index;
  ActionWidget(this.index)
      : this.actionWidgetState = ActionWidgetState(index),
        super(key: GlobalKey());

  Widget getAction() {
    return IconButton(
      icon: Icon(Icons.add),
      onPressed: () {
        actionWidgetState.actionCallback();
      },
    );
  }

  @override
  State<StatefulWidget> createState() => actionWidgetState;
}

class ActionWidgetState extends State<ActionWidget> {
  int _counter = 0;
  VoidCallback actionCallback;
  final index;

  ActionWidgetState(this.index);

  @override
  Widget build(BuildContext context) {
    actionCallback = () => action();
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text(
            'Page ${widget.index}',
          ),
          Text(
            'State $index',
          ),
          Text(
            'You have pushed the button this many times:',
          ),
          Text(
            '$_counter',
            style: Theme.of(context).textTheme.display1,
          ),
        ],
      ),
    );
  }

  void action() {
    setState(() {
      _counter++;
    });
  }
}

2 个答案:

答案 0 :(得分:0)

您没有正确使用StatefulWidget。您在StatefulWidget中调用的操作按钮应该只是按钮本身,然后可以将要在状态中更改的数据传递给statefulWidget类。然后,在State类中,您可以在其中覆盖didUpdateWidget和setState。也许经历以下过程:https://flutter.dev/docs/development/data-and-backend/state-mgmt/intro

答案 1 :(得分:0)

输出:

enter image description here

将您的ActionWidget更改为此。

class ActionWidget extends StatefulWidget {
  static final ActionWidgetState actionWidgetState = ActionWidgetState();
  final action = IconButton(
    icon: Icon(Icons.add),
    onPressed: () {
      actionWidgetState.action();
    },
  );

  @override
  State<StatefulWidget> createState() {
    return actionWidgetState;
  }
} 

完整代码:

void main() => runApp(MaterialApp(home: MyHomePage()));

class ActionWidget extends StatefulWidget {
  static final ActionWidgetState actionWidgetState = ActionWidgetState();
  final action = IconButton(
    icon: Icon(Icons.add),
    onPressed: () => actionWidgetState.action(),
  );

  @override
  State<StatefulWidget> createState() => actionWidgetState;
}

class ActionWidgetState extends State<ActionWidget> {
  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text('You have pushed the button this many times:'),
          Text('$_counter', style: Theme.of(context).textTheme.display1),
        ],
      ),
    );
  }

  void action() => setState(() => _counter++);
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    final actionWidget = ActionWidget();
    return Scaffold(
      appBar: AppBar(actions: <Widget>[actionWidget.action]),
      body: actionWidget,
    );
  }
}