我在 a 中有以下代码,statefullWidget
我想将其更改statefullWidget
为 astatelessWidget
并GetXCintroller
改用。
AnimationController? _controller;
Animation<Offset>? _slideAnimation;
Animation<double>? _opacityAnimation;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(
milliseconds: 300,
),
);
_slideAnimation = Tween<Offset>(
begin: const Offset(0, -1.5),
end: const Offset(0, 0),
).animate(
CurvedAnimation(
parent: _controller as Animation<double>,
curve: Curves.fastOutSlowIn,
),
);
_opacityAnimation = Tween(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _controller as Animation<double>,
curve: Curves.easeIn,
),
);
// _heightAnimation.addListener(() => setState(() {}));
}
我试图把它放在onInit()
方法中而不是initState()
放在一个类extends GetxController with GetSingleTickerProviderStateMixin
中。它似乎没有错误,但是当我在移动平台上启动应用程序时,当我尝试选择登录/注册表单上的文本字段时,它会关闭键盘。实际上,这是一个通过将表单和按钮文本从登录模式切换到注册模式来为登录/注册表单设置动画的代码。这是表单的代码:
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 8.0,
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
curve: Curves.easeIn,
height: _authMode!.value == AuthMode.Signup ? 320 : 260,
//height: _heightAnimation.value.height,
constraints: BoxConstraints(
minHeight: _authMode.value == AuthMode.Signup ? 320 : 260),
width: deviceSize.width * 0.75,
padding: const EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
TextFormField(
decoration: const InputDecoration(labelText: 'E-Mail'),
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value!.isEmpty || !value.contains('@')) {
return 'Invalid email!';
}
},
onSaved: (value) {
_authData['email'] = value as String;
},
),
TextFormField(
decoration: const InputDecoration(labelText: 'Password'),
obscureText: true,
controller: _passwordController,
validator: (value) {
if (value!.isEmpty || value.length < 5) {
return 'Password is too short!';
}
},
onSaved: (value) {
_authData['password'] = value as String;
},
),
AnimatedContainer(
constraints: BoxConstraints(
minHeight: _authMode.value == AuthMode.Signup ? 60 : 0,
maxHeight: _authMode.value == AuthMode.Signup ? 120 : 0,
),
duration: const Duration(milliseconds: 300),
curve: Curves.easeIn,
child: FadeTransition(
opacity: _opacityAnimation as Animation<double>,
child: SlideTransition(
position: _slideAnimation as Animation<Offset>,
child: TextFormField(
enabled: _authMode.value == AuthMode.Signup,
decoration: const InputDecoration(
labelText: 'Confirm Password'),
obscureText: true,
validator: _authMode.value == AuthMode.Signup
? (value) {
if (value != _passwordController.text) {
return 'Passwords do not match!';
}
}
: null,
),
),
),
),
const SizedBox(
height: 20,
),
if (_isLoading!.value)
const CircularProgressIndicator()
else
Obx(() => ElevatedButton(
child: Text(_authMode.value == AuthMode.Login
? 'LOGIN'
: 'SIGN UP'),
onPressed: _submit,
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
primary: Theme.of(context).primaryColor,
padding: const EdgeInsets.symmetric(
horizontal: 30.0, vertical: 8.0),
onPrimary: Theme.of(context)
.primaryTextTheme
.button!
.color,
),
)),
Obx(() => TextButton(
child: Text(
'${_authMode.value == AuthMode.Login ? 'SIGNUP' : 'LOGIN'} '),
onPressed: _switchAuthMode,
style: TextButton.styleFrom(
padding: const EdgeInsets.symmetric(
horizontal: 30.0, vertical: 4),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
textStyle: TextStyle(
color: Theme.of(context).primaryColor),
),
)),
],
),
),
)),
// ),
);
文本按钮有效(通过用 包装Obx
)并且可以更改表单,但文本字段不可点击,并且键盘立即关闭并且表单再次重新启动。