Flutter画中画功能插件pip_flutter的使用
Flutter画中画功能插件pip_flutter的使用
pip_flutter
是一个用于在Android和iOS上实现视频画中画模式的Flutter插件。通过该插件,你可以在你的应用中轻松地将视频设置为画中画模式。
使用示例
以下是一个完整的示例,展示如何使用 pip_flutter
插件来实现画中画功能。
import 'package:flutter/material.dart';
import 'package:pip_flutter/pipflutter_player.dart';
import 'package:pip_flutter/pipflutter_player_configuration.dart';
import 'package:pip_flutter/pipflutter_player_controller.dart';
import 'package:pip_flutter/pipflutter_player_data_source.dart';
import 'package:pip_flutter/pipflutter_player_data_source_type.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.pink,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Picture in Picture Mode'),
),
body: Center(
child: InkWell(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => PictureInPicturePage()));
},
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: Center(
child: Container(
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
decoration: BoxDecoration(color: Colors.pink, borderRadius: BorderRadius.circular(12.0)),
child: const Text(
'Picture in Picture Mode',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16),
),
),
),
),
),
),
);
}
}
class PictureInPicturePage extends StatefulWidget {
@override
_PictureInPicturePageState createState() => _PictureInPicturePageState();
}
class _PictureInPicturePageState extends State<PictureInPicturePage> {
late PipFlutterPlayerController pipFlutterPlayerController;
final GlobalKey pipFlutterPlayerKey = GlobalKey();
@override
void initState() {
PipFlutterPlayerConfiguration pipFlutterPlayerConfiguration =
const PipFlutterPlayerConfiguration(
aspectRatio: 16 / 9,
fit: BoxFit.contain,
);
PipFlutterPlayerDataSource dataSource = PipFlutterPlayerDataSource(
PipFlutterPlayerDataSourceType.network,
'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
);
pipFlutterPlayerController =
PipFlutterPlayerController(pipFlutterPlayerConfiguration);
pipFlutterPlayerController.setupDataSource(dataSource);
pipFlutterPlayerController.setPipFlutterPlayerGlobalKey(pipFlutterPlayerKey);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Picture in Picture player"),
leading: IconButton(
onPressed: () {
Navigator.of(context).pop();
},
icon: const Icon(Icons.arrow_back_ios, color: Colors.white),
),
),
body: Column(
children: [
const SizedBox(height: 20),
Flexible(
flex: 1,
fit: FlexFit.loose,
child: AspectRatio(
aspectRatio: 16 / 9,
child: PipFlutterPlayer(
controller: pipFlutterPlayerController,
key: pipFlutterPlayerKey,
),
),
),
Container(
margin: const EdgeInsets.only(top: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
InkWell(
child: Container(
width: MediaQuery.of(context).size.width * 0.4,
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
decoration: BoxDecoration(color: Colors.pink, borderRadius: BorderRadius.circular(12.0)),
child: const Center(child: Text("Show PiP", style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold))),
),
onTap: () {
pipFlutterPlayerController.enablePictureInPicture(pipFlutterPlayerKey);
},
),
InkWell(
child: Container(
width: MediaQuery.of(context).size.width * 0.4,
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(8.0),
decoration: BoxDecoration(color: Colors.pink, borderRadius: BorderRadius.circular(12.0)),
child: Center(child: const Text("Disable PiP", style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold))),
),
onTap: () async {
pipFlutterPlayerController.disablePictureInPicture();
},
),
],
),
),
],
),
);
}
}
安装
首先,在你的 pubspec.yaml
文件中添加 pip_flutter
依赖:
dependencies:
pip_flutter: ^x.x.x
然后运行 flutter pub get
来安装依赖。
Android 配置
在 AndroidManifest.xml
文件中添加以下权限和配置:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<activity
android:name=".MainActivity"
android:supportsPictureInPicture="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"
android:exported="true"/>
<service
android:name=".PipFlutterPlayerService"
android:stopWithTask="false" />
iOS 配置
在 Xcode 中设置 iOS 的部署信息为 11.0,并在 Info.plist
文件中添加以下配置:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSBonjourServices</key>
<array>
<string>_dartobservatory._tcp</string>
</array>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
<string>processing</string>
<string>remote-notification</string>
</array>
更多关于Flutter画中画功能插件pip_flutter的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter画中画功能插件pip_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
pip_flutter
是一个用于在 Flutter 应用中实现画中画(Picture-in-Picture, PiP)功能的插件。它允许你将应用中的某个视图(如视频播放器)缩小并悬浮在其他应用或主界面上方。
以下是如何使用 pip_flutter
插件的基本步骤:
1. 添加依赖
首先,在 pubspec.yaml
文件中添加 pip_flutter
插件的依赖:
dependencies:
flutter:
sdk: flutter
pip_flutter: ^1.0.0 # 使用最新版本
然后运行 flutter pub get
来安装依赖。
2. 导入插件
在需要使用画中画功能的 Dart 文件中导入插件:
import 'package:pip_flutter/pip_flutter.dart';
3. 初始化 PiP 模式
在应用中初始化 PiP 模式。通常,你可以在 initState
方法中进行初始化:
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
PipFlutter.initialize();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('PiP Flutter Example'),
),
body: Center(
child: ElevatedButton(
onPressed: _enterPipMode,
child: Text('Enter PiP Mode'),
),
),
),
);
}
void _enterPipMode() async {
await PipFlutter.enterPipMode();
}
}
4. 进入 PiP 模式
在需要进入 PiP 模式的地方,调用 PipFlutter.enterPipMode()
方法。例如,在按钮的 onPressed
回调中:
ElevatedButton(
onPressed: _enterPipMode,
child: Text('Enter PiP Mode'),
);
5. 处理 PiP 模式的生命周期
你可以监听 PiP 模式的状态变化,以便在 PiP 模式进入或退出时执行相应的操作:
PipFlutter.onPipModeChanged.listen((isInPipMode) {
if (isInPipMode) {
print('Entered PiP Mode');
} else {
print('Exited PiP Mode');
}
});
6. 自定义 PiP 视图
你可以自定义 PiP 模式下的视图内容。例如,可以在进入 PiP 模式时显示一个视频播放器:
void _enterPipMode() async {
await PipFlutter.enterPipMode(
builder: (context) {
return Container(
color: Colors.black,
child: Center(
child: VideoPlayer(_controller),
),
);
},
);
}
7. 退出 PiP 模式
你可以通过调用 PipFlutter.exitPipMode()
方法手动退出 PiP 模式:
void _exitPipMode() async {
await PipFlutter.exitPipMode();
}
8. 处理 PiP 模式的限制
请注意,PiP 模式在某些设备或 Android 版本上可能不可用。你可以通过 PipFlutter.isPipAvailable
来检查是否支持 PiP 模式:
if (PipFlutter.isPipAvailable) {
// PiP mode is available
} else {
// PiP mode is not available
}
9. 处理 PiP 模式的配置
你可以在 AndroidManifest.xml
文件中配置 PiP 模式的行为。例如,设置 PiP 模式的最小尺寸:
<activity
android:name=".MainActivity"
android:supportsPictureInPicture="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:resizeableActivity="true">
<meta-data
android:name="android.picture_in_picture.minimum_width"
android:value="200"/>
<meta-data
android:name="android.picture_in_picture.minimum_height"
android:value="200"/>
</activity>
10. 处理 PiP 模式的事件
你可以在 MainActivity
中重写 onPictureInPictureModeChanged
方法,以处理 PiP 模式的事件:
[@Override](/user/Override)
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
if (isInPictureInPictureMode) {
// Entered PiP mode
} else {
// Exited PiP mode
}
}