Przeglądaj źródła

Merge pull request #152 from CaiJingLong/change-full-screen

Change full screen
Caijinglong 6 lat temu
rodzic
commit
8a1e77a3fd

+ 2 - 1
.gitignore

@@ -6,4 +6,5 @@
 
 build/
 .idea
-doc/
+doc/
+pubspec.lock

+ 1 - 1
BUG.md

@@ -1,6 +1,6 @@
 ## all
 
-- [ ] 全屏模式可自定义
+- [x] 全屏模式可自定义
 
 ## iOS
 

+ 7 - 0
CHANGELOG.md

@@ -1,3 +1,10 @@
+## 0.3.5
+
+Feature:
+
+- Hide the status bar when entering full screen
+- The callback when the full screen state changes for `DefaultIJKControllerWidget`.
+
 ## 0.3.4
 
 Fix:

+ 20 - 11
README.md

@@ -438,17 +438,26 @@ IJKPlayer(
 
 这个类提供了一些属性进行自定义, 除`controller`外所有属性均为可选:
 
-|               name                |            type            |      default      |                      desc                       |
-| :-------------------------------: | :------------------------: | :---------------: | :---------------------------------------------: |
-|           doubleTapPlay           |            bool            |       false       |                  双击播放暂停                   |
-|          verticalGesture          |            bool            |       true        |                    纵向手势                     |
-|         horizontalGesture         |            bool            |       true        |                    横向手势                     |
-|            volumeType             |         VolumeType         | VolumeType.system |        纵向手势改变的声音类型(系统,媒体)        |
-|        playWillPauseOther         |            bool            |       true        |            播放当前是否暂停其他媒体             |
-|      currentFullScreenState       |            bool            |       false       | **如果你是自定义全屏界面, 这个必须设置为 true** |
-|       showFullScreenButton        |            bool            |       true        |                是否显示全屏按钮                 |
-| fullscreenControllerWidgetBuilder | IJKControllerWidgetBuilder |                   |              可以自定义全屏的界面               |
-|          fullScreenType           |       FullScreenType       |                   |     全屏的类型(旋转屏幕,或是使用 RotateBox)     |
+|               name                |            type            |      default      |                              desc                              |
+| :-------------------------------: | :------------------------: | :---------------: | :------------------------------------------------------------: |
+|           doubleTapPlay           |            bool            |       false       |                          双击播放暂停                          |
+|          verticalGesture          |            bool            |       true        |                            纵向手势                            |
+|         horizontalGesture         |            bool            |       true        |                            横向手势                            |
+|            volumeType             |         VolumeType         | VolumeType.system |               纵向手势改变的声音类型(系统,媒体)                |
+|        playWillPauseOther         |            bool            |       true        |                    播放当前是否暂停其他媒体                    |
+|      currentFullScreenState       |            bool            |       false       |        **如果你是自定义全屏界面, 这个必须设置为 true**         |
+|       showFullScreenButton        |            bool            |       true        |                        是否显示全屏按钮                        |
+| fullscreenControllerWidgetBuilder | IJKControllerWidgetBuilder |                   |                      可以自定义全屏的界面                      |
+|          fullScreenType           |       FullScreenType       |                   |            全屏的类型(旋转屏幕,或是使用 RotateBox)             |
+|     hideSystemBarOnFullScreen     |            bool            |       true        |         进入全屏时,是否自动隐藏状态栏(请看额外说明 1)          |
+|           onFullScreen            |    void Function(bool)     |       null        | 全屏状态改变时的回调, 参数为 true 是全屏状态, false 为普通状态 |
+
+**额外说明 1**: ios 需要向 Info.plist 添加一条属性
+
+```xml
+<key>UIViewControllerBasedStatusBarAppearance</key>
+<true/>
+```
 
 ### 自定义纹理界面
 

+ 32 - 17
android/src/main/java/top/kikt/ijkplayer/IjkplayerPlugin.kt

@@ -15,13 +15,13 @@ import tv.danmaku.ijk.media.player.IjkMediaPlayer
  * IjkplayerPlugin
  */
 class IjkplayerPlugin(private val registrar: Registrar) : MethodCallHandler {
-
+    
     override fun onMethodCall(call: MethodCall, result: Result) {
         IjkMediaPlayer.loadLibrariesOnce(null)
         IjkMediaPlayer.native_profileBegin("libijkplayer.so")
         handleMethodCall(call, result)
     }
-
+    
     private fun handleMethodCall(call: MethodCall, result: Result) {
         when (call.method) {
             "init" -> {
@@ -76,25 +76,40 @@ class IjkplayerPlugin(private val registrar: Registrar) : MethodCallHandler {
                 setBrightness(WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE)
                 result.success(true)
             }
+            "showStatusBar" -> {
+                val show = call.arguments<Boolean>()
+                setStatusBar(show)
+            }
             else -> result.notImplemented()
         }
     }
-
+    
+    private fun setStatusBar(show: Boolean) {
+        val window = registrar.activity()?.window ?: return
+        if (show) {
+            window.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
+            window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+        } else {
+            window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
+            window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN)
+        }
+    }
+    
     private fun getSystemVolume(): Int {
         val max = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC).toFloat()
         return (audioManager.getStreamVolume(AudioManager.STREAM_MUSIC).toFloat() / max * 100).toInt()
     }
-
+    
     private fun setVolume(volume: Int) {
         audioManager.apply {
             val max = getStreamMaxVolume(AudioManager.STREAM_MUSIC)
-
+            
             val step = 100.toFloat() / max.toFloat()
-
+            
             val current = getSystemVolume()
-
+            
             val progress = current * step
-
+            
             if (volume > progress) {
                 volumeDown()
             } else if (volume < progress) {
@@ -102,42 +117,42 @@ class IjkplayerPlugin(private val registrar: Registrar) : MethodCallHandler {
             }
         }
     }
-
+    
     private fun volumeUp() {
         audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, AudioManager.FLAG_PLAY_SOUND)
     }
-
+    
     private fun volumeDown() {
         audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, AudioManager.FLAG_PLAY_SOUND)
     }
-
+    
     private val audioManager: AudioManager
         get() = registrar.activity().getSystemService(Context.AUDIO_SERVICE) as AudioManager
-
+    
     private fun setBrightness(brightness: Float) {
         val window = registrar.activity().window
         val lp = window.attributes
         lp.screenBrightness = brightness
         window.attributes = lp
     }
-
+    
     private fun getBrightness(): Float {
         val window = registrar.activity().window
         val lp = window.attributes
         return lp.screenBrightness
     }
-
+    
     fun MethodCall.getLongArg(key: String): Long {
         return this.argument<Int>(key)!!.toLong()
     }
-
+    
     fun MethodCall.getLongArg(): Long {
         return this.arguments<Int>().toLong()
     }
-
+    
     companion object {
         lateinit var manager: IjkManager
-
+        
         /**
          * Plugin registration.
          */

+ 9 - 0
example/ios/Flutter/flutter_export_environment.sh

@@ -0,0 +1,9 @@
+#!/bin/sh
+# This is a generated file; do not edit or check into version control.
+export "FLUTTER_ROOT=/Volumes/Evo512/sdk/flutter/flutter_beta"
+export "FLUTTER_APPLICATION_PATH=/Users/cai/Documents/GitHub/flutter_ijkplayer/example"
+export "FLUTTER_TARGET=/Users/cai/Documents/GitHub/flutter_ijkplayer/example/lib/main.dart"
+export "FLUTTER_BUILD_DIR=build"
+export "SYMROOT=${SOURCE_ROOT}/../build/ios"
+export "FLUTTER_FRAMEWORK_DIR=/Volumes/Evo512/sdk/flutter/flutter_beta/bin/cache/artifacts/engine/ios"
+export "TRACK_WIDGET_CREATION=true"

+ 3 - 3
example/ios/Podfile.lock

@@ -13,7 +13,7 @@ DEPENDENCIES:
   - photo_manager (from `/Users/cai/.pub-cache/hosted/pub.flutter-io.cn/photo_manager-0.3.4/ios/photo_manager.podspec`)
 
 SPEC REPOS:
-  https://github.com/cocoapods/specs.git:
+  https://github.com/CocoaPods/Specs.git:
     - FlutterIJK
 
 EXTERNAL SOURCES:
@@ -25,11 +25,11 @@ EXTERNAL SOURCES:
     :path: "/Users/cai/.pub-cache/hosted/pub.flutter-io.cn/photo_manager-0.3.4/ios/photo_manager.podspec"
 
 SPEC CHECKSUMS:
-  Flutter: 58dd7d1b27887414a370fcccb9e645c08ffd7a6a
+  Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
   flutter_ijkplayer: ef9006131553deb6d8ae6d7fbd3bcbf93b135930
   FlutterIJK: 68b00c1d11162b5016f3611853aa699e198bd1d2
   photo_manager: d47ddf6cb25cbfa837dc334540eb9a99b208e191
 
 PODFILE CHECKSUM: a14c63eb48a9d676ed6d876506b3258fd9c85235
 
-COCOAPODS: 1.7.5
+COCOAPODS: 1.8.4

+ 7 - 3
example/ios/Runner.xcodeproj/project.pbxproj

@@ -198,6 +198,7 @@
 			developmentRegion = English;
 			hasScannedForEncodings = 0;
 			knownRegions = (
+				English,
 				en,
 				Base,
 			);
@@ -379,7 +380,7 @@
 			baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+				CURRENT_PROJECT_VERSION = 1;
 				DEVELOPMENT_TEAM = 344756CAN4;
 				ENABLE_BITCODE = NO;
 				FRAMEWORK_SEARCH_PATHS = (
@@ -392,6 +393,7 @@
 					"$(inherited)",
 					"$(PROJECT_DIR)/Flutter",
 				);
+				MARKETING_VERSION = 1.0.0;
 				PRODUCT_BUNDLE_IDENTIFIER = top.kikt.ijkplayer.example;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				VALID_ARCHS = "arm64 arm64e";
@@ -506,7 +508,7 @@
 			baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+				CURRENT_PROJECT_VERSION = 1;
 				DEVELOPMENT_TEAM = 344756CAN4;
 				ENABLE_BITCODE = NO;
 				FRAMEWORK_SEARCH_PATHS = (
@@ -519,6 +521,7 @@
 					"$(inherited)",
 					"$(PROJECT_DIR)/Flutter",
 				);
+				MARKETING_VERSION = 1.0.0;
 				PRODUCT_BUNDLE_IDENTIFIER = top.kikt.ijkplayer.example;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				VALID_ARCHS = "arm64 arm64e";
@@ -531,7 +534,7 @@
 			baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-				CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+				CURRENT_PROJECT_VERSION = 1;
 				DEVELOPMENT_TEAM = 344756CAN4;
 				ENABLE_BITCODE = NO;
 				FRAMEWORK_SEARCH_PATHS = (
@@ -544,6 +547,7 @@
 					"$(inherited)",
 					"$(PROJECT_DIR)/Flutter",
 				);
+				MARKETING_VERSION = 1.0.0;
 				PRODUCT_BUNDLE_IDENTIFIER = top.kikt.ijkplayer.example;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				VALID_ARCHS = "arm64 arm64e";

+ 8 - 0
example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDEDidComputeMac32BitWarning</key>
+	<true/>
+</dict>
+</plist>

+ 2 - 8
example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme

@@ -26,10 +26,7 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       shouldUseLaunchSchemeArgsEnv = "YES">
-      <Testables>
-      </Testables>
       <MacroExpansion>
          <BuildableReference
             BuildableIdentifier = "primary"
@@ -39,14 +36,13 @@
             ReferencedContainer = "container:Runner.xcodeproj">
          </BuildableReference>
       </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
+      <Testables>
+      </Testables>
    </TestAction>
    <LaunchAction
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      language = ""
       launchStyle = "0"
       useCustomWorkingDirectory = "NO"
       ignoresPersistentStateOnLaunch = "NO"
@@ -63,8 +59,6 @@
             ReferencedContainer = "container:Runner.xcodeproj">
          </BuildableReference>
       </BuildableProductRunnable>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Profile"

+ 3 - 3
example/ios/Runner/Info.plist

@@ -15,11 +15,11 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>$(FLUTTER_BUILD_NAME)</string>
+	<string>$(MARKETING_VERSION)</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>
-	<string>$(FLUTTER_BUILD_NUMBER)</string>
+	<string>$(CURRENT_PROJECT_VERSION)</string>
 	<key>LSRequiresIPhoneOS</key>
 	<true/>
 	<key>NSPhotoLibraryUsageDescription</key>
@@ -47,6 +47,6 @@
 		<string>UIInterfaceOrientationLandscapeRight</string>
 	</array>
 	<key>UIViewControllerBasedStatusBarAppearance</key>
-	<false/>
+	<true/>
 </dict>
 </plist>

+ 3 - 0
example/lib/const/video_datasource.dart

@@ -4,6 +4,9 @@ class VideoDataSource {
   static final springBootMenuM3u8 = DataSource.network(
       "https://media001.geekbang.org/f433fd1ce5e84d27b1101f0dad72a126/de563bb4aba94b5f95f448b33be4dd9f-9aede6861be944d696fe365f3a33b7b4-sd.m3u8");
 
+  static final ai = DataSource.network(
+      "http://img.ksbbs.com/asset/Mon_1703/05cacb4e02f9d9e.mp4");
+
   static final reportErrorM3u8FromAliyun = DataSource.network(
       "https://outin-4839d24d670f11e988c600163e1a3b4a.oss-cn-shanghai.aliyuncs.com/2b9f4f2d1c4d4985a11352cb1970fead/86c3f36ed4e1cd5539ed347282725b3e-fd-encrypt-stream.m3u8?Expires=1563162783&OSSAccessKeyId=LTAIrkwb21KyGjJl&Signature=y4m98BAzJUQVzFwHszQS%2BFGtq5A%3D");
 }

+ 58 - 0
example/lib/page/developing/crash_on_set_src_page.dart

@@ -0,0 +1,58 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_ijkplayer/flutter_ijkplayer.dart';
+
+class CrashOnSetSrcPage extends StatefulWidget {
+  @override
+  _CrashOnSetSrcPageState createState() => _CrashOnSetSrcPageState();
+}
+
+class _CrashOnSetSrcPageState extends State<CrashOnSetSrcPage> {
+  IjkMediaController controller;
+
+  List<String> networkList = [
+    "http://playertest.longtailvideo.com/adaptive/bipbop/gear4/prog_index.m3u8",
+    "http://img.ksbbs.com/asset/Mon_1703/05cacb4e02f9d9e.mp4",
+    "https://media001.geekbang.org/f433fd1ce5e84d27b1101f0dad72a126/de563bb4aba94b5f95f448b33be4dd9f-9aede6861be944d696fe365f3a33b7b4-sd.m3u8",
+  ];
+
+  int currentIndex = 0;
+
+  @override
+  void initState() {
+    super.initState();
+    controller = IjkMediaController();
+  }
+
+  @override
+  void dispose() {
+    controller.dispose();
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: AppBar(
+        title: Text("切换数据崩溃"),
+      ),
+      body: ListView(
+        children: <Widget>[
+          AspectRatio(
+            aspectRatio: 1,
+            child: IjkPlayer(
+              mediaController: controller,
+            ),
+          ),
+        ],
+      ),
+      floatingActionButton: FloatingActionButton(
+        onPressed: () {
+          final url = networkList[currentIndex];
+          controller.setDataSource(DataSource.network(url), autoPlay: true);
+          currentIndex++;
+          currentIndex %= networkList.length;
+        },
+      ),
+    );
+  }
+}

+ 4 - 0
example/lib/page/developing/develop_index.dart

@@ -1,5 +1,7 @@
 import 'package:flutter/material.dart';
+import 'package:ijkplayer_example/page/developing/test_hide_system_bar.dart';
 
+import 'crash_on_set_src_page.dart';
 import 'develop_prepare_page.dart';
 import 'live_interruption_page.dart';
 import 'new_full_screen_page.dart';
@@ -20,9 +22,11 @@ class DevelopingIndexPageState extends State<DevelopingIndexPage> {
       body: ListView(
         children: <Widget>[
           buildButton("developing preare page", ForPreparePage()),
+          buildButton("切换视频源crash", CrashOnSetSrcPage()),
           buildButton("直播中断", LiveInterruptionPage()),
           buildButton("视频源错误", SreErrorPage()),
           buildButton("新的全屏", NewFullScreenPage()),
+          buildButton("隐藏或显示状态栏", TestHideSystemBar()),
         ],
       ),
     );

+ 34 - 0
example/lib/page/developing/test_hide_system_bar.dart

@@ -0,0 +1,34 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_ijkplayer/flutter_ijkplayer.dart';
+
+class TestHideSystemBar extends StatefulWidget {
+  @override
+  _TestHideSystemBarState createState() => _TestHideSystemBarState();
+}
+
+class _TestHideSystemBarState extends State<TestHideSystemBar> {
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      appBar: AppBar(
+        title: Text("Test system bar"),
+      ),
+      body: Column(
+        children: <Widget>[
+          FlatButton(
+            child: Text("show"),
+            onPressed: () => show(true),
+          ),
+          FlatButton(
+            child: Text("hide"),
+            onPressed: () => show(false),
+          ),
+        ],
+      ),
+    );
+  }
+
+  show(bool show) {
+    IjkManager.showStatusBar(show);
+  }
+}

+ 2 - 1
example/lib/page/screen_shot_page.dart

@@ -25,7 +25,8 @@ class _ScreenShotPageState extends State<ScreenShotPage> {
         TargetPlatform.iOS,
       ],
       [
-        IjkOption(IjkOptionCategory.player, "mediacodec", 0),
+        // IjkOption(IjkOptionCategory.player, "mediacodec", 1),
+        // IjkOption(IjkOptionCategory.player, "videotoolbox", 1),
       ],
     );
     mediaController.setDataSource(

+ 0 - 285
example/pubspec.lock

@@ -1,285 +0,0 @@
-# Generated by pub
-# See https://dart.dev/tools/pub/glossary#lockfile
-packages:
-  analyzer:
-    dependency: transitive
-    description:
-      name: analyzer
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "0.35.4"
-  args:
-    dependency: transitive
-    description:
-      name: args
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.5.1"
-  async:
-    dependency: transitive
-    description:
-      name: async
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "2.2.0"
-  boolean_selector:
-    dependency: transitive
-    description:
-      name: boolean_selector
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.0.4"
-  charcode:
-    dependency: transitive
-    description:
-      name: charcode
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.1.2"
-  collection:
-    dependency: transitive
-    description:
-      name: collection
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.14.11"
-  convert:
-    dependency: transitive
-    description:
-      name: convert
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "2.1.1"
-  crypto:
-    dependency: transitive
-    description:
-      name: crypto
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "2.0.6"
-  cupertino_icons:
-    dependency: "direct main"
-    description:
-      name: cupertino_icons
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "0.1.2"
-  dart_style:
-    dependency: transitive
-    description:
-      name: dart_style
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.2.4"
-  flutter:
-    dependency: "direct main"
-    description: flutter
-    source: sdk
-    version: "0.0.0"
-  flutter_ijkplayer:
-    dependency: "direct main"
-    description:
-      path: ".."
-      relative: true
-    source: path
-    version: "0.3.4"
-  flutter_localizations:
-    dependency: "direct main"
-    description: flutter
-    source: sdk
-    version: "0.0.0"
-  flutter_test:
-    dependency: "direct dev"
-    description: flutter
-    source: sdk
-    version: "0.0.0"
-  front_end:
-    dependency: transitive
-    description:
-      name: front_end
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "0.1.14"
-  glob:
-    dependency: transitive
-    description:
-      name: glob
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.1.7"
-  intl:
-    dependency: "direct main"
-    description:
-      name: intl
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "0.15.8"
-  intl_translation:
-    dependency: "direct dev"
-    description:
-      name: intl_translation
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "0.17.3"
-  kernel:
-    dependency: transitive
-    description:
-      name: kernel
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "0.3.14"
-  matcher:
-    dependency: transitive
-    description:
-      name: matcher
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "0.12.5"
-  meta:
-    dependency: transitive
-    description:
-      name: meta
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.1.6"
-  oktoast:
-    dependency: "direct main"
-    description:
-      name: oktoast
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "2.1.7"
-  package_config:
-    dependency: transitive
-    description:
-      name: package_config
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.0.5"
-  path:
-    dependency: transitive
-    description:
-      name: path
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.6.2"
-  pedantic:
-    dependency: transitive
-    description:
-      name: pedantic
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.7.0"
-  petitparser:
-    dependency: transitive
-    description:
-      name: petitparser
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "2.2.1"
-  photo:
-    dependency: "direct main"
-    description:
-      name: photo
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "0.3.4"
-  photo_manager:
-    dependency: transitive
-    description:
-      name: photo_manager
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "0.3.4"
-  pub_semver:
-    dependency: transitive
-    description:
-      name: pub_semver
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.4.2"
-  quiver:
-    dependency: transitive
-    description:
-      name: quiver
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "2.0.3"
-  sky_engine:
-    dependency: transitive
-    description: flutter
-    source: sdk
-    version: "0.0.99"
-  source_span:
-    dependency: transitive
-    description:
-      name: source_span
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.5.5"
-  stack_trace:
-    dependency: transitive
-    description:
-      name: stack_trace
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.9.3"
-  stream_channel:
-    dependency: transitive
-    description:
-      name: stream_channel
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "2.0.0"
-  string_scanner:
-    dependency: transitive
-    description:
-      name: string_scanner
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.0.4"
-  term_glyph:
-    dependency: transitive
-    description:
-      name: term_glyph
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.1.0"
-  test_api:
-    dependency: transitive
-    description:
-      name: test_api
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "0.2.5"
-  typed_data:
-    dependency: transitive
-    description:
-      name: typed_data
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.1.6"
-  vector_math:
-    dependency: transitive
-    description:
-      name: vector_math
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "2.0.8"
-  watcher:
-    dependency: transitive
-    description:
-      name: watcher
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "0.9.7+10"
-  yaml:
-    dependency: transitive
-    description:
-      name: yaml
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "2.1.15"
-sdks:
-  dart: ">=2.2.2 <3.0.0"
-  flutter: ">=0.3.0 <2.0.0"

+ 19 - 0
ios/Classes/FlutterViewController+CoolStatusBarHidden.h

@@ -0,0 +1,19 @@
+//
+//  FlutterViewController+CoolViewController.h
+//  flutter_ijkplayer
+//
+//  Created by Caijinglong on 2019/11/8.
+//
+#import <Flutter/Flutter.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface FlutterViewController (CoolViewController)
+
+-(void)showStatusBar;
+
+-(void)hideStatusBar;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 44 - 0
ios/Classes/FlutterViewController+CoolStatusBarHidden.m

@@ -0,0 +1,44 @@
+//
+//  FlutterViewController+CoolViewController.m
+//  flutter_ijkplayer
+//
+//  Created by Caijinglong on 2019/11/8.
+//
+
+#import "FlutterViewController+CoolStatusBarHidden.h"
+#import <objc/runtime.h>
+
+@implementation FlutterViewController (CoolViewController)
+
+-(void)showStatusBar{
+    objc_setAssociatedObject(self, @selector(showStatusBar), @"show", OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+    [UIView animateWithDuration:1 animations:^{
+          [self setNeedsStatusBarAppearanceUpdate];
+    }];
+}
+
+-(void)hideStatusBar{
+    objc_setAssociatedObject(self, @selector(showStatusBar), @"hide", OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+    [UIView animateWithDuration:1 animations:^{
+          [self setNeedsStatusBarAppearanceUpdate];
+    }];
+}
+
+-(BOOL)isStatusBarShow{
+    NSString *value = objc_getAssociatedObject(self, @selector(showStatusBar));
+    return ![value isEqualToString:@"hide"];
+}
+
+- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation{
+    return UIStatusBarAnimationFade;
+}
+
+-(BOOL)prefersStatusBarHidden{
+    return ![self isStatusBarShow];
+}
+
+-(void)viewDidDisappear:(BOOL)animated{
+    objc_removeAssociatedObjects(self);
+}
+
+@end

+ 47 - 2
ios/Classes/IjkplayerPlugin.m

@@ -2,6 +2,7 @@
 #import "IjkplayerPlugin.h"
 #import "CoolFlutterIjkManager.h"
 #import "CoolFlutterIJK.h"
+#import "FlutterViewController+CoolStatusBarHidden.h"
 
 NSString *flutterOrientationNotifyName = @"io.flutter.plugin.platform.SystemChromeOrientationNotificationName";
 const NSString *flutterOrientationNotifyKey = @"io.flutter.plugin.platform.SystemChromeOrientationNotificationKey";
@@ -115,6 +116,9 @@ static IjkplayerPlugin *__sharedInstance;
         } else if([@"unlockOrientation" isEqualToString:call.method]){
             [self unlockOrientation];
             result(@YES);
+        } else if([@"showStatusBar" isEqualToString:call.method]) {
+            BOOL showStatusBar = [call.arguments boolValue];
+            [self setStatusBarToShow:showStatusBar];
         } else {
             result(FlutterMethodNotImplemented);
         }
@@ -146,7 +150,7 @@ static IjkplayerPlugin *__sharedInstance;
     for (id number in orientations) {
         int value = [number intValue];
         UIDeviceOrientation orientation = [self convertIntToOrientation:value];
-        NSLog(@"orientation = %ld",orientation);
+        NSLog(@"orientation = %ld",(long)orientation);
         if (orientation == UIDeviceOrientationPortrait){
             mask |= UIInterfaceOrientationMaskPortrait;
         }else if (orientation == UIDeviceOrientationLandscapeLeft) {
@@ -306,8 +310,49 @@ static IjkplayerPlugin *__sharedInstance;
 //    [volumeView removeFromSuperview];
 }
 
--(void) hideSystemVolumeBar {
+-(void)hideSystemVolumeBar {
+    
+}
+
+-(void)setStatusBarToShow:(BOOL)show{
+    UIViewController *ctl = [self getCurrentUIViewController];
+    if([ctl isKindOfClass:[FlutterViewController class] ]){
+        FlutterViewController *fCtl = (FlutterViewController*)ctl;
+        if(show){
+            [fCtl showStatusBar];
+        }else{
+            [fCtl hideStatusBar];
+        }
+    }
+}
+
+-(UIViewController*) getCurrentUIViewController{
+    UIViewController *result = nil;
+    UIWindow *window = [[UIApplication sharedApplication] keyWindow];
+    
+    if(window.windowLevel != UIWindowLevelNormal){
+        NSArray *windows =[[UIApplication sharedApplication ]windows];
+        for(UIWindow *tmp in windows){
+            window = tmp;
+            break;
+        }
+    }
+    
+    result = window.rootViewController;
+    
+    while (result.presentedViewController) {
+        result = result.presentedViewController;
+    }
+    
+    if([result isKindOfClass:[UITabBarController class]]){
+        result = [(UITabBarController*)result selectedViewController];
+    }
+    
+    if([result isKindOfClass:[UINavigationController class]]){
+        result = [(UINavigationController*) result visibleViewController];
+    }
     
+    return result;
 }
 
 @end

+ 6 - 0
lib/src/engine/manager.dart

@@ -140,4 +140,10 @@ class IjkManager {
       _globalChannel.invokeMethod("unlockOrientation");
     }
   }
+
+  static showStatusBar(bool show) async {
+    if (Platform.isIOS || Platform.isAndroid) {
+      _globalChannel.invokeMethod("showStatusBar", show);
+    }
+  }
 }

+ 14 - 1
lib/src/widget/controller_widget_builder.dart

@@ -51,11 +51,18 @@ class DefaultIJKControllerWidget extends StatefulWidget {
   /// The current full-screen button style should not be changed by users.
   final bool currentFullScreenState;
 
+  /// Build widget for full screen.
   final IJKControllerWidgetBuilder fullscreenControllerWidgetBuilder;
 
   /// See [FullScreenType]
   final FullScreenType fullScreenType;
 
+  /// Whether to automatically hide the status bar when it is full screen.
+  final bool hideSystemBarOnFullScreen;
+
+  /// Callback in full screen, full screen when enter true, false to exit full screen.
+  final void Function(bool enter) onFullScreen;
+
   /// The UI of the controller.
   const DefaultIJKControllerWidget({
     Key key,
@@ -69,6 +76,8 @@ class DefaultIJKControllerWidget extends StatefulWidget {
     this.showFullScreenButton = true,
     this.fullscreenControllerWidgetBuilder,
     this.fullScreenType = FullScreenType.rotateBox,
+    this.hideSystemBarOnFullScreen = true,
+    this.onFullScreen,
   }) : super(key: key);
 
   @override
@@ -229,6 +238,8 @@ class _DefaultIJKControllerWidgetState extends State<DefaultIJKControllerWidget>
             controller,
             fullscreenControllerWidgetBuilder: fullscreenBuilder,
             fullScreenType: widget.fullScreenType,
+            hideSystemBar: widget.hideSystemBarOnFullScreen,
+            onFullscreen: widget.onFullScreen,
           );
         }
       },
@@ -283,7 +294,9 @@ class _DefaultIJKControllerWidgetState extends State<DefaultIJKControllerWidget>
           ),
         );
 
-        if (this.widget.fullScreenType == FullScreenType.rotateBox && this.widget.currentFullScreenState && _overlayTurns != 0) {
+        if (this.widget.fullScreenType == FullScreenType.rotateBox &&
+            this.widget.currentFullScreenState &&
+            _overlayTurns != 0) {
           w = RotatedBox(
             child: w,
             quarterTurns: _overlayTurns,

+ 35 - 4
lib/src/widget/full_screen.part.dart

@@ -10,12 +10,16 @@ showFullScreenIJKPlayer(
   IjkMediaController controller, {
   IJKControllerWidgetBuilder fullscreenControllerWidgetBuilder,
   FullScreenType fullScreenType = FullScreenType.rotateBox,
+  bool hideSystemBar = true,
+  void Function(bool enter) onFullscreen,
 }) async {
   if (fullScreenType == FullScreenType.rotateBox) {
     _showFullScreenWithRotateBox(
       context,
       controller,
       fullscreenControllerWidgetBuilder: fullscreenControllerWidgetBuilder,
+      hideSystemBar: hideSystemBar,
+      onFullscreen: onFullscreen,
     );
     return;
   }
@@ -24,13 +28,21 @@ showFullScreenIJKPlayer(
     context,
     controller,
     fullscreenControllerWidgetBuilder,
+    hideSystemBar: hideSystemBar,
+    onFullscreen: onFullscreen,
   );
 }
 
 _showFullScreenWithRotateScreen(
-    BuildContext context,
-    IjkMediaController controller,
-    IJKControllerWidgetBuilder fullscreenControllerWidgetBuilder) async {
+  BuildContext context,
+  IjkMediaController controller,
+  IJKControllerWidgetBuilder fullscreenControllerWidgetBuilder, {
+  bool hideSystemBar,
+  void Function(bool enter) onFullscreen,
+}) async {
+  if (hideSystemBar) {
+    IjkManager.showStatusBar(false);
+  }
   Navigator.push(
     context,
     FullScreenRoute(
@@ -45,8 +57,14 @@ _showFullScreenWithRotateScreen(
   ).then((_) {
     IjkManager.unlockOrientation();
     IjkManager.setCurrentOrientation(DeviceOrientation.portraitUp);
+    if (hideSystemBar) {
+      IjkManager.showStatusBar(true);
+    }
+    onFullscreen?.call(false);
   });
 
+  onFullscreen?.call(true);
+
   var info = await controller.getVideoInfo();
 
   Axis axis;
@@ -78,6 +96,8 @@ _showFullScreenWithRotateBox(
   BuildContext context,
   IjkMediaController controller, {
   IJKControllerWidgetBuilder fullscreenControllerWidgetBuilder,
+  bool hideSystemBar,
+  void Function(bool enter) onFullscreen,
 }) async {
   var info = await controller.getVideoInfo();
 
@@ -99,6 +119,10 @@ _showFullScreenWithRotateBox(
     }
   }
 
+  if (hideSystemBar) {
+    IjkManager.showStatusBar(false);
+  }
+
   Navigator.push(
     context,
     FullScreenRoute(
@@ -136,7 +160,14 @@ _showFullScreenWithRotateBox(
         );
       },
     ),
-  );
+  ).then((data) {
+    if (hideSystemBar) {
+      IjkManager.showStatusBar(true);
+    }
+    onFullscreen?.call(false);
+  });
+
+  onFullscreen?.call(true);
 }
 
 Widget _buildFullScreenMediaController(

+ 0 - 139
pubspec.lock

@@ -1,139 +0,0 @@
-# Generated by pub
-# See https://dart.dev/tools/pub/glossary#lockfile
-packages:
-  async:
-    dependency: transitive
-    description:
-      name: async
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "2.2.0"
-  boolean_selector:
-    dependency: transitive
-    description:
-      name: boolean_selector
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.0.4"
-  charcode:
-    dependency: transitive
-    description:
-      name: charcode
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.1.2"
-  collection:
-    dependency: transitive
-    description:
-      name: collection
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.14.11"
-  flutter:
-    dependency: "direct main"
-    description: flutter
-    source: sdk
-    version: "0.0.0"
-  flutter_test:
-    dependency: "direct dev"
-    description: flutter
-    source: sdk
-    version: "0.0.0"
-  matcher:
-    dependency: transitive
-    description:
-      name: matcher
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "0.12.5"
-  meta:
-    dependency: transitive
-    description:
-      name: meta
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.1.6"
-  path:
-    dependency: transitive
-    description:
-      name: path
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.6.2"
-  pedantic:
-    dependency: transitive
-    description:
-      name: pedantic
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.7.0"
-  quiver:
-    dependency: transitive
-    description:
-      name: quiver
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "2.0.3"
-  sky_engine:
-    dependency: transitive
-    description: flutter
-    source: sdk
-    version: "0.0.99"
-  source_span:
-    dependency: transitive
-    description:
-      name: source_span
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.5.5"
-  stack_trace:
-    dependency: transitive
-    description:
-      name: stack_trace
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.9.3"
-  stream_channel:
-    dependency: transitive
-    description:
-      name: stream_channel
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "2.0.0"
-  string_scanner:
-    dependency: transitive
-    description:
-      name: string_scanner
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.0.4"
-  term_glyph:
-    dependency: transitive
-    description:
-      name: term_glyph
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.1.0"
-  test_api:
-    dependency: transitive
-    description:
-      name: test_api
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "0.2.5"
-  typed_data:
-    dependency: transitive
-    description:
-      name: typed_data
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "1.1.6"
-  vector_math:
-    dependency: transitive
-    description:
-      name: vector_math
-      url: "https://pub.flutter-io.cn"
-    source: hosted
-    version: "2.0.8"
-sdks:
-  dart: ">=2.2.2 <3.0.0"

+ 1 - 1
pubspec.yaml

@@ -1,6 +1,6 @@
 name: flutter_ijkplayer
 description: Base by bilibili ijkplayer, it's video/audio player, support https、rtmp、m3u8 and more protocol.
-version: 0.3.4
+version: 0.3.5
 author: caijinglong<cjl_spy@163.com>
 homepage: https://github.com/CaiJingLong/flutter_ijkplayer