Ширина кнопки не меняется во время анимации - PullRequest
1 голос
/ 06 июля 2019

Я пытаюсь реализовать анимацию кнопки при нажатии, она сжимается и показывает круговой индикатор прогресса (при загрузке), затем расширяется и показывает результат выполненной операции (в данном случае это логин).

Идея кода пришла из этой ссылки .Идея дизайна возникла по этой ссылке .Теперь я реализовал это раньше, и он работал именно так, как и предполагалось.Однако при повторной реализации здесь, при нажатой кнопке -> человек успешно входит в систему, и кнопка меняет цвет в соответствии с дизайном «все».Единственная проблема в том, что кнопки анимации не происходит.Я попытался напечатать значения _loginButtonWidth и на самом деле вижу, как он уменьшается и увеличивается в соответствии с дизайном, но визуально ширина остается неизменной.

Код:

import 'package:flutter/material.dart';
import 'package:garuda_academy_app/Login/Authentication.dart';
import 'package:garuda_academy_app/Tools/FixedColors.dart';
import 'dart:async';

class LoginPage extends StatefulWidget {
  LoginPage({this.auth, this.onLoggedIn});

  @override
  _LoginPageState createState() => _LoginPageState();

  final BaseAuth auth;
  final VoidCallback onLoggedIn;
}

class _LoginPageState extends State<LoginPage> with TickerProviderStateMixin {
  // for device type
  bool _isIos;

  // text form field
  String _userEmail = "";
  String _userPassword = "";
  final _formKey = GlobalKey<FormState>();

  // for login button
  int _loginButtonState = 0;
  double _loginButtonWidth = double.maxFinite;
  Color _loginButtonColor = primaryColor;
  Color _loginButtonOutlineColor = primaryColor;
  Color _loginButtonTextColor = secondaryColor;
  GlobalKey _loginButtonKey = GlobalKey();
  Animation _loginButtonAnimation;
  AnimationController _loginButtonController;

  Widget _loginButton() {
    if (_loginButtonState == 0) {
      return Text(
        "Log In",
        style: TextStyle(
          color: _loginButtonTextColor,
          fontSize: 20,
        ),
      );
    } else if (_loginButtonState == 1) {
      return CircularProgressIndicator(
        valueColor: AlwaysStoppedAnimation<Color>(secondaryColor),
      );
    } else if (_loginButtonState == 2) {
      return Icon(
        Icons.check,
        color: _loginButtonTextColor,
      );
    } else if (_loginButtonState == 3) {
      return Icon(
        Icons.close,
        color: _loginButtonTextColor,
      );
    } else if (_loginButtonState == 4) {
      return Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Icon(
            Icons.check,
            color: _loginButtonTextColor,
          ),
          Icon(
            Icons.check,
            color: transparent,
          ),
          Text(
            "Successful",
            style: TextStyle(
              color: _loginButtonTextColor,
            ),
          ),
        ],
      );
    } else if (_loginButtonState == 5) {
      return Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Icon(
            Icons.close,
            color: _loginButtonTextColor,
          ),
          Icon(
            Icons.close,
            color: transparent,
          ),
          Text(
            "Unsuccessful",
            style: TextStyle(
              color: _loginButtonTextColor,
            ),
          ),
        ],
      );
    }
  }

  bool _validateLoginAndSave() {
    if (_formKey.currentState.validate()) {
      _formKey.currentState.save();
      return true;
    }
    return false;
  }

  _animateLoginButton() async {
    String userId = "";
    String errorMsg = "";
    setState(() {
      _loginButtonState = 1;
    });
    // animation
    double initialWidth = _loginButtonKey.currentContext.size.width;
    _loginButtonController =
        AnimationController(duration: Duration(milliseconds: 300), vsync: this)
          ..addStatusListener((AnimationStatus status) async {
            if (status == AnimationStatus.completed) {
              // firebase signin
              try {
                userId = await widget.auth.signIn(_userEmail, _userPassword);
              } catch (e) {
                setState(() {
                  errorMsg = _isIos ? e.details : e.message;
                  print(errorMsg);
                });
              }

              // loading timer
              Timer(Duration(seconds: 1), () {
                // set login state
                _loginButtonState =
                    (userId.length > 0 && userId != null) ? 2 : 3;
                // change colors
                if (_loginButtonState == 2) {
                  _loginButtonColor = secondaryColor;
                  _loginButtonOutlineColor = successfulColor;
                  _loginButtonTextColor = successfulColor;
                } else if (_loginButtonState == 3) {
                  _loginButtonColor = secondaryColor;
                  _loginButtonOutlineColor = unsuccessfulColor;
                  _loginButtonTextColor = unsuccessfulColor;
                }
                _loginButtonController.reverse();
              });
            } else if (status == AnimationStatus.dismissed) {
              if (_loginButtonState == 2) {
                _loginButtonState = 4;
              } else if (_loginButtonState == 3) {
                _loginButtonState = 5;
              }
              // minimal time before it is done
              Timer(Duration(seconds: 1), () {
                setState(() {
                  if (_loginButtonState == 4) widget.onLoggedIn();
                  // reset state
                  _loginButtonState = 0;

                  // reset colors
                  _loginButtonColor = primaryColor;
                  _loginButtonOutlineColor = primaryColor;
                  _loginButtonTextColor = secondaryColor;
                });
              });
            }
          });

    _loginButtonAnimation =
        Tween(begin: 0.0, end: 1.0).animate(_loginButtonController)
          ..addListener(() {
            setState(() {
              _loginButtonWidth = initialWidth -
                  ((initialWidth - 80.0) * _loginButtonAnimation.value);
            });
            print("initial: " + initialWidth.toString());
            print("current: " + _loginButtonWidth.toString());
          });

    _loginButtonController.forward();
  }

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

  @override
  Widget build(BuildContext context) {
    _isIos = Theme.of(context).platform == TargetPlatform.iOS;
    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: SingleChildScrollView(
        child: Center(
          child: Theme(
            data: ThemeData(primaryColor: primaryColor),
            child: Form(
              key: _formKey,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: <Widget>[
                  Padding(
                    padding: EdgeInsets.all(40),
                    child: Text(
                      "Log in to continue",
                      textAlign: TextAlign.left,
                      style: TextStyle(
                        fontSize: 30,
                        fontWeight: FontWeight.bold,
                        color: primaryColor,
                      ),
                    ),
                  ),
                  Padding(
                    padding: EdgeInsets.only(bottom: 20, left: 40, right: 40),
                    child: TextFormField(
                      keyboardType: TextInputType.emailAddress,
                      style: TextStyle(
                        fontSize: 20,
                      ),
                      decoration: InputDecoration(
                        labelText: "Email Address",
                        labelStyle: TextStyle(fontSize: 20),
                      ),
                      validator: (value) =>
                          value.isEmpty ? "Email cannot be empty" : null,
                      onSaved: (value) => _userEmail = value,
                    ),
                  ),
                  Padding(
                    padding: EdgeInsets.only(bottom: 20, left: 40, right: 40),
                    child: TextFormField(
                      keyboardType: TextInputType.emailAddress,
                      obscureText: true,
                      style: TextStyle(
                        fontSize: 20,
                      ),
                      decoration: InputDecoration(
                        labelText: "Password",
                        labelStyle: TextStyle(fontSize: 20),
                      ),
                      validator: (value) =>
                          value.isEmpty ? "Password cannot be empty" : null,
                      onSaved: (value) => _userPassword = value,
                    ),
                  ),
                  Padding(
                    padding: EdgeInsets.only(bottom: 50, left: 40, right: 40),
                    child: Container(
                      height: 60,
                      width: _loginButtonWidth,
                      child: PhysicalModel(
                        color: transparent,
                        borderRadius: BorderRadius.circular(10.0),
                        child: RaisedButton(
                          elevation: 8.0,
                          color: _loginButtonColor,
                          key: _loginButtonKey,
                          shape: OutlineInputBorder(
                            borderSide: BorderSide(
                              color: _loginButtonOutlineColor,
                            ),
                            borderRadius: BorderRadius.circular(10.0),
                          ),
                          child: _loginButton(),
                          onPressed: () {
                            setState(() {
                              if (_loginButtonState == 0 &&
                                  _validateLoginAndSave()) {
                                _animateLoginButton();
                              }
                            });
                          },
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

Ширина кнопки остаетсято же самое, когда предполагается уменьшить:

enter image description here

1 Ответ

2 голосов
/ 06 июля 2019

Простое исправление, добавьте виджет Center или Align в качестве родительского элемента для кнопки Container.

 Padding(
                    padding: EdgeInsets.only(bottom: 50, left: 40, right: 40),
                    child: Center(
                      child: Container(
                        height: 60,
                        width: _loginButtonWidth,

Для получения дополнительной информации проверьте Поведение макета

...