Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 颤振-自定义小部件-如何从_Flutter_Widget - Fatal编程技术网

Flutter 颤振-自定义小部件-如何从

Flutter 颤振-自定义小部件-如何从,flutter,widget,Flutter,Widget,这是我遇到的问题的一个简单例子。给出以下示例,如何从类外获取“counter”的值 class Counter extends StatefulWidget { @override _CounterState createState() => _CounterState(); } class _CounterState extends State<Counter> { int counter = 0; void increaseCount() { se

这是我遇到的问题的一个简单例子。给出以下示例,如何从类外获取“counter”的值

class Counter extends StatefulWidget {
  @override
  _CounterState createState() => _CounterState();
}

class _CounterState extends State<Counter> {
  int counter = 0;
  void increaseCount() {
    setState(() => this.counter++);
    print("New count = $counter");
  }

  Widget build(context) {
    return new RaisedButton(
      onPressed: increaseCount,
      child: new Text('Tap To Add'),
    );
  }
}
类计数器扩展StatefulWidget{
@凌驾
_CounterState createState()=>\u CounterState();
}
类_countstate扩展状态{
int计数器=0;
无效增量计数(){
setState(()=>this.counter++);
打印(“新计数=$计数器”);
}
小部件构建(上下文){
返回新的RaisedButton(
onPressed:增加计数,
子项:新文本(“点击添加”),
);
}
}

在flatter中,您通常要做的是传递回调函数,在该函数中您可以传递所需的值,例如

class Counter extends StatefulWidget {
  // you can use a callback function
  final ValueSetter<int> callback;

  Counter({this.callback});

  @override
  _CounterState createState() => _CounterState();
}

class _CounterState extends State<Counter> {
  int counter = 0;
  void increaseCount() {
    setState(() => this.counter++);
    print("New count = $counter");
    // Here you can pass the value
    widget.callback(this.counter);
  }

  Widget build(context) {
    return new RaisedButton(
      onPressed: increaseCount,
      child: new Text('Tap To Add'),
    );
  }
}
这是我所知道的最简单的方法,也可以使用其他一些模式,如bloc或其他模式。

希望能有所帮助。

您可以使用如下GlobalKey:

类计数器扩展StatefulWidget{
@凌驾
最终globalKey=globalKey();
@凌驾
_CounterState createState()=>\u CounterState();
}
类_countstate扩展状态{
int计数器=0;
无效增量计数(){
设置状态(()=>计数器++);
打印(“新计数=$计数器”);
}
@凌驾
小部件构建(上下文){
返回上升按钮(
onPressed:增加计数,
子项:文本(“点击添加”),
);
}
}
然后按如下方式访问计数器:

计数器计数器=计数器();
int count=counter.globalKey.currentState.counter;
警告:这是不推荐的

您正在从一个简单的、包含的状态过渡到多个小部件之间共享的状态。有几种更好的方法来解决这个问题。有关更多信息和更好的解决问题的方法,请访问。

这只是一个示例(概念验证),用于演示我想要实现的目标。我只是想让小部件存储它的值,并在我需要时将其提供给我(即更新数据)。另一种选择是由主程序存储值,但我认为这并不理想

以下内容似乎有效。为了简单地获得计数器的值,我似乎要做很多事情。我希望有一个更简单的方法。代码如下:

import 'package:flutter/material.dart';
import 'counterWithState.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  CounterWithState _counterWithState =
      CounterWithState(iCounter: 0, isAllowedChange: true);
  FloatingActionButton _fab;
  final _scaffoldKey = GlobalKey<ScaffoldState>();
  @override
  void initState() {
    super.initState();
    _fab = FloatingActionButton(
      onPressed: _showSnackbar,
      tooltip: 'Press to show Counter',
      child: Icon(Icons.info),
    );
  }

  _showSnackbar() {
    _scaffoldKey.currentState.showSnackBar(SnackBar(
        backgroundColor: Colors.blue,
        content:
            Text("Current value of Counter is ${_counterWithState.iCounter}")));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            _counterWithState.getCounterWidget(),
          ],
        ),
      ),
      floatingActionButton: _fab,
    );
  }
}
import 'package:flutter/material.dart';
import 'counterWithState.dart';

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

class MyApp extends StatelessWidget {
  final String sTitle = 'Flutter Counter-With-State Demo';
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: sTitle,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: sTitle),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  CounterWithState _counterWithState;
  FloatingActionButton _fab;
  int _iCounterOriginal = 99;
  RaisedButton _raisedButton;
  SizedBox _sizedBox;
  final _scaffoldKey = GlobalKey<ScaffoldState>();

  @override
  void initState() {
    super.initState();
    _fab = FloatingActionButton(
      onPressed: _showSnackbar,
      tooltip: 'Press to show Counter',
      child: Icon(Icons.info),
    );
    _raisedButton = RaisedButton(
        child: const Text('Update'),
        color: Theme.of(context).accentColor,
        elevation: 4.0,
        splashColor: Colors.blueGrey,
        onPressed: () {
          _iCounterOriginal = _counterWithState.iCounter;
          _counterWithState = null;
          _getCounterWithState(context);
          setState(() {});
        });
    _sizedBox = SizedBox(height: _raisedButton.height);
  }

  fnCounterChanged(int iCounter) {
    setState(() {});
  }

  _showSnackbar() {
    _scaffoldKey.currentState.showSnackBar(SnackBar(
        backgroundColor: Colors.blue,
        content:
            Text("Current value of Counter is ${_counterWithState.iCounter}")));
  }

  @override
  Widget build(BuildContext context) {
    _counterWithState = _counterWithState != null
        ? _counterWithState
        : _getCounterWithState(context);
    return Scaffold(
      key: _scaffoldKey,
      appBar: AppBar(
        title: Text(widget.title),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            _counterWithState.getCounterWidget(),
            _getUpdateButton(context),
          ],
        ),
      ),
      floatingActionButton: _fab,
    );
  }

  Widget _getUpdateButton(BuildContext context) {
    return _counterWithState == null ||
            _counterWithState.iCounter == _iCounterOriginal
        ? _sizedBox
        : _raisedButton;
  }

  CounterWithState _getCounterWithState(context) {
    if (_counterWithState == null)
      _counterWithState = CounterWithState(
          iCounter: _iCounterOriginal,
          isAllowedChange: true,
          fnNotifyChange: fnCounterChanged);
    return _counterWithState;
  }
}
导入“包装:颤振/材料.省道”;
导入“计数器状态.省道”;
void main()=>runApp(MyApp());
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“颤振演示”,
主题:主题数据(
主样本:颜色。蓝色,
),
主页:MyHomePage(标题:“颤振演示主页”),
);
}
}
类MyHomePage扩展StatefulWidget{
MyHomePage({Key,this.title}):超级(Key:Key);
最后的字符串标题;
@凌驾
_MyHomePageState createState()=>\u MyHomePageState();
}
类_MyHomePageState扩展状态{
抗衡状态=
计数器状态(i计数器:0,isAllowedChange:true);
浮动操作按钮_fab;
最终_scaffoldKey=GlobalKey();
@凌驾
void initState(){
super.initState();
_fab=浮动操作按钮(
按下按钮:_showSnackbar,
工具提示:“按此键可显示计数器”,
子:图标(Icons.info),
);
}
_showSnackbar(){
_scaffoldKey.currentState.showSnackBar(SnackBar(
背景颜色:Colors.blue,
内容:
Text(“计数器的当前值为${u counterWithState.iCounter}”);
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
钥匙:_scaffoldKey,
appBar:appBar(
标题:文本(widget.title),
),
正文:中(
子:列(
mainAxisAlignment:mainAxisAlignment.center,
儿童:[
_counterWithState.getCounterWidget(),
],
),
),
浮动操作按钮:_fab,
);
}
}
导入“包装:颤振/材料.省道”;
阶级对抗状态{
国际货币基金组织;
CounterWithStateInternal _CounterWithStateInternal;
fnDataChanged(int iNewCounter){
_i计数器=不计数器;
debugPrint(“CounterWithState:New value=$\u iCounter”);
}
CounterWithStateInternalGetCounterWidget(){
返回(内部状态);;
}
计数器状态({@required iCounter,@required bool isAllowedChange}){
_i计数器=i计数器;
_counterWithStateInternal=counterWithStateInternal(
GlobalKey(),this.\u i计数器,isAllowedChange,fnDataChanged);
}
获取iCounter=>\u iCounter;
}
类CounterWithStateInternal扩展StatefulWidget{
最终国际数学家;
最后一次bool-tfAllowChange;
最终功能改变;
反陈述内部(
Key Key、this.iCounter、this.tfAllowChange、this.fndatachange)
:super(key:key);
@凌驾
CounterWithStateMain createState()=>CounterWithStateMain();
}
类CounterWithStateMain扩展状态{
int _i计数器=0;
@凌驾
initState(){
super.initState();
_iCounter=widget.iCounter;
}
无效增量计数(){
if(widget.tfAllowChange){
设置状态(()=>this.\u iCounter++);
widget.fnDataChanged(_iCounter);
打印(“CounterWithStateMain:New count=$\u iCounter”);
}
}
小部件构建(上下文){
返回列(子项:[
文本(“计数器值=$\u i计数器”),
大小盒子(
身高:20.0,
),
升起的按钮(
onPressed:增加计数,
子项:文本(“点击添加”),
)
]);
}
}

这是我之前答案的更新,以更好地说明我想要实现的目标。我目前在我的代码中使用这个概念,使用复选框来存储它自己的值

这只是一个简单的例子(概念证明)来说明我想要实现的目标。我只是想让小部件存储它的值,并在我需要时将其提供给我(即更新数据)。另一种选择是由主程序存储值,但我认为这并不理想

以下内容似乎有效。它似乎比我高很多
import 'package:flutter/material.dart';

class CounterWithState {
  int _iCounter;
  CounterWithStateInternal _counterWithStateInternal;

  fnDataChanged(int iNewCounter) {
    _iCounter = iNewCounter;
    debugPrint("CounterWithState: New value = $_iCounter");
  }

  CounterWithStateInternal getCounterWidget() {
    return _counterWithStateInternal;
  }

  CounterWithState({@required iCounter, @required bool isAllowedChange}) {
    _iCounter = iCounter;
    _counterWithStateInternal = CounterWithStateInternal(
        GlobalKey(), this._iCounter, isAllowedChange, fnDataChanged);
  }
  get iCounter => _iCounter;
}

class CounterWithStateInternal extends StatefulWidget {
  final int iCounter;
  final bool tfAllowChange;
  final Function fnDataChanged;
  CounterWithStateInternal(
      Key key, this.iCounter, this.tfAllowChange, this.fnDataChanged)
      : super(key: key);
  @override
  CounterWithStateMain createState() => CounterWithStateMain();
}

class CounterWithStateMain extends State<CounterWithStateInternal> {
  int _iCounter = 0;

  @override
  initState() {
    super.initState();
    _iCounter = widget.iCounter;
  }

  void increaseCount() {
    if (widget.tfAllowChange) {
      setState(() => this._iCounter++);
      widget.fnDataChanged(_iCounter);
      print("CounterWithStateMain: New count = $_iCounter");
    }
  }

  Widget build(context) {
    return Column(children: <Widget>[
      Text("Value of counter = $_iCounter"),
      SizedBox(
        height: 20.0,
      ),
      RaisedButton(
        onPressed: increaseCount,
        child: Text('Tap To Add'),
      )
    ]);
  }
}

import 'package:flutter/material.dart';
import 'counterWithState.dart';

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

class MyApp extends StatelessWidget {
  final String sTitle = 'Flutter Counter-With-State Demo';
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: sTitle,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: sTitle),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  CounterWithState _counterWithState;
  FloatingActionButton _fab;
  int _iCounterOriginal = 99;
  RaisedButton _raisedButton;
  SizedBox _sizedBox;
  final _scaffoldKey = GlobalKey<ScaffoldState>();

  @override
  void initState() {
    super.initState();
    _fab = FloatingActionButton(
      onPressed: _showSnackbar,
      tooltip: 'Press to show Counter',
      child: Icon(Icons.info),
    );
    _raisedButton = RaisedButton(
        child: const Text('Update'),
        color: Theme.of(context).accentColor,
        elevation: 4.0,
        splashColor: Colors.blueGrey,
        onPressed: () {
          _iCounterOriginal = _counterWithState.iCounter;
          _counterWithState = null;
          _getCounterWithState(context);
          setState(() {});
        });
    _sizedBox = SizedBox(height: _raisedButton.height);
  }

  fnCounterChanged(int iCounter) {
    setState(() {});
  }

  _showSnackbar() {
    _scaffoldKey.currentState.showSnackBar(SnackBar(
        backgroundColor: Colors.blue,
        content:
            Text("Current value of Counter is ${_counterWithState.iCounter}")));
  }

  @override
  Widget build(BuildContext context) {
    _counterWithState = _counterWithState != null
        ? _counterWithState
        : _getCounterWithState(context);
    return Scaffold(
      key: _scaffoldKey,
      appBar: AppBar(
        title: Text(widget.title),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            _counterWithState.getCounterWidget(),
            _getUpdateButton(context),
          ],
        ),
      ),
      floatingActionButton: _fab,
    );
  }

  Widget _getUpdateButton(BuildContext context) {
    return _counterWithState == null ||
            _counterWithState.iCounter == _iCounterOriginal
        ? _sizedBox
        : _raisedButton;
  }

  CounterWithState _getCounterWithState(context) {
    if (_counterWithState == null)
      _counterWithState = CounterWithState(
          iCounter: _iCounterOriginal,
          isAllowedChange: true,
          fnNotifyChange: fnCounterChanged);
    return _counterWithState;
  }
}
import 'package:flutter/material.dart';

class CounterWithState {
  int _iCounter;
  final Function fnNotifyChange;
  CounterWithStateInternal _counterWithStateInternal;

  fnDataChanged(int iNewCounter) {
    _iCounter = iNewCounter;
    if (fnNotifyChange != null) fnNotifyChange(iNewCounter);
  }

  CounterWithStateInternal getCounterWidget() {
    return _counterWithStateInternal;
  }

  CounterWithState(
      {@required iCounter,
      @required bool isAllowedChange,
      this.fnNotifyChange}) {
    _iCounter = iCounter;
    _counterWithStateInternal = CounterWithStateInternal(
        GlobalKey(), this._iCounter, isAllowedChange, fnDataChanged);
  }
  get iCounter => _iCounter;
}

class CounterWithStateInternal extends StatefulWidget {
  final int iCounter;
  final bool tfAllowChange;
  final Function fnDataChanged;
  CounterWithStateInternal(
      Key key, this.iCounter, this.tfAllowChange, this.fnDataChanged)
      : super(key: key);
  @override
  CounterWithStateMain createState() => CounterWithStateMain();
}

class CounterWithStateMain extends State<CounterWithStateInternal> {
  int _iCounter;
  int _iOriginalCounter;

  @override
  initState() {
    super.initState();
    _iCounter = widget.iCounter;
    _iOriginalCounter = widget.iCounter;
  }

  void incrementCounter(int iValue) {
    if (widget.tfAllowChange) {
      setState(() => this._iCounter += iValue);
      widget.fnDataChanged(_iCounter);
    }
  }

  Widget build(context) {
    return Column(children: <Widget>[
      Text("Value of original counter = $_iOriginalCounter"),
      _getSizedBox(),
      Text("Value of counter = $_iCounter"),
      _getSizedBox(),
      RaisedButton(
        onPressed: (() => incrementCounter(1)),
        child: Text('Tap To Add'),
      ),
      _getSizedBox(),
      RaisedButton(
        onPressed: (() => incrementCounter(-1)),
        child: Text('Tap To Subtract'),
      ),
      _getSizedBox(),
    ]);
  }

  SizedBox _getSizedBox() {
    return SizedBox(height: 20.0);
  }
}