当前位置: 首页 > article >正文

Flutter鸿蒙next 实现长按录音按钮及动画特效

在 Flutter 中实现长按录音按钮并且添加动画特效,是一个有趣且实用的功能。本文将通过实现一个具有动画效果的长按录音按钮,带领你一步步了解如何使用 Flutter 完成这个任务,并解释每一部分的实现。

一、功能需求

我们需要一个按钮,当用户长按时,开始录音并且显示相应的录音进度。长按结束时,停止录音并显示录音的结果。同时,在长按时,按钮应该具备一个动画效果,展示录音进度或指示正在录音。

二、实现思路

  1. 按钮UI设计:使用 GestureDetector 监听长按手势,设置不同的状态(长按开始、录音中、录音结束)。
  2. 动画效果:使用 AnimatedContainer 或 AnimationController 配合 Tween 实现按钮的尺寸变化、颜色变化等动画效果,提升用户体验。
  3. 录音功能:利用 Flutter 的录音插件 flutter_sound 来实现录音功能。

三、代码实现

1. 添加依赖

pubspec.yaml 文件中添加所需的依赖:

yaml

dependencies: flutter: sdk: flutter flutter_sound: ^9.1.9 # 音频录制插件

2. 编写UI和动画逻辑

import 'package:flutter/material.dart';
import 'package:flutter_sound/flutter_sound.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '长按录音按钮',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: RecordingButton(),
    );
  }
}

class RecordingButton extends StatefulWidget {
  @override
  _RecordingButtonState createState() => _RecordingButtonState();
}

class _RecordingButtonState extends State<RecordingButton> with TickerProviderStateMixin {
  FlutterSoundRecorder _recorder;  // 录音器
  bool _isRecording = false;  // 是否正在录音
  double _progress = 0.0;  // 录音进度
  AnimationController _animationController;  // 动画控制器
  Animation<double> _scaleAnimation;  // 缩放动画
  Animation<Color?> _colorAnimation;  // 颜色变化动画

  @override
  void initState() {
    super.initState();
    _recorder = FlutterSoundRecorder();
    _initRecorder();
    _initAnimations();
  }

  // 初始化录音器
  void _initRecorder() async {
    await _recorder.openAudioSession();
  }

  // 初始化动画控制器
  void _initAnimations() {
    _animationController = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 200),
    );

    _scaleAnimation = Tween<double>(begin: 1.0, end: 1.2).animate(
      CurvedAnimation(parent: _animationController, curve: Curves.easeInOut),
    );

    _colorAnimation = ColorTween(begin: Colors.blue, end: Colors.red).animate(
      CurvedAnimation(parent: _animationController, curve: Curves.easeInOut),
    );
  }

  // 开始录音
  void _startRecording() async {
    await _recorder.startRecorder(toFile: 'audio.aac');
    setState(() {
      _isRecording = true;
    });
    _animationController.forward();
    _recordingProgress();
  }

  // 停止录音
  void _stopRecording() async {
    await _recorder.stopRecorder();
    setState(() {
      _isRecording = false;
      _progress = 0.0;
    });
    _animationController.reverse();
  }

  // 录音进度
  void _recordingProgress() async {
    while (_isRecording) {
      await Future.delayed(Duration(milliseconds: 100));
      final progress = await _recorder.getRecordingDuration();
      setState(() {
        _progress = progress.inSeconds.toDouble();
      });
      if (_progress >= 10) { // 假设录音最大为10秒
        _stopRecording();
      }
    }
  }

  @override
  void dispose() {
    _recorder.closeAudioSession();
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('长按录音按钮')),
      body: Center(
        child: GestureDetector(
          onLongPress: _startRecording,
          onLongPressEnd: (_) => _stopRecording(),
          child: AnimatedBuilder(
            animation: _animationController,
            builder: (context, child) {
              return Container(
                width: 150,
                height: 150,
                decoration: BoxDecoration(
                  color: _colorAnimation.value,
                  shape: BoxShape.circle,
                ),
                child: Center(
                  child: ScaleTransition(
                    scale: _scaleAnimation,
                    child: Icon(
                      _isRecording ? Icons.stop : Icons.mic,
                      color: Colors.white,
                      size: 80,
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ),
    );
  }
}

3. 代码详细解释

1. UI 和手势操作

我们使用了 GestureDetector 来监听用户的长按手势:

  • onLongPress:当用户长按按钮时,调用 _startRecording 函数开始录音。
  • onLongPressEnd:当长按结束时,调用 _stopRecording 停止录音。

通过 AnimatedBuilder 来监听动画状态变化,更新 UI。

2. 录音功能

我们使用 flutter_sound 插件来处理录音功能:

  • _recorder.startRecorder(toFile: 'audio.aac'):开始录音并保存为 audio.aac 文件。
  • _recorder.stopRecorder():停止录音。
  • _recorder.getRecordingDuration():获取录音进度,通过 inSeconds 获取已录制的时间。
3. 动画效果

我们通过 AnimationControllerTween 来控制动画:

  • _scaleAnimation:通过 ScaleTransition 实现按钮的缩放

http://www.kler.cn/a/388114.html

相关文章:

  • 【Webpack实用指南】如何拆分CSS资源(2)
  • 事件循环 -- 资源总结(浏览器进程模型、事件循环机制、练习题)
  • Gsensor加速度传感器数据异常及概率性卡死
  • 算法演练----24点游戏
  • vue项目npm run serve出现【- Network: unavailable】(从排查到放弃)
  • Ue5 umg学习(一)
  • 链表知识汇总
  • 手机的ip地址是固定的吗?多角度深入探讨
  • 【Linux】Linux入门实操——vim、目录结构、远程登录、重启注销
  • 第9章 Apache WEB服务器企业实战
  • ChatGPT 新体验:AI 搜索功能与订阅支付指南
  • 加固筑牢安全防线:多源威胁检测响应在企业网络安全运营中的核心作用
  • leetcode 832.翻转图像
  • Vue Router 详细使用步骤:如何在 Vue 项目中配置 Vue Router
  • 世优科技携手人民中科打造AI数字人智能体助力智慧校园
  • Vue vs React:两大前端框架的区别解析
  • Cannot read properties of undefined (reading ‘$isServer‘)
  • [强网杯 2019]随便注 1
  • 解决Mac M芯片 Wireshark 运行rvictl -s 后,出现Starting device failed
  • Java中的I/O模型——BIO、NIO、AIO
  • 华为大变革?仓颉编程语言会代替ArkTS吗?
  • 机器学习系列-----主成分分析(PCA)
  • Redis的内存淘汰机制
  • WPF在MVVM模式下怎么实现导航功能
  • 【SpringBoot】ThreadLocal线程空间上下文使用
  • Linux:版本控制器git的简单使用+gdb/cgdb调试器的使用