播放和暂停视频

播放视频是应用程序开发中的一项常见任务,Flutter 应用程序也不例外。为了播放视频,Flutter 团队提供了 video_player 插件。您可以使用 video_player 插件播放存储在文件系统、作为资源或来自互联网的视频。

在 iOS 上,video_player 插件使用 AVPlayer 来处理播放。在 Android 上,它使用 ExoPlayer

本示例演示了如何使用 video_player 包通过以下步骤从互联网流式传输视频,并使用基本的播放和暂停控件:

  1. 添加 video_player 依赖项。
  2. 向您的应用程序添加权限。
  3. 创建并初始化 VideoPlayerController
  4. 显示视频播放器。
  5. 播放和暂停视频。

1. 添加 video_player 依赖项

#

本示例依赖于一个 Flutter 插件:video_player。首先,将此依赖项添加到您的项目中。

要将 video_player 包作为依赖项添加,请运行 flutter pub add

flutter pub add video_player

2. 为您的应用添加权限

#

接下来,更新您的 androidios 配置,以确保您的应用程序具有从互联网流式传输视频的正确权限。

Android

#

将以下权限添加到 AndroidManifest.xml 文件中,紧接在 <application> 定义之后。AndroidManifest.xml 文件位于 <project root>/android/app/src/main/AndroidManifest.xml 中。

xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application ...>

    </application>

    <uses-permission android:name="android.permission.INTERNET"/>
</manifest>

iOS

#

对于 iOS,将以下内容添加到 Info.plist 文件中,该文件位于 <project root>/ios/Runner/Info.plist 中。

xml
<key>NSAppTransportSecurity</key>
<dict>
  <key>NSAllowsArbitraryLoads</key>
  <true/>
</dict>

3. 创建并初始化 VideoPlayerController

#

现在您已经安装了 video_player 插件,并具有正确的权限,请创建一个 VideoPlayerControllerVideoPlayerController 类允许您连接到不同类型的视频并控制播放。

在播放视频之前,您还必须 初始化 控制器。这将建立与视频的连接,并为播放准备控制器。

要创建和初始化 VideoPlayerController,请执行以下操作:

  1. 创建一个 StatefulWidget,并附带一个 State 类。
  2. State 类添加一个变量来存储 VideoPlayerController
  3. State 类添加一个变量来存储从 VideoPlayerController.initialize 返回的 Future
  4. initState 方法中创建并初始化控制器。
  5. dispose 方法中释放控制器。
dart
class VideoPlayerScreen extends StatefulWidget {
  const VideoPlayerScreen({super.key});

  @override
  State<VideoPlayerScreen> createState() => _VideoPlayerScreenState();
}

class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
  late VideoPlayerController _controller;
  late Future<void> _initializeVideoPlayerFuture;

  @override
  void initState() {
    super.initState();

    // Create and store the VideoPlayerController. The VideoPlayerController
    // offers several different constructors to play videos from assets, files,
    // or the internet.
    _controller = VideoPlayerController.networkUrl(
      Uri.parse(
        'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4',
      ),
    );

    _initializeVideoPlayerFuture = _controller.initialize();
  }

  @override
  void dispose() {
    // Ensure disposing of the VideoPlayerController to free up resources.
    _controller.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // Complete the code in the next step.
    return Container();
  }
}

4. 显示视频播放器

#

现在,显示视频。video_player 插件提供了 VideoPlayer 小部件来显示由 VideoPlayerController 初始化的视频。默认情况下,VideoPlayer 小部件会占用尽可能多的空间。这对于视频来说通常并不理想,因为它们应该以特定的纵横比显示,例如 16x9 或 4x3。

因此,将 VideoPlayer 小部件包装在 AspectRatio 小部件中,以确保视频具有正确的比例。

此外,您必须在 _initializeVideoPlayerFuture() 完成后显示 VideoPlayer 小部件。使用 FutureBuilder 来显示一个加载旋转器,直到控制器完成初始化。注意:初始化控制器不会开始播放。

dart
// Use a FutureBuilder to display a loading spinner while waiting for the
// VideoPlayerController to finish initializing.
FutureBuilder(
  future: _initializeVideoPlayerFuture,
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.done) {
      // If the VideoPlayerController has finished initialization, use
      // the data it provides to limit the aspect ratio of the video.
      return AspectRatio(
        aspectRatio: _controller.value.aspectRatio,
        // Use the VideoPlayer widget to display the video.
        child: VideoPlayer(_controller),
      );
    } else {
      // If the VideoPlayerController is still initializing, show a
      // loading spinner.
      return const Center(
        child: CircularProgressIndicator(),
      );
    }
  },
)

5. 播放和暂停视频

#

默认情况下,视频以暂停状态开始。要开始播放,请调用 VideoPlayerController 提供的 play() 方法。要暂停播放,请调用 pause() 方法。

对于此示例,请在您的应用程序中添加一个 FloatingActionButton,它根据情况显示播放或暂停图标。当用户点击按钮时,如果视频当前处于暂停状态,则播放视频;如果视频正在播放,则暂停视频。

dart
FloatingActionButton(
  onPressed: () {
    // Wrap the play or pause in a call to `setState`. This ensures the
    // correct icon is shown.
    setState(() {
      // If the video is playing, pause it.
      if (_controller.value.isPlaying) {
        _controller.pause();
      } else {
        // If the video is paused, play it.
        _controller.play();
      }
    });
  },
  // Display the correct icon depending on the state of the player.
  child: Icon(
    _controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
  ),
)

完整示例

#
import 'dart:async';

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

void main() => runApp(const VideoPlayerApp());

class VideoPlayerApp extends StatelessWidget {
  const VideoPlayerApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Video Player Demo',
      home: VideoPlayerScreen(),
    );
  }
}

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

  @override
  State<VideoPlayerScreen> createState() => _VideoPlayerScreenState();
}

class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
  late VideoPlayerController _controller;
  late Future<void> _initializeVideoPlayerFuture;

  @override
  void initState() {
    super.initState();

    // Create and store the VideoPlayerController. The VideoPlayerController
    // offers several different constructors to play videos from assets, files,
    // or the internet.
    _controller = VideoPlayerController.networkUrl(
      Uri.parse(
        'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4',
      ),
    );

    // Initialize the controller and store the Future for later use.
    _initializeVideoPlayerFuture = _controller.initialize();

    // Use the controller to loop the video.
    _controller.setLooping(true);
  }

  @override
  void dispose() {
    // Ensure disposing of the VideoPlayerController to free up resources.
    _controller.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Butterfly Video'),
      ),
      // Use a FutureBuilder to display a loading spinner while waiting for the
      // VideoPlayerController to finish initializing.
      body: FutureBuilder(
        future: _initializeVideoPlayerFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            // If the VideoPlayerController has finished initialization, use
            // the data it provides to limit the aspect ratio of the video.
            return AspectRatio(
              aspectRatio: _controller.value.aspectRatio,
              // Use the VideoPlayer widget to display the video.
              child: VideoPlayer(_controller),
            );
          } else {
            // If the VideoPlayerController is still initializing, show a
            // loading spinner.
            return const Center(
              child: CircularProgressIndicator(),
            );
          }
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // Wrap the play or pause in a call to `setState`. This ensures the
          // correct icon is shown.
          setState(() {
            // If the video is playing, pause it.
            if (_controller.value.isPlaying) {
              _controller.pause();
            } else {
              // If the video is paused, play it.
              _controller.play();
            }
          });
        },
        // Display the correct icon depending on the state of the player.
        child: Icon(
          _controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
        ),
      ),
    );
  }
}