如何使按钮的onPressed [位于单独的类中]将值返回给父类?

时间:2018-07-26 09:51:37

标签: dart flutter

因此,我正在制作我的第一个Flutter应用程序,并且在登录屏幕上,我使用了带有动画的自定义按钮小部件(我将其设置为类,以便可以在我的应用程序中多次使用它)。我的自定义按钮小部件基于this Tutorial。我的问题是,我正在尝试通过将要传递给小部件类的方法中的setState()方法来调用文本验证。由于它位于完全不同的类上,因此我无法调用setState()方法。

我已经尽可能地搜索了SO,但是似乎找不到适用于我的用例的有用问题。 我要做的是,一旦用户按下了自定义窗口小部件按钮,自定义窗口小部件按钮的onPressed()方法应调用validateTextField()方法并使用setState()相应地设置TexFormField的errorText参数(文本字段位于“登录名”中)小部件类)。

PS:这是我的第一个SO问题,因此,如果我有任何错误,请与我包容,如果我需要编辑此问题的任何部分,请对此发表评论。如果您需要更多代码,只需询问,谢谢。

这是我的代码:

我的自定义小部件类:

  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类正在调用的自定义Widget:

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

传递给“自定义小部件”的On Pressed方法:

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 :(得分:0)

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

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

typedef bool ValidationFunction();

您将创建类为

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