是否要停止上一次点击的音频?

时间:2019-12-19 05:22:50

标签: flutter flutter-dependencies

是否要停止上一次点击的音频?当我在TAP上颤抖地点击另一个图像时?

请查看下面的代码,让我知道当我们敲击另一只鸟时如何停止音乐。

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

child: InkWell(
  onTap: () {
    Audio.load('assets/audios/' + audio)
      ..play()
      ..dispose();
  },

1 个答案:

答案 0 :(得分:0)

您可以使用官方示例
https://github.com/google/flutter.plugins/tree/master/packages/audiofileplayer/example/lib
代码段

    static Widget _transportButtonWithTitle(
      String title, bool isPlaying, VoidCallback onTap) =>
      Padding(
          padding: const EdgeInsets.all(4.0),
          child: Column(
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 4.0),
                child: RaisedButton(
                    onPressed: onTap,
                    child: isPlaying
                        ? Image.asset("assets/icons/ic_pause_black_48dp.png")
                        : Image.asset(
                        "assets/icons/ic_play_arrow_black_48dp.png")),
              ),
              Padding(
                  padding: const EdgeInsets.symmetric(vertical: 4.0),
                  child: Text(title)),
            ],
          ));


_transportButtonWithTitle('play from start', false, () {
                  _audio.play();
                  setState(() => _audioPlaying = true);
                }),
                _transportButtonWithTitle(
                    _audioPlaying ? 'pause' : 'resume', _audioPlaying, () {
                  _audioPlaying ? _audio.pause() : _audio.resume();
                  setState(() => _audioPlaying = !_audioPlaying);
                }),       

工作演示

enter image description here

完整的示例代码

import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;

import 'package:audiofileplayer/audiofileplayer.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  // Preloaded audio data for the first card.
  Audio _audio;
  bool _audioPlaying = false;
  double _audioDurationSeconds;
  double _audioPositionSeconds;
  double _audioVolume = 1.0;
  double _seekSliderValue = 0.0; // Normalized 0.0 - 1.0.

  // On-the-fly audio data for the second card.
  int _spawnedAudioCount = 0;
  ByteData _audioByteData;

  // Remote url audio data for the third card.
  Audio _remoteAudio;
  bool _remoteAudioPlaying = false;
  bool _remoteAudioLoading = false;
  String _remoteErrorMessage;

  // The iOS audio category dropdown item in the fourth card.
  IosAudioCategory _iosAudioCategory = IosAudioCategory.playback;

  @override
  void initState() {
    super.initState();
    _audio = Audio.load('assets/audio/printermanual.m4a',
        onComplete: () => setState(() => _audioPlaying = false),
        onDuration: (double durationSeconds) =>
            setState(() => _audioDurationSeconds = durationSeconds),
        onPosition: (double positionSeconds) => setState(() {
              _audioPositionSeconds = positionSeconds;
              _seekSliderValue = _audioPositionSeconds / _audioDurationSeconds;
            }));
    _loadAudioByteData();
    _loadRemoteAudio();
  }

  @override
  void dispose() {
    _audio.dispose();
    if (_remoteAudio != null) {
      _remoteAudio.dispose();
    }
    super.dispose();
  }

  static Widget _transportButtonWithTitle(
          String title, bool isPlaying, VoidCallback onTap) =>
      Padding(
          padding: const EdgeInsets.all(4.0),
          child: Column(
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 4.0),
                child: RaisedButton(
                    onPressed: onTap,
                    child: isPlaying
                        ? Image.asset("assets/icons/ic_pause_black_48dp.png")
                        : Image.asset(
                            "assets/icons/ic_play_arrow_black_48dp.png")),
              ),
              Padding(
                  padding: const EdgeInsets.symmetric(vertical: 4.0),
                  child: Text(title)),
            ],
          ));

  // convert double seconds to minutes:seconds
  static String _stringForSeconds(double seconds) {
    if (seconds == null) return null;
    return '${(seconds ~/ 60)}:${(seconds.truncate() % 60).toString().padLeft(2, '0')}';
  }

  void _loadAudioByteData() async {
    _audioByteData = await rootBundle.load('assets/audio/sinesweep.mp3');
    setState(() {});
  }

  void _loadRemoteAudio() {
    _remoteErrorMessage = null;
    _remoteAudioLoading = true;
    _remoteAudio = Audio.loadFromRemoteUrl('https://streams.kqed.org/kqedradio',
        onDuration: (_) => setState(() => _remoteAudioLoading = false),
        onError: (String message) => setState(() {
              _remoteErrorMessage = message;
              _remoteAudio.dispose();
              _remoteAudio = null;
              _remoteAudioPlaying = false;
              _remoteAudioLoading = false;
            }));
  }

  // Creates a card, out of column child widgets. Injects vertical padding
  // around the column children.
  Widget _cardWrapper(List<Widget> columnChildren) => Card(
      child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
              mainAxisSize: MainAxisSize.min,
              children: columnChildren
                  .map((Widget child) => Padding(
                        padding: const EdgeInsets.symmetric(vertical: 4.0),
                        child: child,
                      ))
                  .toList())));

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
      backgroundColor: const Color(0xFFCCCCCC),
      appBar: AppBar(
        title: const Text('Audio file player example'),
      ),
      body: ListView(children: <Widget>[
        // A card controlling a pre-loaded (on app start) audio object.
        _cardWrapper(<Widget>[
          const Text('Preloaded asset audio, with transport controls.'),
          Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
            _transportButtonWithTitle('play from start', false, () {
              _audio.play();
              setState(() => _audioPlaying = true);
            }),
            _transportButtonWithTitle(
                _audioPlaying ? 'pause' : 'resume', _audioPlaying, () {
              _audioPlaying ? _audio.pause() : _audio.resume();
              setState(() => _audioPlaying = !_audioPlaying);
            }),
            _transportButtonWithTitle(
                _audioPlaying ? 'pause' : 'play 0:05 to 0:10', _audioPlaying,
                () async {
              if (_audioPlaying) {
                _audio.pause();
              } else {
                await _audio.seek(5);
                _audio.resume(10);
              }
              setState(() => _audioPlaying = !_audioPlaying);
            }),
          ]),
          Row(
            children: <Widget>[
              Text(_stringForSeconds(_audioPositionSeconds) ?? ''),
              Expanded(child: Container()),
              Text(_stringForSeconds(_audioDurationSeconds) ?? ''),
            ],
          ),
          Slider(
              value: _seekSliderValue,
              onChanged: (double val) {
                setState(() => _seekSliderValue = val);
                final double positionSeconds = val * _audioDurationSeconds;
                _audio.seek(positionSeconds);
              }),
          const Text('drag to seek'),
          Slider(
              value: _audioVolume,
              onChanged: (double val) {
                setState(() => _audioVolume = val);
                _audio.setVolume(_audioVolume);
              }),
          const Text('volume (linear amplitude)'),
        ]),
        _cardWrapper(<Widget>[
          const Text(
            'Spawn overlapping one-shot audio playback.\n(tap multiple times)',
            textAlign: TextAlign.center,
          ),
          Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
            _transportButtonWithTitle('audio from assets', false, () {
              Audio.load('assets/audio/sinesweep.mp3',
                  onComplete: () => setState(() => --_spawnedAudioCount))
                ..play()
                ..dispose();
              setState(() => ++_spawnedAudioCount);
            }),
            _transportButtonWithTitle(
                'audio from ByteData',
                false,
                _audioByteData == null
                    ? null
                    : () {
                        Audio.loadFromByteData(_audioByteData,
                            onComplete: () =>
                                setState(() => --_spawnedAudioCount))
                          ..play()
                          ..dispose();
                        setState(() => ++_spawnedAudioCount);
                      })
          ]),
          Text('Spawned audio count: $_spawnedAudioCount'),
        ]),
        _cardWrapper(<Widget>[
          const Text('Play remote stream'),
          _transportButtonWithTitle(
              'resume/pause NPR (KQED) live stream',
              _remoteAudioPlaying,
              _remoteAudioLoading
                  ? null
                  : () {
                      if (!_remoteAudioPlaying) {
                        // If remote audio loading previously failed with an
                        // error, attempt to reload.
                        if (_remoteAudio == null) _loadRemoteAudio();
                        // Note call to resume(), not play(). play() attempts to
                        // seek to the start of a file, which, for streams, will
                        // fail with an error on Android platforms, so streams
                        // should use resume() to begin playback.
                        _remoteAudio.resume();
                        setState(() => _remoteAudioPlaying = true);
                      } else {
                        _remoteAudio.pause();
                        setState(() => _remoteAudioPlaying = false);
                      }
                    }),
          _remoteErrorMessage != null
              ? Text(_remoteErrorMessage,
                  style: const TextStyle(color: const Color(0xFFFF0000)))
              : Text(_remoteAudioLoading ? 'loading...' : 'loaded')
        ]),
        _cardWrapper(<Widget>[
          Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
            const Text('Enable background playback:'),
            Checkbox(
                value: Audio.shouldPlayWhileAppPaused,
                onChanged: (bool isOn) =>
                    setState(() => Audio.shouldPlayWhileAppPaused = isOn))
          ]),
          const Text('(iOS only) iOS audio category:'),
          DropdownButton<IosAudioCategory>(
            value: _iosAudioCategory,
            onChanged: (IosAudioCategory newValue) {
              setState(() {
                _iosAudioCategory = newValue;
                Audio.setIosAudioCategory(_iosAudioCategory);
              });
            },
            items: IosAudioCategory.values.map((IosAudioCategory category) {
              return DropdownMenuItem<IosAudioCategory>(
                value: category,
                child: Text(category.toString()),
              );
            }).toList(),
          )
        ]),
      ]),
    ));
  }
}