Flutter中如何实现运行页面最小化及类似YouTube的后台播放兼首页浏览功能
Hey there! Let's tackle your two Flutter questions with practical, actionable solutions that mimic real-world apps like YouTube.
First, let's clarify what "minimize a page" means in Flutter—there are two common scenarios we need to cover:
场景A:返回上一级页面(最常用的页面「最小化」)
If you just want to send the current page to the background and go back to the previous screen, use Flutter's built-in Navigator API:
// Add this to a button or gesture in your current page ElevatedButton( onPressed: () { // Pop the current page from the navigation stack Navigator.of(context).pop(); }, child: const Text('返回上页'), )
If you want to jump straight back to the root home page instead of just the previous screen:
Navigator.of(context).popUntil(ModalRoute.withName('/'));
场景B:将整个应用切换到后台(类似按Home键)
If you want to minimize the entire app and send it to the device's background, use the SystemNavigator class from Flutter's services package:
import 'package:flutter/services.dart'; void minimizeEntireApp() { // This sends the app to background on Android; behaves differently on iOS SystemNavigator.pop(); }
Note: On iOS, this might exit the app entirely since iOS has stricter rules about app backgrounding. For iOS, focus on background audio playback (covered next) instead of forcing the app to minimize.
This feature requires keeping audio running while the user navigates away from the video page. We'll use two popular packages: just_audio for audio playback and audio_service to handle background tasks.
Step 1: Add dependencies
First, add these to your pubspec.yaml:
dependencies: flutter: sdk: flutter just_audio: ^0.9.34 audio_service: ^0.18.11 rxdart: ^0.27.7 # For state management streams
Step 2: Build the background audio service
Create a background task class to handle audio playback even when the app is in the background:
import 'package:audio_service/audio_service.dart'; import 'package:just_audio/just_audio.dart'; class AudioPlayerTask extends BackgroundAudioTask { final _player = AudioPlayer(); @override Future<void> onStart(Map<String, dynamic>? params) async { // Load your video's audio URL (pass this from the foreground) await _player.setUrl(params!['audioUrl']); _player.play(); // Update the system with playback state await AudioServiceBackground.setState( controls: [MediaControl.pause, MediaControl.stop], systemActions: const {MediaAction.seekTo}, playing: true, processingState: AudioProcessingState.ready, ); // Listen for playback changes to update the UI _player.playbackEventStream.listen((event) { AudioServiceBackground.setState( playing: event.playing, processingState: event.processingState == ProcessingState.completed ? AudioProcessingState.completed : AudioProcessingState.ready, ); }); } @override Future<void> onPause() async { _player.pause(); await AudioServiceBackground.setState(playing: false); } @override Future<void> onPlay() async { _player.play(); await AudioServiceBackground.setState(playing: true); } @override Future<void> onStop() async { await _player.dispose(); await AudioServiceBackground.setState( controls: [], playing: false, processingState: AudioProcessingState.stopped, ); await super.onStop(); } }
Step 3: Add controls to your video page
In your video playback page, add a button to start background playback and navigate back to the home page:
import 'package:audio_service/audio_service.dart'; import 'package:flutter/material.dart'; class VideoPlayerScreen extends StatelessWidget { // Replace this with your actual video audio URL final String audioUrl = "https://example.com/your-video-audio.mp3"; Future<void> _startBackgroundPlayback(BuildContext context) async { // Start the background audio service await AudioService.start( backgroundTaskEntrypoint: _audioPlayerTaskEntrypoint, params: {'audioUrl': audioUrl}, ); // Navigate back to the home page (minimize the video page) Navigator.of(context).popUntil(ModalRoute.withName('/')); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('视频播放页')), body: Center( child: ElevatedButton( onPressed: () => _startBackgroundPlayback(context), child: const Text('最小化并继续收听音频'), ), ), ); } } // Required top-level entry point for the background service void _audioPlayerTaskEntrypoint() { AudioServiceBackground.run(() => AudioPlayerTask()); }
Step 4: Add playback controls to the home page
To let users control the background audio while scrolling the home page, add a persistent bottom bar:
class HomeScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('首页')), body: ListView.builder( itemCount: 20, itemBuilder: (context, index) => ListTile( title: Text('推荐视频 $index'), leading: const Icon(Icons.video_library), ), ), // Show playback controls when audio is running bottomNavigationBar: StreamBuilder<PlaybackState>( stream: AudioService.playbackStateStream, builder: (context, snapshot) { final playbackState = snapshot.data; if (playbackState?.playing == true) { return Container( height: 60, color: Colors.grey[800], child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ IconButton( icon: const Icon(Icons.pause, color: Colors.white), onPressed: AudioService.pause, ), IconButton( icon: const Icon(Icons.stop, color: Colors.white), onPressed: AudioService.stop, ), ], ), ); } return const SizedBox.shrink(); }, ), ); } }
效果示例

示例说明:用户点击视频页的按钮后,回到首页滚动视频列表,底部显示播放控制栏,音频持续播放,完全复刻YouTube的后台音频体验。
内容的提问来源于stack exchange,提问作者Vincent




