我目前正在开发一个 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),
),
),
],
),
],
);
}
}
我创建了一个演示应用程序。
根据你的代码。
它可以满足您的需要。
我意识到的一件重要的事情是,在最后五秒内,不要每秒播放/暂停,这会导致计数器和音频播放器之间失去同步,而是从最后 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.
],
);
}
}
}
当谈到 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
包。