- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在 flutter 中使用 audioplayers
库,我试图保存和恢复播放器位置,除了从第一个位置播放,就像缓存播放器搜索栏位置一样,在这段代码中,我尝试使用 SharedPreference
保存和恢复它,但我的实现不成功
class ApplicationSettings {
ApplicationSettings(StreamingSharedPreferences preferences)
: showIntro = preferences.getBool('showIntro', defaultValue: false),
pageViewIndex = preferences.getInt('pageViewIndex', defaultValue: 0),
audioPosition = preferences.getString('audioPosition', defaultValue: "{}")
;
final Preference<bool> showIntro;
final Preference<int> pageViewIndex;
final Preference<String> audioPosition;
}
AudioInformation
类:
part'audio_information.g.dart';
@JsonSerializable(nullable: true)
class AudioInformation {
final String productName;
final int audioPosition;
AudioInformation(this.productName, this.audioPosition);
factory AudioInformation.fromJson(Map<String, dynamic> json) => _$AudioInformationFromJson(json);
Map<String, dynamic> toJson() => _$AudioInformationToJson(this);
}
PlayerWidget
类:
enum PlayerState { stopped, playing, paused }
enum PlayingRouteState { speakers, earpiece }
class PlayerWidget extends StatefulWidget {
final String url;
final PlayerMode mode;
final String productName;
final String imageUrl;
PlayerWidget({Key key, @required this.url, this.mode = PlayerMode.MEDIA_PLAYER, @required this.productName, @required this.imageUrl}) : super(key: key);
@override
State<StatefulWidget> createState() {
return _PlayerWidgetState(url, mode);
}
}
class _PlayerWidgetState extends State<PlayerWidget> {
_PlayerWidgetState(this.url, this.mode);
String url;
PlayerMode mode;
AudioPlayer _audioPlayer;
Duration _duration;
Duration _position;
PlayerState _playerState = PlayerState.stopped;
PlayingRouteState _playingRouteState = PlayingRouteState.speakers;
StreamSubscription _durationSubscription;
StreamSubscription _positionSubscription;
StreamSubscription _playerCompleteSubscription;
StreamSubscription _playerErrorSubscription;
StreamSubscription _playerStateSubscription;
StreamSubscription<PlayerControlCommand> _playerControlCommandSubscription;
get _isPlaying => _playerState == PlayerState.playing;
get _isPaused => _playerState == PlayerState.paused;
get _durationText => _duration?.toString()?.split('.')?.first ?? '';
get _positionText => _position?.toString()?.split('.')?.first ?? '';
Preference<String> _audioPosition;
@override
void didChangeDependencies() {
super.didChangeDependencies();
_audioPosition = Provider.of<ApplicationSettings>(context).audioPosition;
}
@override
void initState() {
super.initState();
_initAudioPlayer();
_play();
}
@override
void dispose() {
_audioPlayer.dispose();
_durationSubscription?.cancel();
_positionSubscription?.cancel();
_playerCompleteSubscription?.cancel();
_playerErrorSubscription?.cancel();
_playerStateSubscription?.cancel();
_playerControlCommandSubscription?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return PreferenceBuilder(
preference: _audioPosition,
builder: (context, String audioDetail) {
/* SAVE position*/
AudioInformation _audio = AudioInformation('${widget.productName}', _duration?.inMilliseconds?.round()??0);
_audioPosition.setValue(_audio.toJson().toString());
return Scaffold(
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(Icons.audiotrack_outlined),
Expanded(
child: Text(
' - ${widget.productName}',
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
),
],
),
),
body: Stack(
children: [
Positioned.fill(
child: CachedNetworkImage(
imageUrl: widget.imageUrl,
fit: BoxFit.cover,
)),
Container(
width: double.infinity,
height: double.infinity,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 2.0, sigmaY: 2.0),
child: Container(
color: Colors.white.withOpacity(0.7),
),
),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.all(16.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(11.0),
boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.2), offset: Offset(0.0, 0.0), spreadRadius: 1.0)],
border: Border.all(color: Colors.black)),
child: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: CachedNetworkImage(
imageUrl: '${widget.imageUrl}',
fit: BoxFit.cover,
width: 150.0,
),
),
),
Container(
margin: EdgeInsets.all(8.0),
padding: EdgeInsets.all(5.0),
decoration: BoxDecoration(color: Colors.white.withOpacity(0.5), border: Border.all(color: Colors.black), borderRadius: BorderRadius.circular(5.0)),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IconButton(
key: Key('play_button'),
onPressed: _isPlaying ? null : () => _play(),
iconSize: 64.0,
icon: Icon(MdiIcons.playCircle),
color: Colors.black,
),
IconButton(
key: Key('pause_button'),
onPressed: _isPlaying ? () => _pause() : null,
iconSize: 64.0,
icon: Icon(MdiIcons.pauseCircle),
color: Colors.green[900],
),
IconButton(
key: Key('stop_button'),
onPressed: _isPlaying || _isPaused ? () => _stop() : null,
iconSize: 64.0,
icon: Icon(MdiIcons.stopCircle),
color: Colors.indigo[700],
),
],
),
Slider(
onChanged: (v) {
final position = v * _duration.inMilliseconds;
_audioPlayer.seek(Duration(milliseconds: position.round()));
/* SAVE position*/
AudioInformation _audio = AudioInformation('${widget.productName}', position.round());
_audioPosition.setValue(_audio.toJson().toString());
},
value: (_position != null && _duration != null && _position.inMilliseconds > 0 && _position.inMilliseconds < _duration.inMilliseconds)
? _position.inMilliseconds / _duration.inMilliseconds
: 0.0,
),
],
),
),
_durationText != null && _durationText.toString().isNotEmpty
? Container(
height: 43.0,
padding: EdgeInsets.all(8.0),
decoration: BoxDecoration(color: Colors.white.withOpacity(0.5), border: Border.all(color: Colors.black), borderRadius: BorderRadius.circular(5.0)),
child: Text(
_position != null
? '${_positionText ?? ''} / ${_durationText ?? ''}'
: _duration != null
? _durationText
: ' --- ',
style: TextStyle(fontSize: 24.0),
),
)
: Container(
height: 43.0,
),
],
),
],
),
);
});
}
void _initAudioPlayer() {
_audioPlayer = AudioPlayer(mode: mode);
_durationSubscription = _audioPlayer.onDurationChanged.listen((duration) {
setState(() => _duration = duration);
});
_positionSubscription = _audioPlayer.onAudioPositionChanged.listen((p) => setState(() {
_position = p;
}));
_playerCompleteSubscription = _audioPlayer.onPlayerCompletion.listen((event) {
_onComplete();
setState(() {
_position = _duration;
});
});
_playerErrorSubscription = _audioPlayer.onPlayerError.listen((msg) {
print('audioPlayer error : $msg');
setState(() {
_playerState = PlayerState.stopped;
_duration = Duration(seconds: 0);
_position = Duration(seconds: 0);
});
});
_playerControlCommandSubscription = _audioPlayer.onPlayerCommand.listen((command) {
print('command');
});
_audioPlayer.onPlayerStateChanged.listen((state) {
if (!mounted) return;
});
_audioPlayer.onNotificationPlayerStateChanged.listen((state) {
if (!mounted) return;
//setState(() => _audioPlayerState = state);
});
_playingRouteState = PlayingRouteState.speakers;
}
Future<int> _play() async {
final playPosition = (_position != null && _duration != null && _position.inMilliseconds > 0 && _position.inMilliseconds < _duration.inMilliseconds) ? _position : null;
final result = await _audioPlayer.play(url, position: playPosition);
if (result == 1) setState(() => _playerState = PlayerState.playing);
_audioPlayer.setPlaybackRate(playbackRate: 1.0);
/* RESTORE position*/
if (_audioPosition?.getValue() != null) {
final _res = jsonDecode(_audioPosition.getValue());
int pos = _audioPosition.getValue() == '{}' ? 0 : _res['audioPosition'];
_audioPlayer.seek(Duration(milliseconds: pos));
}
return result;
}
Future<int> _pause() async {
final result = await _audioPlayer.pause();
if (result == 1) setState(() => _playerState = PlayerState.paused);
return result;
}
Future<int> _stop() async {
final result = await _audioPlayer.stop();
if (result == 1) {
setState(() {
_playerState = PlayerState.stopped;
_position = Duration();
});
}
return result;
}
void _onComplete() {
setState(() => _playerState = PlayerState.stopped);
}
}
最佳答案
在 PreferenceBuilder widget 中,您应该删除第一个“Save Position”代码,当 widget 第一次构建时,脚手架返回之前的那两行代码用零值覆盖保存的音频位置的值,这是因为第一次构建小部件时,持续时间为 null。在 sharedpreference 中保存音频位置的更好位置是在
_audioplayer.onAudioPositionChanged()
功能在
_initAudioPlayer()
函数。您可以查看下面的代码片段以了解我在说什么
AudioInformation _audio = AudioInformation('${widget.productName}', p?.inMilliseconds?.round() ?? 0);
_audioPosition.setValue(_audio.toJson().toString());
setState(() {
_position = p;
});
});
这应该可以解决您面临的问题
关于Flutter 保存并恢复 AudioPlayer 位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65145783/
我正在尝试获取从过去的 startposition/location 到当前移动的 currentposition/location 的距离(以米为单位)。 我确实有工作正常的currentposit
所以我有一堆绝对覆盖的 div。用户通过在叠加层上拖动来创建方形 div。如果您要创建一个 div,然后放大和缩小,div 会保持在同一位置,因为它对叠加层是绝对的,如前所述。 然而问题就出在这里。您
我想找到 View 在显示屏幕上的位置。 为此,我使用了 view.getLeft() 、view.getBottom() 、view.getRight() 等方法> , view.getTop()。
我有一个看起来像这样的 View 层次结构(基于其他答案和 Apple 的使用 UIScrollView 的高级 AutoLayout 指南): ScrollView 所需的2 个步骤是: 为 Scr
所以我有一个名为 MARKS 的表,我有这些列 STUDENT_ID, CLASSFORM_NAME, ACADEMIC_YEAR, TERM, SUBJECT_NAME, TOTAL_MARKS
我有一个问题我无法理解,请帮助: 我开发了带有图像的 html 页面,并使用 jQuery UI 帮助使它们可拖动,我将这些图像位置设置为相对位置并给出了左侧和顶部像素,这是页面的链接 http://
我正在尝试创建一个 CSS 动画,它在 sprite 表中循环播放 16 个图像,给人一种幽灵“漂浮”的错觉。动画通过在 background-position 位置之间移动以显示不同状态的幽灵来实现
我正在创建这个网站的 WebView https://nearxt.com/打开时询问位置但是当我使用此链接在 flutter 中创建 webview 时那么它就无法定位我还在应用程序中定义了位置,但
我正在以编程方式创建一个需要跨越 2 个屏幕的窗口。正在创建的窗口的大小是正确的,但窗口大约从第一个屏幕的一半开始。我可以将它拖回第一个屏幕的开头,NSWindow 非常适合。 我只需要知道在窗口的起
位置“/”的匹配叶路由没有元素。这意味着默认情况下它将呈现一个空值,从而导致一个“空”页面 //App.js File import { BrowserRouter as Router, Routes
我有一个运行 Ubuntu 和 Apache 的 VPS 例如,假设地址是:5.5.5.5 在 VPS 上,我有一个名为 eggdrop 的用户(除了我的 root 用户)。 用户 eggdrop 有
我有一个 JLabel与 ImageIcon ,我使用 setIcon() JLabel中的函数. ImageIcon然后上来,坐在我的JLabel 的文字左侧.是否有可能拥有 ImageIcon在文
我的图中有节点,它们的 xlabels 位于它们的左上方。我怎样才能改变这个位置?我希望 xlabels 正好位于节点本身的旁边。 最佳答案 xlp是你想要的属性,但它没有做任何事情。 你不能改变位置
我对基本的 VIM 功能有疑问:(我尝试谷歌搜索但找不到答案) 如何列出所有自定义功能。(我做了 :function 并且不能找到我的自定义函数) 如何获得自定义函数列表中的函数(或它们的存储位置)。
我是 PHP 的新手,虽然我一直在搜索,但我不知道该怎么做。 我知道可以使用 Location("some page") 进行重定向。我还读到,只要没有向用户显示任何内容,它就可以工作。 我想做的是:
如果在 jgrowl.css 中位置更改为“center”,我如何将其覆盖为默认值,即“top-right” $.jGrowl(data, { header: 'data', an
我需要根据用户是否滑动屏幕顶部、屏幕中间或屏幕底部来触发不同的事件。我正在尝试找出最好/最简单的方法来做到这一点,因为我很确定没有办法从 UISwipeGestureRecognizer 获取位置。
我需要枚举用delphi编写的外部应用程序中使用的类 ,因此我需要访问VMT表以获取该信息,但是我找不到任何有关如何在exe(由delphi生成)文件中找到VMT(虚拟方法表)的位置(地址)的文档。
在 D2010 (unicode) 中是否有像 Pos 这样不区分大小写的类似函数? 我知道我可以使用 Pos(AnsiUpperCase(FindString), AnsiUpperCase(Sou
我正在尝试为我的reveal.js 演示文稿制作一个标题,该标题会粘贴在屏幕顶部。标题中的内容在每张幻灯片的基础上都是动态的,因此我必须将标记放在 section 标记中。 显然,如果标记在 sect
我是一名优秀的程序员,十分优秀!