首页 文章

如何使按钮的onPressed [在单独的类中]将值返回到父类?

提问于
浏览
0

所以我正在创建我的第一个Flutter应用程序,并且在登录屏幕上我使用了一个带动画的自定义按钮小部件(我把它变成了一个类,所以我可以在我的应用程序中多次使用它) . 我的自定义按钮小部件基于this Tutorial . 我的问题是,我试图通过在我将要传递给widget类的方法中使用setState()方法来调用文本验证 . 由于它是在一个完全不同的类上,我无法调用setState()方法 .

我尽可能多地搜索SO,但我似乎无法找到适用于我的用例的任何有用的问题 . 我想要做的是,一旦用户按下自定义小部件按钮,自定义小部件按钮的onPressed()方法应该调用validateTextField()方法并使用setState()相应地设置TexFormField的errorText参数(文本字段在登录中)小工具类) .

PS:这是我的第一个问题,所以如果我犯了任何错误,请耐心等待,如果我需要编辑这个问题的任何部分,我只会评论它 . 如果您需要更多代码,请询问,谢谢 .

这是我的代码:

我的自定义小部件类:

class LoginProgressButton extends StatefulWidget {
  final Color successButtonColor;
  final Color buttonColor;
  final Color splashColor;
  @required
  final bool onPressed;
  @required
  final VoidCallback navigator;

  const LoginProgressButton({
    Key key,
    this.onPressed,
    this.successButtonColor,
    this.buttonColor,
    this.splashColor,
    this.navigator,
  }) : super(key: key);

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

class _LoginProgressButton extends State<LoginProgressButton>
    with TickerProviderStateMixin {
  int _state = 0;
  double _width = 240.0;
  Animation _animation;
  AnimationController _controller;
  GlobalKey _globalKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Container(
      key: _globalKey,
      alignment: Alignment.center,
      height: 60.0,
      width: _width,
      child: ButtonTheme(
        height: 60.0,
        minWidth: _width,
        shape: OutlineInputBorder(
          borderRadius: BorderRadius.circular(30.0),
        ),
        child: RaisedButton(
          onPressed: () => onPressed(),
          color: _state == 2 ? widget.successButtonColor : widget.buttonColor,
          child: loginState(),
          splashColor: widget.splashColor,
          onHighlightChanged: null,
        ),
      ),
    );
  }

  Widget loginState() {
    if (_state == 2) {
      return Icon(
        Icons.check,
        color: Colors.white,
      );
    } else if (_state == 1) {
      return SizedBox(
        height: 30.0,
        width: 30.0,
        child: CircularProgressIndicator(
          value: null,
          backgroundColor: Colors.white,
          strokeWidth: 3.0,
          valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
        ),
      );
    } else {
      return Text('Connect',
          style: TextStyle(
            color: Colors.white,
            fontSize: 24.0,
          ));
    }
  }

  void animateButton() {
    print(_state);
    double initialWidth = _globalKey.currentContext.size.width;
    _controller =
        AnimationController(duration: Duration(milliseconds: 300), vsync: this);

    _animation = Tween(begin: 0.0, end: 1.0).animate(_controller)
      ..addListener(() {
        setState(() {
          _width = initialWidth - ((initialWidth - 60.0) * _animation.value);
          //this reduces the width by 48.0 for each frame, thus showing a smooth transition
        });
      });

    _controller.forward(); //the forward function starts the animation

    //starting with the default state
    setState(() => _state = 1);

    Timer(Duration(milliseconds: 3600), () => setState(() => _state = 2));

    Timer(Duration(milliseconds: 4200), () => widget.navigator());

    Timer(Duration(milliseconds: 4400), () => reset());
  }

  void reset() {
    _width = 240.0;
    _state = 0;
  }

  @override
  void dispose() {
    super.dispose();
  }

  void onPressed() {
    if (widget.onPressed) {
      setState(() {
        if (_state == 0) {
          animateButton();
        } else if (_state == 2) {
          reset();
        }
      });
    } else {}
  }
}

Login Widget类调用Custom Widget:

LoginProgressButton(
     buttonColor: Theme.of(context).buttonColor,
                  splashColor: Theme.of(context).splashColor,
                  onPressed: _validateTextField(_pageHostLink),
                  navigator: _navigation,
                  successButtonColor: Colors.greenAccent,
                ),

On Pressed方法传递给Custom Widget:

void _validateField() {
    String value = _pageHostLink;
    setState(() {
      _fieldValidated = value == null ? false : value.isNotEmpty;
    });
    print("value is $value of datatype ${value.runtimeType}");
    setState(() => _errorText =
        _fieldValidated ? null : 'This field cannot be left empty');
  }

  bool _validateTextField(String value) {
    print("value is $value of datatype ${value.runtimeType}");
    _validateField();
    return value == null ? false : value.isNotEmpty;
  }

如果验证成功,则导航器功能会推送下一个路径

void _navigation() {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (BuildContext context) => LoginPage(
              pageHostLink: _pageHostLink,
            ),
      ),
    );
  }

1 回答

  • 0

    有几种方法可以更改另一个小部件的状态 . 最简单的是传递回调函数 . 其他选项是使用InheritedWidhets,因此您可以从应用程序的任何位置获取AppState . 有关不同体系结构示例的更多信息,请参阅here .

    对于你的情况,我会在 LoginProgressButton 类中将 bool onPressed 更改为 ValidationFunction onPressed ,其中ValidationFunction是

    typedef bool ValidationFunction();
    

    你创建了你的课程

    LoginProgressButton(
        buttonColor: Theme.of(context).buttonColor,
         splashColor: Theme.of(context).splashColor,
         onPressed: () => _validateTextField(_pageHostLink),
         navigator: _navigation,
         successButtonColor: Colors.greenAccent,
    ),
    

相关问题