Flutter 倒计时截止日期音频

问题描述 投票:0回答:2

我目前正在开发一个 Flutter 项目,并利用circular_countdown_timer 包来显示倒计时器。然而,我在实现一个功能时面临着挑战,我想在倒计时的最后 5 秒内播放“Tic”音频。具体来说,我想在倒计时的最后一秒播放“Tic”音频,总共 5 个“Tic”声音。

我正在寻求有关如何在我的 Flutter 应用程序中实现此功能的指导。如何在倒计时的最后 5 秒触发音频播放,确保倒计时的每一秒都播放“Tic”音频?

任何与使用circular_countdown_timer包在倒计时期间集成音频播放相关的见解、建议或代码示例将不胜感激。

提前感谢您在解决这一挑战方面的支持和专业知识。

小部件:

 /// Returns Body as per mode or mode conditions
  Widget returnSmQuizBodyWidget({required BuildContext context}) {
    if (_soloModeLogic.currentMode == 'Exclusive'{
      return const SMWinScreen();
    } else {
      return Column(
        children: [
          //-----------------------   Question Container
          Stack(
            clipBehavior: Clip.none,
            children: [
              //-----------------------   Question Frame
              returnQuestionFrame(context: context),

              //-----------------------   Timer
              Positioned(
                      right: 0,
                      left: 0,
                      bottom: -25,
                      child: CircularCountDownTimer(
                        duration: _soloModeLogic.quizTime,
                        initialDuration: 0,
                        controller: _soloModeLogic.countDownController,
                        width: 5.w,
                        height: 7.h,
                        ringColor: Colors.grey.shade400,
                        ringGradient: null,
                        fillColor: _soloModeLogic.isFreezeColor
                            ? Colors.lightBlueAccent
                            : Colors.red,
                        fillGradient: null,
                        backgroundColor: const Color(0xfff5f5f5),
                        backgroundGradient: null,
                        strokeWidth: 4.w,
                        strokeCap: StrokeCap.butt,
                        textStyle: TextStyle(
                          fontSize: 20.sp,
                          color: _soloModeLogic.isFreezeColor
                              ? Colors.lightBlueAccent
                              : Colors.red,
                          fontWeight: FontWeight.bold,
                        ),
                        textFormat: CountdownTextFormat.S,
                        isReverse: true,
                        isReverseAnimation: false,
                        isTimerTextShown: true,
                        autoStart: true,
                        onStart: () {},
                        onChange: (v) {},
                        onComplete: () =>
                            _soloModeLogic.onTimeOut(context: context),
                      ),
                    ),
            ],
          ),
        ],
      );
    }
  }
flutter dart
2个回答
1
投票

我创建了一个演示应用程序。 根据你的代码。 它可以满足您的需要。
我意识到的一件重要的事情是,在最后五秒内,不要每秒播放/暂停,这会导致计数器和音频播放器之间失去同步,而是从最后 5 秒开始播放音频,并在零处或之前停止并选择合适的音频文件,需要大约 1 秒才能播放声音。
您可以更改音频速度进行调整,还可以查找备用音频播放器库。
你可以用代码做任何事情。(Fork/copy-pase 等)
谢谢:)

编辑:
我意识到将来我可能会从存储库中删除该应用程序,因此将代码的重要部分粘贴到此处。
我的根目录中有

assets/tick.mp3
文件。
这是我的
pubspec.yaml
文件。

name: solution_76450197
description: A new Flutter project.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1

environment:
  sdk: '>=3.0.3 <4.0.0'
dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2
  circular_countdown_timer: ^0.2.3
  audioplayers: ^4.1.0

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^2.0.0
flutter:
  uses-material-design: true

  assets:
    - assets/

这是我的 main.dart 文件。

import 'package:audioplayers/audioplayers.dart';
import 'package:circular_countdown_timer/circular_countdown_timer.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class SoloModeLogic {
  String currentMode = "none";
  bool isFreezeColor = false;

  final audioPlayer = AudioPlayer()..setSource(AssetSource('tick.mp3'));
  int quizTime = 10;
  final CountDownController countDownController = CountDownController();


  // The length indicates threshold seconds (last five seconds)
  List<bool> threshold = [false, false ,false,false,false];

  onTimeOut({required BuildContext context}) {
    print("time out");
    audioPlayer.pause();
    //restartCountdown();
  }
  // Please not that it's not called at every second change but instead
  // called on more smaller unit of second second.
  // Hence it could be called multiple times per second
  void onCountdownChange(String v) {
    int vInt = int.parse(v);
    if (vInt > 0 && vInt < threshold.length + 1 && !threshold[vInt-1]) {
      audioPlayer.pause();
      threshold[vInt-1] = true;
      audioPlayer.seek(const Duration(milliseconds: 0));
      audioPlayer.resume();
    } else if (vInt == 0) {
      audioPlayer.pause();
    }
  }


  void restartCountdown() {
    audioPlayer.pause();
    threshold = threshold.map((e) => false).toList();
    countDownController.restart(duration: quizTime);
  }
}

final _soloModeLogic = SoloModeLogic();

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return returnSmQuizBodyWidget(context: context);
  }

  /// Returns Body as per mode or mode conditions
  Widget returnSmQuizBodyWidget({required BuildContext context}) {
    if (_soloModeLogic.currentMode == 'Exclusive') {
      return const Text("Exclusive Mode");
    } else {
      return Column(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          //-----------------------   Question Container
          Stack(
            clipBehavior: Clip.none,
            children: [
              //-----------------------   Question Frame
              const Text("My Question"),

              //-----------------------   Timer
              Positioned(
                right: 0,
                left: 0,
                top: (MediaQuery.of(context).size.height / 2),
                child: CircularCountDownTimer(
                  duration: _soloModeLogic.quizTime,
                  initialDuration: 0,
                  controller: _soloModeLogic.countDownController,
                  width: 50,
                  height: 70,
                  ringColor: Colors.grey.shade400,
                  ringGradient: null,
                  fillColor: _soloModeLogic.isFreezeColor
                      ? Colors.lightBlueAccent
                      : Colors.red,
                  fillGradient: null,
                  backgroundColor: const Color(0xfff5f5f5),
                  backgroundGradient: null,
                  strokeWidth: 4,
                  strokeCap: StrokeCap.butt,
                  textStyle: TextStyle(
                    fontSize: 20,
                    color: _soloModeLogic.isFreezeColor
                        ? Colors.lightBlueAccent
                        : Colors.red,
                    fontWeight: FontWeight.bold,
                  ),
                  textFormat: CountdownTextFormat.S,
                  isReverse: true,
                  isReverseAnimation: false,
                  isTimerTextShown: true,
                  autoStart: false,
                  onStart: () {},
                  onChange: _soloModeLogic.onCountdownChange,
                  onComplete: () => _soloModeLogic.onTimeOut(context: context),
                ),
              ),
            ],
          ),
          FloatingActionButton(
            onPressed: () {
              _soloModeLogic.restartCountdown();
            },
            child: Text("Start"),
          ),
          // This trailing comma makes auto-formatting nicer for build methods.
        ],
      );
    }
  }
}

0
投票

当谈到 Flutter 中的音频处理时,我总是选择 just_audio 包。它可以轻松完成所需的工作。

您的

CircularCountDownTimer
有一个
onChange
回调,应该足以满足您在最后 5 秒内每秒播放声音的用例。

步骤1 从这里安装

just_audio
软件包:https://pub.dev/packages/just_audio

第2步 在您的

onChange
回调中,您应该能够获取当前持续时间(例如 23)并将其与最终值进行比较(例如,如果倒计时为 0),如果差值小于或等于 4,则播放音频。由于我不能 100% 确定倒数计时器包的工作原理,因此我将使用伪代码。

late AudioPlayer player;

void initAudio() {
  player = AudioPlayer();
  await player.setAsset('assets/audio/tic.mp3'); // add whatever audio you have
}

CircularCountDownTimer(
  duration: _soloModeLogic.quizTime,
  initialDuration: 0,
  controller: _soloModeLogic.countDownController,
  width: 5.w,
  height: 7.h,
  ringColor: Colors.grey.shade400,
  ringGradient: null,
  fillColor: _soloModeLogic.countDownController.isPaused
      ? Colors.lightBlueAccent
      : Colors.redAccent,
  fillGradient: null,
  backgroundColor: const Color(0xfff5f5f5),
  backgroundGradient: null,
  strokeWidth: 4.w,
  strokeCap: StrokeCap.butt,
  textStyle: TextStyle(
    fontSize: 20.sp,
    color: _soloModeLogic.countDownController.isPaused
        ? Colors.blueAccent
        : Colors.red,
    fontWeight: FontWeight.bold,
  ),
  textFormat: CountdownTextFormat.S,
  isReverse: true,
  isReverseAnimation: false,
  isTimerTextShown: true,
  autoStart: true,
  onStart: () {},
  onChange: () {
    // considering you're counting from 0 to _soloModeLogic.quizTime
    player.seek(Duration(second: 0));     // set track position to 0
    if (_soloModeLogic.quizTime - currentDuration <= 4) {   // if duration is in last 5 seconds
      player.play();
    }
    
  },
  onComplete: () =>
      player.stop();
      _soloModeLogic.onTimeOut(context: context),
),

我希望这是有道理的。如果您不确定,请随时询问。

再一次,我不确定如何访问

currentDuration
,因为我从未使用过
circular_countdown_timer
包。

© www.soinside.com 2019 - 2024. All rights reserved.