Flutter视频播放与AppBar集成插件video_appbar的使用

Flutter视频播放与AppBar集成插件video_appbar的使用

pub package coverage

一个允许在AppBar中播放视频,并且可以自定义每个组件的Flutter插件。

Android iOS macOS Web
支持 SDK 16+ 12.0+ 10.14+ Any*

Demo

移动端 - Android

移动端 - Android (带有前置图标)

平板 - Android

安装

首先,在pubspec.yaml文件中添加video_appbar作为依赖项:

dependencies:
  video_appbar: ^0.0.1+2

依赖项

该插件使用video_player插件。如果你需要了解兼容的格式或其他详细信息,可以访问官方文档。以下是使用基于网络的视频所需的配置:

iOS

如果需要使用http(而不是https)URL访问视频,你需要在应用的Info.plist文件中添加适当的NSAppTransportSecurity权限。该文件位于<项目根目录>/ios/Runner/Info.plist。参见 Apple文档 以确定适合你的用例和受支持的iOS版本的正确组合条目。

Android

如果使用基于网络的视频,请确保在AndroidManifest.xml文件中包含以下权限。该文件位于<项目根目录>/android/app/src/main/AndroidManifest.xml

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

macOS

如果使用基于网络的视频,你需要添加 com.apple.security.network.client 权限。具体操作可以参考 官方文档

示例

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

void main() {
  runApp(const MainApp());
}

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: SafeArea(
        child: Scaffold(
          appBar: VideoAppBar(
            source: VideoAppBarSource.network(
              url: 'https://github.com/jorgemvv01/flutter_video_appbar/raw/main/example/res/video/video_01.mp4'
            ),
            height: 54,
            body: const Center(
              child: Text(
                'Video appbar body',
                style: TextStyle(
                  fontSize: 18,
                  color: Colors.white
                ),
              )
            ),
          ),
        )
      ),
    );
  }
}

Acknowledgements

展示包功能的图像和视频来自官方 Valorant 页面。

示例代码

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

void main() {
  runApp(const MainApp());
}

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      routes: {
        'home': (context) => const HomeScreen(),
        'second': (context) => const SecondScreen()
      },
      initialRoute: 'home',
    );
  }
}

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

  static const characters = [
    'brimstone',
    'phoenix',
    'sage',
    'sova',
    'vyper',
    'cypher'
  ];
  static const mainColor = Color(0xFFff4655);

  [@override](/user/override)
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;
    return SafeArea(
      child: Scaffold(
        backgroundColor: Colors.black87,
        appBar: VideoAppBar(
          source: VideoAppBarSource.asset(dataSource: 'res/video/video_01.mp4'),
          height: 260,
          actions: [
            IconButton(
                onPressed: null,
                icon: Container(
                  padding: const EdgeInsets.all(6),
                  decoration: BoxDecoration(
                      color: mainColor,
                      borderRadius: BorderRadius.circular(25)),
                  child: const Icon(
                    Icons.person,
                    size: 22,
                    color: Colors.white,
                  ),
                ))
          ],
          gradient: LinearGradient(
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter,
              colors: [Colors.black.withOpacity(0.25), Colors.black]),
          body: Center(
            child: Text(
              'VideoAppBar body',
              style: TextStyle(
                  fontSize: 26,
                  color: mainColor.withOpacity(0.6),
                  fontWeight: FontWeight.bold),
            ),
          ),
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            children: [
              Expanded(
                  child: GridView.builder(
                gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
                    maxCrossAxisExtent: size.height * 0.3,
                    mainAxisExtent: size.height * 0.38,
                    mainAxisSpacing: 10,
                    crossAxisSpacing: 10),
                itemCount: characters.length,
                itemBuilder: (_, index) {
                  return CharacterItem(character: characters[index]);
                },
              )),
            ],
          ),
        ),
      ),
    );
  }
}

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

  static const characters = [
    'brimstone',
    'phoenix',
    'sage',
    'sova',
    'vyper',
    'cypher'
  ];
  static const mainColor = Color(0xFFff4655);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        backgroundColor: Colors.black87,
        appBar: VideoAppBar(
          source: VideoAppBarSource.asset(dataSource: 'res/video/video_02.mp4'),
          height: 54,
        ),
        body: Center(
            child: TextButton(
                onPressed: () => Navigator.pop(context),
                child: const Text(
                  'Go to home',
                  style: TextStyle(fontSize: 16),
                ))),
      ),
    );
  }
}

class CharacterItem extends StatelessWidget {
  const CharacterItem({
    super.key,
    required this.character,
  });

  final String character;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return InkWell(
      onTap: () {
        Navigator.pushNamed(context, 'second');
      },
      child: Column(
        children: [
          Expanded(
            child: Image.asset(
              'res/img/$character.webp',
              fit: BoxFit.cover,
            ),
          ),
          Row(
            children: [
              Expanded(
                child: Container(
                  color: Colors.grey[200],
                  child: Text(
                    character.toUpperCase(),
                    style: const TextStyle(
                        fontSize: 16, fontWeight: FontWeight.bold),
                    textAlign: TextAlign.center,
                  ),
                ),
              ),
            ],
          )
        ],
      ),
    );
  }
}

更多关于Flutter视频播放与AppBar集成插件video_appbar的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter视频播放与AppBar集成插件video_appbar的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter应用中使用video_appbar插件来实现视频播放与AppBar集成的代码示例。video_appbar插件允许你在视频播放时动态地显示或隐藏AppBar,从而提供更好的用户体验。

首先,你需要在你的pubspec.yaml文件中添加video_appbarchewie(用于视频播放)的依赖:

dependencies:
  flutter:
    sdk: flutter
  video_player: ^2.2.17  # 确保使用最新版本
  chewie: ^1.2.2  # 确保使用最新版本
  video_appbar: ^0.0.2  # 假设这是插件的最新版本,请检查pub.dev获取实际版本

然后运行flutter pub get来安装这些依赖。

接下来,在你的Dart文件中,你可以这样使用这些插件:

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: VideoScreen(),
    );
  }
}

class VideoScreen extends StatefulWidget {
  @override
  _VideoScreenState createState() => _VideoScreenState();
}

class _VideoScreenState extends State<VideoScreen> {
  late VideoPlayerController _controller;
  late ChewieController _chewieController;

  @override
  void initState() {
    super.initState();
    // 使用网络视频URL初始化VideoPlayerController
    _controller = VideoPlayerController.network(
      'https://www.example.com/video.mp4',
    )..initialize().then((_) {
      // 确保视频已经加载完成后设置ChewieController
      setState(() {
        _chewieController = ChewieController(
          videoPlayerController: _controller,
          aspectRatio: _controller.value.aspectRatio,
          autoPlay: false,
          looping: false,
        );
      });
    });
  }

  @override
  void dispose() {
    _controller.dispose();
    _chewieController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Video with AppBar'),
      ),
      body: _controller.value.isInitialized
          ? VideoAppBar(
              controller: _chewieController,
              child: Center(
                child: Chewie(
                  controller: _chewieController,
                ),
              ),
            )
          : Center(
              child: CircularProgressIndicator(),
            ),
    );
  }
}

在这个示例中,我们做了以下几件事:

  1. 依赖导入:导入了video_playerchewievideo_appbar包。
  2. 视频控制器初始化:在initState方法中,我们初始化了VideoPlayerController并加载了网络视频。一旦视频加载完成,我们就设置了ChewieController
  3. UI构建:在build方法中,我们使用VideoAppBar组件来集成视频播放和AppBar。VideoAppBar接受一个ChewieController和一个子组件,子组件在这里是Chewie播放器。
  4. 资源释放:在dispose方法中,我们释放了视频控制器和Chewie控制器,以避免内存泄漏。

请注意,video_appbar插件的API可能会有所不同,具体取决于其版本和实现。上述代码假设了一个假想的VideoAppBar组件的API,因为实际上并没有一个广泛认可的名为video_appbar的官方或广泛使用的Flutter插件。如果你找到了一个具体的video_appbar插件,请查阅其文档以获取正确的用法。如果这样的插件不存在,你可能需要自己实现类似的逻辑,比如监听视频播放状态来动态显示或隐藏AppBar。

回到顶部