record_playback_widget.dart 3.79 KB
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 RecorderPlaybackWidget extends StatefulWidget {
  final bool isClickable;
  final bool isPlaying;
  final VoidCallback? onTap;
  final double width;
  final double height;

  const RecorderPlaybackWidget({
    Key? key,
    required this.isClickable,
    required this.isPlaying,
    required this.onTap,
    required this.width,
    required this.height,
  }) : super(key: key);

  @override
  _RecorderPlaybackWidgetState createState() => _RecorderPlaybackWidgetState();
}

class _RecorderPlaybackWidgetState extends State<RecorderPlaybackWidget>
    with SingleTickerProviderStateMixin {
  late final AnimationController _controller;
  late final Future<LottieComposition> _futureComposition;
  static const String TAG = "RecorderPlaybackWidget";

  bool _isPlaying = false;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this);
    _loadComposition();
    if (widget.isPlaying) {
      _playAnimation();
    }

    _controller.addListener(() {
      // Log.d("$TAG addListener _controller=${_controller.status}");
    });
  }

  @override
  void didUpdateWidget(RecorderPlaybackWidget 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;
      });
      _playAnimation();
    } else if (!widget.isPlaying && _isPlaying) {
      _stopAnimation();
    }

    if (!_isPlaying) {
      _displayAnimation(widget.isClickable);
    }
  }

  Future<void> _loadComposition() async {
    _futureComposition = AssetLottie('assets/lotties/recorder_back.zip').load();
  }

  void _playAnimation() {
    _controller.reset();
    _futureComposition.then((composition) {
      _controller.duration = composition.duration;
      _controller.repeat(
        min: 2 / composition.endFrame,
        max: 20 / composition.endFrame,
      );
    });
  }

  void _stopAnimation() {
    _controller.stop();
    if (mounted) {
      setState(() {
        _isPlaying = false;
        _futureComposition.then((composition) {
          _controller.value = 1 / composition.endFrame;
        });
        // _controller.repeat(
        //   min: 1 / _composition.endFrame,
        //   max: 1 / _composition.endFrame,
        // );
      });
    }
  }

  void _displayAnimation(bool clickable) {
    if (clickable) {
      _controller.value = 1;
      // _controller.repeat(
      //   min: 1,
      //   max: 1,
      // );
    } else {
      _controller.value = 0;
      // _controller.repeat(
      //   min: 0,
      //   max: 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<LottieComposition>(
            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();
              }
            }),
      ),
    );
  }
}