You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter/Dart中播放/暂停按钮功能实现求助

Flutter冥想APP播放/暂停按钮功能修复方案

核心问题排查

你的代码存在3个关键问题导致功能失效:

  • 赋值运算符误用:在setState里错误使用比较运算符==而非赋值运算符=,导致playingIndex状态从未正确更新
  • 音频切换逻辑缺失:切换新音频时未停止当前播放的音频,会出现多音频同时播放的情况
  • 播放/暂停逻辑混淆:当前用stop()直接终止音频,未实现真正的暂停/恢复功能

修复后完整代码

import 'package:flutter/material.dart';
import 'package:meditaion_app/Models/item_model.dart';
import 'package:just_audio/just_audio.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';

class MeditaionAppScreen extends StatefulWidget {
  const MeditaionAppScreen({super.key});

  @override
  State<MeditaionAppScreen> createState() => _MeditaionAppScreenState();
}

class _MeditaionAppScreenState extends State<MeditaionAppScreen> {
  final List<Item> items = [
    Item(
      name: "Forest",
      audiopath: "assets/meditation_audios/forest.mp3",
      imagepath: 'assets/meditation_images/forest.jpeg',
    ),
    Item(
      name: "Night",
      audiopath: "assets/meditation_audios/night.mp3",
      imagepath: 'assets/meditation_images/night.jpeg',
    ),
    Item(
      name: "Ocean",
      audiopath: "assets/meditation_audios/ocean.mp3",
      imagepath: 'assets/meditation_images/ocean.jpeg',
    ),
    Item(
      name: "Waterfall",
      audiopath: "assets/meditation_audios/waterfall.mp3",
      imagepath: 'assets/meditation_images/waterfall.jpeg',
    ),
    Item(
      name: "Wind",
      audiopath: "assets/meditation_audios/wind.mp3",
      imagepath: 'assets/meditation_images/wind.jpeg',
    ),
  ];

  final AudioPlayer audioPlayer = AudioPlayer();
  int? playingIndex;
  bool isPaused = false;

  Widget showIcon(int currentIndex) {
    if (playingIndex == currentIndex) {
      return FaIcon(isPaused ? FontAwesomeIcons.play : FontAwesomeIcons.pause);
    } else {
      return const FaIcon(FontAwesomeIcons.play);
    }
  }

  @override
  void dispose() {
    audioPlayer.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Center(
          child: Text("Meditation App"),
        ),
      ),
      body: SafeArea(
        child: ListView.builder(
          itemCount: items.length,
          itemBuilder: (context, index) {
            return Padding(
              padding: const EdgeInsets.all(10.0),
              child: Container(
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(25),
                  image: DecorationImage(
                    fit: BoxFit.cover,
                    image: AssetImage(
                      items[index].imagepath,
                    ),
                  ),
                ),
                height: 100,
                child: ListTile(
                  title: Text(items[index].name),
                  leading: IconButton(
                    icon: showIcon(index),
                    onPressed: () async {
                      try {
                        if (playingIndex == index) {
                          if (audioPlayer.playing) {
                            await audioPlayer.pause();
                            setState(() => isPaused = true);
                          } else {
                            await audioPlayer.play();
                            setState(() => isPaused = false);
                          }
                        } else {
                          await audioPlayer.stop();
                          await audioPlayer.setAsset(items[index].audiopath);
                          await audioPlayer.play();
                          setState(() {
                            playingIndex = index;
                            isPaused = false;
                          });
                        }
                      } catch (error) {
                        print(error);
                        ScaffoldMessenger.of(context).showSnackBar(
                          SnackBar(
                            backgroundColor: Colors.red.withOpacity(0.5),
                            content: const Text("音频加载失败"),
                          ),
                        );
                      }
                    },
                  ),
                ),
              ),
            );
          },
        ),
      ),
    );
  }
}

关键修改说明

  • 修复赋值错误:将setState内的==替换为=,确保playingIndex状态正确更新
  • 实现暂停/播放切换:新增isPaused变量跟踪音频状态,点击同一音频按钮时切换播放/暂停状态
  • 优化音频切换逻辑:切换新音频前先停止当前播放,避免多音频同时播放
  • 资源泄漏防护:在dispose方法中释放音频播放器资源
  • 错误提示优化:将错误提示改为更明确的中文信息,统一错误捕获逻辑

内容的提问来源于stack exchange,提问作者Abdullokh Yuldoshev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 15:01:12