Parcourir la source

增加了一个DataSource类
支持进度条的拖动快速定位视频

Caijinglong il y a 6 ans
Parent
commit
873147a58e

+ 4 - 4
example/lib/page/full_screen.dart

@@ -10,14 +10,14 @@ class _FullScreenState extends State<FullScreen> {
   var controller = IjkMediaController();
 
   Orientation get orientation => MediaQuery.of(context).orientation;
+  DataSource source = DataSource.network(
+    "https://www.sample-videos.com/video123/mp4/360/big_buck_bunny_360p_30mb.mp4",
+  );
 
   @override
   void initState() {
     super.initState();
-    controller.setNetworkDataSource(
-      "https://www.sample-videos.com/video123/mp4/360/big_buck_bunny_360p_30mb.mp4",
-      autoPlay: true,
-    );
+    controller.setDataSource(source, autoPlay: true);
   }
 
   @override

+ 4 - 4
lib/src/controller.dart

@@ -375,7 +375,7 @@ class DataSource {
 
   DataSource._();
 
-  /// Create file datasource
+  /// Create file data source
   factory DataSource.file(File file) {
     var ds = DataSource._();
     ds._file = file;
@@ -383,15 +383,15 @@ class DataSource {
     return ds;
   }
 
-  /// Create network datasource
+  /// Create network data source
   factory DataSource.network(String url) {
     var ds = DataSource._();
     ds._netWorkUrl = url;
-    ds.type = DataSourceType.file;
+    ds.type = DataSourceType.network;
     return ds;
   }
 
-  /// Create asset datasource
+  /// Create asset data source
   factory DataSource.asset(String assetName, {String package}) {
     var ds = DataSource._();
     ds._assetName = assetName;

+ 23 - 0
lib/src/helper/time_helper.dart

@@ -0,0 +1,23 @@
+class TimeHelper {
+  static String getTimeText(double seconds) {
+    var duration = Duration(milliseconds: (seconds * 1000).toInt());
+
+    String twoDigits(int n) {
+      if (n >= 10) return "$n";
+      return "0$n";
+    }
+
+    String twoDigitMinutes =
+        twoDigits(duration.inMinutes.remainder(Duration.minutesPerHour));
+    String twoDigitSeconds =
+        twoDigits(duration.inSeconds.remainder(Duration.secondsPerMinute));
+
+    var str = "$twoDigitMinutes:$twoDigitSeconds";
+
+    if (duration.inHours == 0) {
+      return str;
+    }
+    var hour = duration.inHours.toString().padLeft(2, "0");
+    return "$hour:$str";
+  }
+}

+ 5 - 1
lib/src/ijkplayer.dart

@@ -79,7 +79,11 @@ class IjkPlayerState extends State<IjkPlayer> {
         controllerWidget,
       ],
     );
-    return stack;
+//    return stack;
+    return Material(
+      child: stack,
+      color: Colors.black,
+    );
   }
 
   Widget _buildTexture(int id, VideoInfo info) {

+ 90 - 29
lib/src/widget/controller_widget_builder.dart

@@ -1,7 +1,9 @@
 import 'dart:async';
 
+import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_ijkplayer/flutter_ijkplayer.dart';
+import 'package:flutter_ijkplayer/src/helper/time_helper.dart';
 import 'package:flutter_ijkplayer/src/logutil.dart';
 import 'package:flutter_ijkplayer/src/widget/progress_bar.dart';
 
@@ -49,7 +51,8 @@ class DefaultControllerWidget extends StatefulWidget {
       _DefaultControllerWidgetState();
 }
 
-class _DefaultControllerWidgetState extends State<DefaultControllerWidget> {
+class _DefaultControllerWidgetState extends State<DefaultControllerWidget>
+    implements TooltipDelegate {
   IjkMediaController get controller => widget.controller;
 
   bool _isShow = true;
@@ -148,12 +151,13 @@ class _DefaultControllerWidgetState extends State<DefaultControllerWidget> {
     return PortraitController(
       controller: controller,
       info: info,
+      tooltipDelegate: this,
     );
   }
 
   OverlayEntry _tipOverlay;
 
-  Widget createTipWidgetWrapper(Widget widget) {
+  Widget createTooltipWidgetWrapper(Widget widget) {
     var typography = Typography(platform: TargetPlatform.android);
     var theme = typography.white;
     const style = const TextStyle(
@@ -176,8 +180,8 @@ class _DefaultControllerWidgetState extends State<DefaultControllerWidget> {
     );
   }
 
-  void showTipWidget(Widget widget) {
-    hideTipWidget();
+  void showTooltip(Widget widget) {
+    hideTooltip();
     _tipOverlay = OverlayEntry(
       builder: (BuildContext context) {
         return IgnorePointer(
@@ -190,7 +194,7 @@ class _DefaultControllerWidgetState extends State<DefaultControllerWidget> {
     Overlay.of(context).insert(_tipOverlay);
   }
 
-  void hideTipWidget() {
+  void hideTooltip() {
     _tipOverlay?.remove();
     _tipOverlay = null;
   }
@@ -244,11 +248,11 @@ class _DefaultControllerWidgetState extends State<DefaultControllerWidget> {
       ],
     );
 
-    showTipWidget(createTipWidgetWrapper(w));
+    showTooltip(createTooltipWidgetWrapper(w));
   }
 
   void _onHorizontalDragEnd(DragEndDetails details) async {
-    hideTipWidget();
+    hideTooltip();
     var targetSeek = _calculator.getTargetSeek(details);
     _calculator = null;
     await controller.seekTo(targetSeek);
@@ -282,11 +286,11 @@ class _DefaultControllerWidgetState extends State<DefaultControllerWidget> {
       ],
     );
 
-    showTipWidget(createTipWidgetWrapper(column));
+    showTooltip(createTooltipWidgetWrapper(column));
   }
 
   void _onVerticalDragEnd(DragEndDetails details) {
-    hideTipWidget();
+    hideTooltip();
   }
 
   Future<int> getVolume() async {
@@ -356,31 +360,28 @@ class _ProgressCalculator {
   }
 }
 
-String _getTimeText(double durationSecond) {
-  var duration = Duration(milliseconds: ((durationSecond ?? 0) * 1000).toInt());
-  var minute = (duration.inMinutes % 60).toString().padLeft(2, "0");
-  var second = (duration.inSeconds % 60).toString().padLeft(2, "0");
-  var text = "$minute:$second";
-//  LogUtils.log("$durationSecond = $text");
-  return text;
-}
-
 class PortraitController extends StatelessWidget {
   final IjkMediaController controller;
   final VideoInfo info;
+  final TooltipDelegate tooltipDelegate;
 
   const PortraitController({
     Key key,
     this.controller,
     this.info,
+    this.tooltipDelegate,
   }) : super(key: key);
 
+  bool get haveTime {
+    return info.hasData && info.duration > 0;
+  }
+
   @override
   Widget build(BuildContext context) {
     if (!info.hasData) {
       return Container();
     }
-    Widget bottomBar = buildBottomBar();
+    Widget bottomBar = buildBottomBar(context);
     return Column(
       children: <Widget>[
         Expanded(
@@ -391,16 +392,12 @@ class PortraitController extends StatelessWidget {
     );
   }
 
-  Widget buildBottomBar() {
-    var currentTime = Text(
-      _getTimeText(info.currentPosition),
-    );
-    var maxTime = Text(
-      _getTimeText(info.duration),
-    );
+  Widget buildBottomBar(BuildContext context) {
+    var currentTime = buildCurrentText();
+    var maxTime = buildMaxTimeText();
     var progress = buildProgress(info);
 
-    var playButton = buildPlayButton();
+    var playButton = buildPlayButton(context);
 
     Widget widget = Row(
       children: <Widget>[
@@ -440,13 +437,32 @@ class PortraitController extends StatelessWidget {
         max: info.duration,
         changeProgressHandler: (progress) async {
           await controller.seekToProgress(progress);
+          tooltipDelegate?.hideTooltip();
+        },
+        tapProgressHandler: (progress) {
+          showProgressTooltip(info, progress);
         },
-        tapProgressHandler: (progress) {},
       ),
     );
   }
 
-  buildPlayButton() {
+  buildCurrentText() {
+    return haveTime
+        ? Text(
+            TimeHelper.getTimeText(info.currentPosition),
+          )
+        : Container();
+  }
+
+  buildMaxTimeText() {
+    return haveTime
+        ? Text(
+            TimeHelper.getTimeText(info.duration),
+          )
+        : Container();
+  }
+
+  buildPlayButton(BuildContext context) {
     return IconButton(
       onPressed: () {
         controller.playOrPause();
@@ -456,6 +472,51 @@ class PortraitController extends StatelessWidget {
       iconSize: 25.0,
     );
   }
+
+  void showProgressTooltip(VideoInfo info, double progress) {
+    var target = info.duration * progress;
+
+    var diff = info.currentPosition - target;
+
+    String diffString;
+    if (diff < 1 && diff > -1) {
+      diffString = "0s";
+    } else if (diff < 0) {
+      diffString = "+${TimeHelper.getTimeText(diff.abs())}";
+    } else if (diff > 0) {
+      diffString = "-${TimeHelper.getTimeText(diff.abs())}";
+    } else {
+      diffString = "0s";
+    }
+
+    Widget text = Container(
+      alignment: Alignment.center,
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.center,
+        children: <Widget>[
+          Text(
+            TimeHelper.getTimeText(target),
+            style: TextStyle(fontSize: 20),
+          ),
+          Container(
+            height: 10,
+          ),
+          Text(diffString),
+        ],
+      ),
+    );
+
+    var tooltip = tooltipDelegate?.createTooltipWidgetWrapper(text);
+    tooltipDelegate?.showTooltip(tooltip);
+  }
+}
+
+abstract class TooltipDelegate {
+  void showTooltip(Widget widget);
+
+  Widget createTooltipWidgetWrapper(Widget widget);
+
+  void hideTooltip();
 }
 
 enum VolumeType {

+ 21 - 1
lib/src/widget/progress_bar.dart

@@ -36,12 +36,21 @@ class ProgressBar extends StatefulWidget {
 class _ProgressBarState extends State<ProgressBar> {
   GlobalKey _progressKey = GlobalKey();
 
+  double tempLeft;
+
+  double get left {
+    var l = widget.current / widget.max;
+    if (tempLeft != null) {
+      return tempLeft;
+    }
+    return l;
+  }
+
   @override
   Widget build(BuildContext context) {
     if (widget.max == null || widget.current == null || widget.max == 0)
       return _buildEmpty();
 
-    var left = widget.current / widget.max;
     var mid = (widget.buffered ?? 0) / widget.max - left;
     if (mid < 0) {
       mid = 0;
@@ -58,6 +67,7 @@ class _ProgressBarState extends State<ProgressBar> {
         behavior: HitTestBehavior.translucent,
         onPanUpdate: _onPanUpdate,
         onHorizontalDragUpdate: _onHorizontalDragUpdate,
+        onHorizontalDragEnd: _onHorizontalDragEnd,
         onTapDown: _onTapDown,
         onTapUp: _onTapUp,
       );
@@ -126,6 +136,9 @@ class _ProgressBarState extends State<ProgressBar> {
 
   void _onHorizontalDragUpdate(DragUpdateDetails details) {
     var progress = getProgress(details.globalPosition);
+    setState(() {
+      tempLeft = progress;
+    });
     widget.tapProgressHandler(progress);
   }
 
@@ -147,4 +160,11 @@ class _ProgressBarState extends State<ProgressBar> {
       globalPosition,
     );
   }
+
+  void _onHorizontalDragEnd(DragEndDetails details) {
+    if (tempLeft != null) {
+      widget.changeProgressHandler(tempLeft);
+      tempLeft = null;
+    }
+  }
 }