Flutter 颤振动画控制器。动画回退(0)不工作
我有一个带有Flutter 颤振动画控制器。动画回退(0)不工作,flutter,dart,flutter-animation,Flutter,Dart,Flutter Animation,我有一个带有缩放动画的小部件,然后我在上面调用动画回退(0),它不会缩小。我可以确认使用相同的动画控制器调用了animateBack(0),因为我在执行animateBack(0)的代码中放置了一个断点 这里的代码块是它执行它的地方: zoomStream.listen((dynamic event) { zoomController.animateBack(0, duration: const Duration(milliseconds: 500)); }); 为什么它不能重
缩放
动画的小部件,然后我在上面调用动画回退(0)
,它不会缩小。我可以确认使用相同的动画控制器调用了animateBack(0)
,因为我在执行animateBack(0)
的代码中放置了一个断点
这里的代码块是它执行它的地方:
zoomStream.listen((dynamic event) {
zoomController.animateBack(0,
duration: const Duration(milliseconds: 500));
});
为什么它不能重新设置动画?它过去是可以工作的,但是我已经重构了我的代码来使用流,尽管它们确实执行了它,所以我认为它们不是问题所在
小部件:
import 'package:animate_do/animate_do.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:reactive_forms/reactive_forms.dart';
import 'package:vepo/presentation/animations/pulse_animation.dart';
import 'pulse_on_change_animation_controller.dart';
class VpPulseOnChangeAnimation extends StatelessWidget {
VpPulseOnChangeAnimation(this.field, {this.child}) {
controller = Get.put(VpPulseOnChangeAnimationController(field));
}
final ReactiveFormFieldState<String> field;
final Widget child;
VpPulseOnChangeAnimationController controller;
@override
Widget build(BuildContext context) {
if (controller.firstLoad) {
return Container();
} else {
return ZoomIn(
duration: const Duration(milliseconds: 250),
controller: (AnimationController zoomAnimationController) =>
{controller.zoomController = zoomAnimationController},
child: VpPulse(
manualTrigger: true,
controller: (AnimationController pulseAnimationController) =>
{controller.pulseController = pulseAnimationController},
duration: const Duration(milliseconds: 70),
child: child));
}
}
}
import 'package:flutter/animation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:reactive_forms/reactive_forms.dart';
class VpPulseOnChangeAnimationController extends GetxController {
AnimationController pulseController;
AnimationController zoomController;
bool firstLoad = true;
ReactiveFormFieldState<String> field;
@override
void onInit() {}
@override
void onReady() {
field.control.valueChanges.first.then((dynamic value) => firstLoad = false);
final pulseStream = field.control.valueChanges
.where((dynamic val) => (val as String).length < 20)
.where((dynamic val) => (val as String).isNotEmpty)
.where((dynamic val) => pulseController != null)
.where((dynamic val) => !pulseController.isAnimating);
final zoomStream = field.control.valueChanges
.where((dynamic val) => (val as String).isEmpty)
.where((dynamic val) => zoomController != null)
.where((dynamic val) => !zoomController.isAnimating);
pulseStream.listen((dynamic event) {
pulseController.forward(from: 0);
});
zoomStream.listen((dynamic event) {
zoomController.animateBack(0,
duration: const Duration(milliseconds: 500));
});
}
@override
void onClose() {}
}
@override
Widget build(BuildContext context) {
controller.applyAppropriateAnimations(field.value as String);
if (controller.firstLoad) {
return Container();
} else {
return ZoomIn(
manualTrigger: true,
duration: const Duration(milliseconds: 250),
controller: (AnimationController zoomAnimationController) =>
{controller.zoomController = zoomAnimationController},
child: VpPulse(
manualTrigger: true,
controller: (AnimationController pulseAnimationController) =>
{controller.pulseController = pulseAnimationController},
duration: const Duration(milliseconds: 70),
child: child));
}
}
animationController(zoomController
)值在中首次设置动画时应为1。然而,它并没有这样做。但它确实在动画中。因此,zoomController
可能与在中设置动画的控件不同
我的老方法很管用,但势在必行:
在控制器中:
// ignore: avoid_void_async
void applyAppropriateAnimations(String field) async {
await Future.delayed(const Duration(milliseconds: 0), () {});
if (pulseController != null &&
!pulseController.isAnimating &&
field != null &&
field.length > 1) {
await pulseController.forward(from: 0);
} else {
if (zoomController != null &&
!zoomController.isAnimating &&
field.isEmpty) {
zoomController.animateBack(0);
}
}
}
在小部件中:
import 'package:animate_do/animate_do.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:reactive_forms/reactive_forms.dart';
import 'package:vepo/presentation/animations/pulse_animation.dart';
import 'pulse_on_change_animation_controller.dart';
class VpPulseOnChangeAnimation extends StatelessWidget {
VpPulseOnChangeAnimation(this.field, {this.child}) {
controller = Get.put(VpPulseOnChangeAnimationController(field));
}
final ReactiveFormFieldState<String> field;
final Widget child;
VpPulseOnChangeAnimationController controller;
@override
Widget build(BuildContext context) {
if (controller.firstLoad) {
return Container();
} else {
return ZoomIn(
duration: const Duration(milliseconds: 250),
controller: (AnimationController zoomAnimationController) =>
{controller.zoomController = zoomAnimationController},
child: VpPulse(
manualTrigger: true,
controller: (AnimationController pulseAnimationController) =>
{controller.pulseController = pulseAnimationController},
duration: const Duration(milliseconds: 70),
child: child));
}
}
}
import 'package:flutter/animation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:reactive_forms/reactive_forms.dart';
class VpPulseOnChangeAnimationController extends GetxController {
AnimationController pulseController;
AnimationController zoomController;
bool firstLoad = true;
ReactiveFormFieldState<String> field;
@override
void onInit() {}
@override
void onReady() {
field.control.valueChanges.first.then((dynamic value) => firstLoad = false);
final pulseStream = field.control.valueChanges
.where((dynamic val) => (val as String).length < 20)
.where((dynamic val) => (val as String).isNotEmpty)
.where((dynamic val) => pulseController != null)
.where((dynamic val) => !pulseController.isAnimating);
final zoomStream = field.control.valueChanges
.where((dynamic val) => (val as String).isEmpty)
.where((dynamic val) => zoomController != null)
.where((dynamic val) => !zoomController.isAnimating);
pulseStream.listen((dynamic event) {
pulseController.forward(from: 0);
});
zoomStream.listen((dynamic event) {
zoomController.animateBack(0,
duration: const Duration(milliseconds: 500));
});
}
@override
void onClose() {}
}
@override
Widget build(BuildContext context) {
controller.applyAppropriateAnimations(field.value as String);
if (controller.firstLoad) {
return Container();
} else {
return ZoomIn(
manualTrigger: true,
duration: const Duration(milliseconds: 250),
controller: (AnimationController zoomAnimationController) =>
{controller.zoomController = zoomAnimationController},
child: VpPulse(
manualTrigger: true,
controller: (AnimationController pulseAnimationController) =>
{controller.pulseController = pulseAnimationController},
duration: const Duration(milliseconds: 70),
child: child));
}
}