import 'package:flutter/material.dart'; import 'package:lottie/lottie.dart'; import 'package:wow_english/common/widgets/throttledGesture_gesture_detector.dart'; import '../../utils/log_util.dart'; /// 录音组件 class RecorderWidget extends StatefulWidget { final bool isClickable; final bool isPlaying; final VoidCallback? onTap; final double width; final double height; const RecorderWidget({ Key? key, this.isClickable = true, required this.isPlaying, required this.onTap, required this.width, required this.height, }) : super(key: key); @override _RecorderWidgetState createState() => _RecorderWidgetState(); } class _RecorderWidgetState extends State with SingleTickerProviderStateMixin { late final AnimationController _controller; late final Future _futureComposition; static const String TAG = "RecorderWidget"; bool _isPlaying = false; @override void initState() { super.initState(); _controller = AnimationController(vsync: this); _loadComposition(); if (widget.isPlaying) { _playInitialAnimation(); } _controller.addListener(() { // Log.d("$TAG addListener _controller=${_controller.status}"); }); } @override void didUpdateWidget(RecorderWidget oldWidget) { super.didUpdateWidget(oldWidget); Log.d( "$TAG ${identityHashCode(this)} didUpdateWidget widget=${widget.isPlaying} oldWidget=${oldWidget.isPlaying} _isPlaying=$_isPlaying"); if (widget.isPlaying && !_isPlaying) { setState(() { _isPlaying = true; }); _playInitialAnimation(); } else if (!widget.isPlaying && _isPlaying) { _playFinalAnimation(); } } Future _loadComposition() async { _futureComposition = AssetLottie('assets/lotties/recorder_input.zip').load(); } void _playInitialAnimation() { _controller.reset(); _futureComposition.then((composition) { _controller.duration = composition.duration; _controller .animateTo(22 / composition.endFrame) .whenComplete(() => _loopMiddleAnimation(composition)); }); } void _loopMiddleAnimation(LottieComposition composition) { _controller.repeat( min: 22 / composition.endFrame, max: 37 / composition.endFrame, ); } void _playFinalAnimation() { _controller.stop(); _futureComposition.then((composition) { _controller.duration = composition.duration; _controller .animateTo(50 / composition.endFrame) .whenComplete(() => _resetAnimation()); }); } void _resetAnimation() { if (mounted) { setState(() { _isPlaying = false; _controller.value = 0; }); } } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return ThrottledGestureDetector( onTap: widget.isClickable ? widget.onTap : null, child: Opacity( opacity: widget.isClickable ? 1.0 : 0.5, // 设置透明度 child: FutureBuilder( future: _futureComposition, builder: (context, snapshot) { if (snapshot.hasData) { final composition = snapshot.data!; return Lottie( composition: composition, controller: _controller, renderCache: RenderCache.raster, width: widget.width, height: widget.height, ); } else { return const SizedBox.shrink(); } })), ); } }