Browse Source

Merge pull request #10 from CaiJingLong/dev

Add example for IJKPlayer in PageView.
Caijinglong 6 years ago
parent
commit
2ca5ff0cc1

+ 30 - 0
README-EN.md

@@ -222,6 +222,36 @@ await controller.reset(); // When this method is called, all native resources ar
 await controller.dispose(); // After this method call, the current controller is theoretically no longer available, resetting dataSource is invalid and may throw an exception.
 await controller.dispose(); // After this method call, the current controller is theoretically no longer available, resetting dataSource is invalid and may throw an exception.
 ```
 ```
 
 
+### Use self controller UI
+
+Use `IJKPlayer`'s `controllerWidgetBuilder` params can customize UI, default use `defaultBuildIjkControllerWidget` method to get widget.
+
+The returned widget will be overwritten on the `Texture`.
+
+```dart
+IJKPlayer(
+  mediaController: IjkMediaController(),
+  controllerWidgetBuilder: (mediaController){
+    return Container(); // your controller widget.
+  },
+);
+```
+
+### Use Texture widget
+
+Use `textureBuilder` params to customize `Texture` widget, use `playerBuilder` in before 0.1.8 version.
+
+Default use `buildDefaultIjkPlayer` method, params is `context,controller,videoInfo` and reture a `Widget`.
+
+```dart
+IJKPlayer(
+  mediaController: IjkMediaController(),
+  textureBuilder: (context,mediaController,videoInfo){
+    return Texture(); /// Your `Texture` widget
+  },
+);
+```
+
 ## LICENSE
 ## LICENSE
 
 
 MIT
 MIT

+ 31 - 1
README.md

@@ -243,7 +243,37 @@ Stream<bool> volumeStream = controller.playingStream;
 ```dart
 ```dart
 await controller.reset(); // 这个方法调用后,会释放所有原生资源,但重新设置dataSource依然可用
 await controller.reset(); // 这个方法调用后,会释放所有原生资源,但重新设置dataSource依然可用
 
 
-await controller.dispose(); //这个方法调用后,当前控制器理论上不再可用,重新设置dataSource无效
+await controller.dispose(); //这个方法调用后,当前控制器理论上不再可用,重新设置dataSource无效,且可能会抛出异常
+```
+
+### 自定义控制器 UI
+
+使用`IJKPlayer`的`controllerWidgetBuilder`属性可以自定义控制器的 UI,默认使用`defaultBuildIjkControllerWidget`方法构建
+
+返回的 Widget 会被覆盖在 Texture 上
+
+```dart
+IJKPlayer(
+  mediaController: IjkMediaController(),
+  controllerWidgetBuilder: (mediaController){
+    return Container(); // 自定义
+  },
+);
+```
+
+### 自定义纹理界面
+
+使用`textureBuilder`属性自定义纹理界面,在 0.1.8 和之前的版本该属性名是`playerBuilder`
+
+默认的方法`buildDefaultIjkPlayer`接受 `context,controller,videoInfo` 参数返回 Widget
+
+```dart
+IJKPlayer(
+  mediaController: IjkMediaController(),
+  textureBuilder: (context,mediaController,videoInfo){
+    return Texture(); // 自定义纹理界面
+  },
+);
 ```
 ```
 
 
 ## Progress
 ## Progress

+ 5 - 2
example/lib/main.dart

@@ -1,6 +1,7 @@
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_ijkplayer/flutter_ijkplayer.dart';
 import 'package:flutter_ijkplayer/flutter_ijkplayer.dart';
 import 'package:ijkplayer_example/page/index.dart';
 import 'package:ijkplayer_example/page/index.dart';
+import 'package:oktoast/oktoast.dart';
 
 
 void main() {
 void main() {
   IjkConfig.isLog = true;
   IjkConfig.isLog = true;
@@ -17,8 +18,10 @@ class MyApp extends StatefulWidget {
 class _MyAppState extends State<MyApp> {
 class _MyAppState extends State<MyApp> {
   @override
   @override
   Widget build(BuildContext context) {
   Widget build(BuildContext context) {
-    return MaterialApp(
-      home: IndexPage(),
+    return OKToast(
+      child: MaterialApp(
+        home: IndexPage(),
+      ),
     );
     );
   }
   }
 }
 }

+ 2 - 0
example/lib/page/index.dart

@@ -4,6 +4,7 @@ import 'package:ijkplayer_example/page/dialog_video_page.dart';
 import 'package:ijkplayer_example/page/full_screen.dart';
 import 'package:ijkplayer_example/page/full_screen.dart';
 import 'package:ijkplayer_example/page/gallery_page.dart';
 import 'package:ijkplayer_example/page/gallery_page.dart';
 import 'package:ijkplayer_example/page/network.dart';
 import 'package:ijkplayer_example/page/network.dart';
+import 'package:ijkplayer_example/page/paging_page.dart';
 import 'package:ijkplayer_example/page/video_list.dart';
 import 'package:ijkplayer_example/page/video_list.dart';
 
 
 class IndexPage extends StatefulWidget {
 class IndexPage extends StatefulWidget {
@@ -27,6 +28,7 @@ class _IndexPageState extends State<IndexPage> {
           buildButton("全屏切换示例(自动)", FullScreen()),
           buildButton("全屏切换示例(自动)", FullScreen()),
           buildButton("全屏切换示例(手动)", FullScreen2()),
           buildButton("全屏切换示例(手动)", FullScreen2()),
           buildButton("在dialog中播放显示视频", DialogVideoPage()),
           buildButton("在dialog中播放显示视频", DialogVideoPage()),
+          buildButton("纵向视频", PagingPickPage()),
         ],
         ],
       ),
       ),
     );
     );

+ 151 - 0
example/lib/page/paging_page.dart

@@ -0,0 +1,151 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_ijkplayer/flutter_ijkplayer.dart';
+import 'package:oktoast/oktoast.dart';
+import 'package:photo/photo.dart';
+
+class PagingPickPage extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: AppBar(
+        title: Text("选择视频"),
+      ),
+      body: ListView(
+        children: <Widget>[
+          FlatButton(
+            child: Text("选择视频并开启"),
+            onPressed: () => pickVideo(context),
+          ),
+        ],
+      ),
+    );
+  }
+
+  pickVideo(BuildContext context) async {
+    var photos = await PhotoPicker.pickAsset(
+      context: context,
+      maxSelected: 8,
+      pickType: PickType.onlyVideo,
+    );
+
+    if (photos == null || photos.isEmpty) {
+      showToast("没选择视频");
+      return;
+    }
+
+    showDialog(
+      context: context,
+      builder: (_) => buildLoadingWidget(),
+    );
+
+    List<DataSource> dataSourceList = [];
+    for (var photo in photos) {
+      var file = await photo.file;
+      dataSourceList.add(DataSource.file(file));
+    }
+
+    Navigator.pop(context);
+
+    Navigator.push(
+      context,
+      MaterialPageRoute(
+        builder: (_) => PagingPage(
+              dataSourceList: dataSourceList,
+            ),
+      ),
+    );
+  }
+}
+
+Widget buildLoadingWidget() {
+  return Center(
+    child: Container(
+      decoration: BoxDecoration(
+        borderRadius: BorderRadius.circular(8),
+        color: Colors.white,
+      ),
+      width: 80,
+      height: 80,
+      padding: EdgeInsets.all(22),
+      child: CircularProgressIndicator(),
+    ),
+  );
+}
+
+class PagingPage extends StatefulWidget {
+  final List<DataSource> dataSourceList;
+
+  const PagingPage({
+    Key key,
+    this.dataSourceList,
+  }) : super(key: key);
+
+  @override
+  _PagingPageState createState() => _PagingPageState();
+}
+
+class _PagingPageState extends State<PagingPage> {
+  Map<DataSource, IjkMediaController> map = {};
+  @override
+  void initState() {
+    super.initState();
+    assert(widget.dataSourceList != null);
+    assert(widget.dataSourceList.isNotEmpty);
+    initFirst();
+  }
+
+  void initFirst() async {
+    await Future.delayed(Duration(seconds: 1));
+    getControllerWithSrc(widget.dataSourceList[0])?.play();
+  }
+
+  @override
+  void dispose() {
+    _disposeAllCtl();
+    super.dispose();
+  }
+
+  _disposeAllCtl() {
+    for (var ctl in map.values) {
+      ctl?.dispose();
+    }
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    assert(widget.dataSourceList != null);
+
+    return PageView.builder(
+      scrollDirection: Axis.vertical,
+      itemBuilder: _buildItem,
+      itemCount: widget.dataSourceList.length,
+      onPageChanged: (current) {
+        print("current page = $current");
+        var src = widget.dataSourceList[current];
+        var ctl = getControllerWithSrc(src);
+        ctl?.pauseOtherController();
+        ctl?.seekTo(0);
+        ctl?.play();
+      },
+    );
+  }
+
+  Widget _buildItem(BuildContext context, int index) {
+    var src = widget.dataSourceList[index];
+    var ctl = getControllerWithSrc(src);
+    return IjkPlayer(
+      mediaController: ctl,
+      controllerWidgetBuilder: (_) => Container(),
+    );
+  }
+
+  IjkMediaController getControllerWithSrc(DataSource src) {
+    var ctl = map[src];
+    if (ctl == null) {
+      ctl = IjkMediaController();
+      map[src] = ctl;
+      ctl.setDataSource(src, autoPlay: false);
+    }
+    return ctl;
+  }
+}

+ 8 - 0
example/pubspec.lock

@@ -67,6 +67,13 @@ packages:
       url: "https://pub.flutter-io.cn"
       url: "https://pub.flutter-io.cn"
     source: hosted
     source: hosted
     version: "1.1.6"
     version: "1.1.6"
+  oktoast:
+    dependency: "direct main"
+    description:
+      name: oktoast
+      url: "https://pub.flutter-io.cn"
+    source: hosted
+    version: "2.1.6"
   path:
   path:
     dependency: transitive
     dependency: transitive
     description:
     description:
@@ -165,3 +172,4 @@ packages:
     version: "2.0.8"
     version: "2.0.8"
 sdks:
 sdks:
   dart: ">=2.2.0 <3.0.0"
   dart: ">=2.2.0 <3.0.0"
+  flutter: ">=0.3.0 <2.0.0"

+ 1 - 0
example/pubspec.yaml

@@ -13,6 +13,7 @@ dependencies:
   # Use with the CupertinoIcons class for iOS style icons.
   # Use with the CupertinoIcons class for iOS style icons.
   cupertino_icons: ^0.1.2
   cupertino_icons: ^0.1.2
   photo: ^0.3.3
   photo: ^0.3.3
+  oktoast: ^2.1.6
 
 
 dev_dependencies:
 dev_dependencies:
   flutter_test:
   flutter_test:

+ 5 - 5
lib/src/ijkplayer.dart

@@ -20,17 +20,17 @@ class IjkPlayer extends StatefulWidget {
   final IjkMediaController mediaController;
   final IjkMediaController mediaController;
 
 
   /// See [DefaultIJKControllerWidget]
   /// See [DefaultIJKControllerWidget]
-  final ControllerWidgetBuilder controllerWidgetBuilder;
+  final IJKControllerWidgetBuilder controllerWidgetBuilder;
 
 
   /// See [buildDefaultIjkPlayer]
   /// See [buildDefaultIjkPlayer]
-  final PlayerBuilder playerBuilder;
+  final IJKTextureBuilder textureBuilder;
 
 
   /// Main Classes of Library
   /// Main Classes of Library
   const IjkPlayer({
   const IjkPlayer({
     Key key,
     Key key,
     @required this.mediaController,
     @required this.mediaController,
     this.controllerWidgetBuilder = defaultBuildIjkControllerWidget,
     this.controllerWidgetBuilder = defaultBuildIjkControllerWidget,
-    this.playerBuilder = buildDefaultIjkPlayer,
+    this.textureBuilder = buildDefaultIjkPlayer,
   }) : super(key: key);
   }) : super(key: key);
 
 
   @override
   @override
@@ -91,8 +91,8 @@ class IjkPlayerState extends State<IjkPlayer> {
   }
   }
 
 
   Widget _buildTexture(int id, VideoInfo info) {
   Widget _buildTexture(int id, VideoInfo info) {
-    if (widget?.playerBuilder != null) {
-      return widget.playerBuilder.call(context, controller, info);
+    if (widget?.textureBuilder != null) {
+      return widget.textureBuilder.call(context, controller, info);
     }
     }
 
 
     if (id == null) {
     if (id == null) {

+ 2 - 2
lib/src/widget/controller_widget_builder.dart

@@ -10,7 +10,7 @@ import 'package:flutter_ijkplayer/src/helper/ui_helper.dart';
 import 'package:flutter_ijkplayer/src/widget/progress_bar.dart';
 import 'package:flutter_ijkplayer/src/widget/progress_bar.dart';
 
 
 /// Using mediaController to Construct a Controller UI
 /// Using mediaController to Construct a Controller UI
-typedef Widget ControllerWidgetBuilder(IjkMediaController controller);
+typedef Widget IJKControllerWidgetBuilder(IjkMediaController controller);
 
 
 /// default create IJK Controller UI
 /// default create IJK Controller UI
 Widget defaultBuildIjkControllerWidget(IjkMediaController controller) {
 Widget defaultBuildIjkControllerWidget(IjkMediaController controller) {
@@ -23,7 +23,7 @@ Widget defaultBuildIjkControllerWidget(IjkMediaController controller) {
 
 
 /// Default Controller Widget
 /// Default Controller Widget
 ///
 ///
-/// see [IjkPlayer] and [ControllerWidgetBuilder]
+/// see [IjkPlayer] and [IJKControllerWidgetBuilder]
 class DefaultIJKControllerWidget extends StatefulWidget {
 class DefaultIJKControllerWidget extends StatefulWidget {
   final IjkMediaController controller;
   final IjkMediaController controller;
 
 

+ 1 - 1
lib/src/widget/ijkplayer_builder.dart

@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
 import 'package:flutter_ijkplayer/flutter_ijkplayer.dart';
 import 'package:flutter_ijkplayer/flutter_ijkplayer.dart';
 
 
 /// Player builder, Inheritance of this class allows you to implement your own player
 /// Player builder, Inheritance of this class allows you to implement your own player
-typedef Widget PlayerBuilder(
+typedef Widget IJKTextureBuilder(
   BuildContext context,
   BuildContext context,
   IjkMediaController controller,
   IjkMediaController controller,
   VideoInfo info,
   VideoInfo info,