Bläddra i källkod

新增自定义Control Bar

hwh97 6 år sedan
förälder
incheckning
0610072530

BIN
assets/chewie_demo.gif


BIN
assets/dub_user_play/2.0x/bofang.png


BIN
assets/dub_user_play/2.0x/fangda.png


BIN
assets/dub_user_play/2.0x/shousuo.png


BIN
assets/dub_user_play/2.0x/stop.png


BIN
assets/dub_user_play/2.0x/zuojiantou.png


BIN
assets/dub_user_play/3.0x/bofang.png


BIN
assets/dub_user_play/3.0x/fangda.png


BIN
assets/dub_user_play/3.0x/shousuo.png


BIN
assets/dub_user_play/3.0x/stop.png


BIN
assets/dub_user_play/3.0x/zuojiantou.png


BIN
assets/dub_user_play/bofang.png


BIN
assets/dub_user_play/fangda.png


BIN
assets/dub_user_play/shousuo.png


BIN
assets/dub_user_play/stop.png


BIN
assets/dub_user_play/zuojiantou.png


+ 14 - 8
example/lib/main.dart

@@ -1,5 +1,4 @@
 import 'package:chewie/chewie.dart';
-import 'package:chewie/src/chewie_player.dart';
 import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:video_player/video_player.dart';
@@ -42,6 +41,9 @@ class _ChewieDemoState extends State<ChewieDemo> {
           aspectRatio: _videoPlayerController1.value.aspectRatio,
           autoPlay: true,
           looping: true,
+          customControls: I2MaterialControls(
+
+          ),
         );
         setState(() {
         });
@@ -75,13 +77,17 @@ class _ChewieDemoState extends State<ChewieDemo> {
 //        ),
         body: Column(
           children: <Widget>[
-            Container(
-              constraints: BoxConstraints(maxHeight: 300),
-              child: _chewieController == null ? Container() : Chewie(
-                controller: _chewieController,
-              ),
-              color: Colors.black,
-            ),
+            Stack(
+              children: <Widget>[
+                Container(
+                  constraints: BoxConstraints(maxHeight: 200),
+                  child: _chewieController == null ? Container() : Chewie(
+                    controller: _chewieController,
+                  ),
+                  color: Colors.black,
+                ),
+              ],
+            )
           ],
         ),
       ),

+ 2 - 2
example/pubspec.yaml

@@ -31,8 +31,8 @@ flutter:
   uses-material-design: true
 
   # To add assets to your application, add an assets section, like this:
-  # assets:
-  #  - images/a_dot_burr.jpeg
+  assets:
+    - ../assets/dub_user_play/
   #  - images/a_dot_ham.jpeg
 
   # An image asset can refer to one or more resolution-specific "variants", see

+ 1 - 0
lib/chewie.dart

@@ -2,3 +2,4 @@ library chewie;
 
 export 'src/chewie_player.dart';
 export 'src/chewie_progress_colors.dart';
+export 'src/i2_material_controls.dart';

+ 471 - 0
lib/src/i2_material_controls.dart

@@ -0,0 +1,471 @@
+import 'dart:async';
+
+import 'package:chewie/src/chewie_player.dart';
+import 'package:chewie/src/chewie_progress_colors.dart';
+import 'package:chewie/src/material_progress_bar.dart';
+import 'package:chewie/src/utils.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:video_player/video_player.dart';
+
+class I2MaterialControls extends StatefulWidget {
+
+  const I2MaterialControls({Key key}) : super(key: key);
+
+  @override
+  State<StatefulWidget> createState() {
+    return _MaterialControlsState();
+  }
+}
+
+class _MaterialControlsState extends State<I2MaterialControls> {
+  VideoPlayerValue _latestValue;
+  double _latestVolume;
+  bool _hideStuff = true;
+  Timer _hideTimer;
+  Timer _initTimer;
+  Timer _showAfterExpandCollapseTimer;
+  bool _dragging = false;
+  bool _displayTapped = false;
+
+  final barHeight = 36.0;
+  final marginSize = 5.0;
+
+  VideoPlayerController controller;
+  ChewieController chewieController;
+
+  @override
+  Widget build(BuildContext context) {
+    if (_latestValue.hasError) {
+      return chewieController.errorBuilder != null
+          ? chewieController.errorBuilder(
+        context,
+        chewieController.videoPlayerController.value.errorDescription,
+      )
+          : Center(
+        child: Icon(
+          Icons.error,
+          color: Colors.white,
+          size: 42,
+        ),
+      );
+    }
+
+    return MouseRegion(
+      onHover: (_) {
+        _cancelAndRestartTimer();
+      },
+      child: GestureDetector(
+        onTap: () => _cancelAndRestartTimer(),
+        child: AbsorbPointer(
+          absorbing: _hideStuff,
+          child: Stack(
+            children: <Widget>[
+              Positioned(
+                child: _buildTopBar(context),
+                top: 20,
+              ),
+              Column(
+                children: <Widget>[
+                  _latestValue != null &&
+                      !_latestValue.isPlaying &&
+                      _latestValue.duration == null ||
+                      _latestValue.isBuffering
+                      ? const Expanded(
+                    child: const Center(
+                      child: const CircularProgressIndicator(),
+                    ),
+                  )
+                      : _buildHitArea(),
+                  _buildBottomBar(context),
+                ],
+              ),
+            ],
+          )
+        ),
+      ),
+    );
+  }
+
+  @override
+  void dispose() {
+    _dispose();
+    super.dispose();
+  }
+
+  void _dispose() async {
+    controller.removeListener(_updateState);
+    _hideTimer?.cancel();
+    _initTimer?.cancel();
+    _showAfterExpandCollapseTimer?.cancel();
+  }
+
+  @override
+  void didChangeDependencies() {
+    final _oldController = chewieController;
+    chewieController = ChewieController.of(context);
+    controller = chewieController.videoPlayerController;
+
+    if (_oldController != chewieController) {
+      _dispose();
+      _initialize();
+    }
+
+    super.didChangeDependencies();
+  }
+
+
+  AnimatedOpacity _buildTopBar(
+      BuildContext context,
+      ) {
+    return AnimatedOpacity(
+      opacity: _hideStuff ? 0.0 : 1.0,
+      duration: Duration(milliseconds: 300),
+      child: Container(
+//          color: chewieController.isFullScreen ? Colors.black26 : Colors.transparent,
+          alignment: Alignment.centerLeft,
+//              height: 44.0 + MediaQuery.of(context).padding.top != 0 ? MediaQuery.of(context).padding.top : 0,
+          width: MediaQuery.of(context).size.width,
+//          margin: EdgeInsets.only(top: MediaQuery.of(context).padding.top != 0 ? MediaQuery.of(context).padding.top : 0),
+          padding: EdgeInsets.only(left: 13,),
+          child: Row(
+            children: <Widget>[
+              GestureDetector(
+                  onTap: onTapBack,
+                  child: Image(image: AssetImage("assets/dub_user_play/zuojiantou.png", package: 'chewie'), width: 20, height: 20,)
+              ),
+            ],
+          )
+      ),
+    );
+  }
+
+  AnimatedOpacity _buildBottomBar(
+      BuildContext context,
+      ) {
+    final iconColor = Theme.of(context).textTheme.button.color;
+
+    return AnimatedOpacity(
+      opacity: _hideStuff ? 0.0 : 1.0,
+      duration: Duration(milliseconds: 300),
+      child: Container(
+        height: barHeight,
+//        color: Theme.of(context).dialogBackgroundColor,
+        color: Colors.transparent,
+        child: Row(
+          children: <Widget>[
+            _buildPlayPause(controller),
+            chewieController.isLive
+                ? Expanded(child: const Text('LIVE'))
+                : _buildPosition(iconColor),
+            chewieController.isLive ? const SizedBox() : _buildProgressBar(),
+            chewieController.isLive
+                ? const SizedBox()
+                : _buildFullPosition(iconColor),
+//            chewieController.allowMuting
+//                ? _buildMuteButton(controller)
+//                : Container(),
+            chewieController.allowFullScreen
+                ? _buildExpandButton()
+                : Container(),
+          ],
+        ),
+      ),
+    );
+  }
+
+  GestureDetector _buildExpandButton() {
+    return GestureDetector(
+      onTap: _onExpandCollapse,
+      child: AnimatedOpacity(
+        opacity: _hideStuff ? 0.0 : 1.0,
+        duration: Duration(milliseconds: 300),
+        child: Container(
+          height: barHeight,
+          margin: EdgeInsets.only(right: 12.0),
+          padding: EdgeInsets.only(
+            left: 8.0,
+            right: 8.0,
+          ),
+          child: Center(
+              child: Image(image: AssetImage("assets/dub_user_play/${chewieController.isFullScreen ? "shousuo.png" : "fangda.png"}", package: 'chewie'), width: 20, height: 20,),
+          ),
+        ),
+      ),
+    );
+  }
+
+  Expanded _buildHitArea() {
+    return Expanded(
+      child: GestureDetector(
+        onTap: () {
+          if (_latestValue != null && _latestValue.isPlaying) {
+            if (_displayTapped) {
+              _hideStatusBar();
+              setState(() {
+                _hideStuff = true;
+              });
+            } else
+              _cancelAndRestartTimer();
+          } else {
+            _playPause();
+            _hideStatusBar();
+            setState(() {
+              _hideStuff = true;
+            });
+          }
+        },
+        child: Container(
+          color: Colors.transparent,
+          child: Center(
+            child: AnimatedOpacity(
+              opacity:
+              _latestValue != null && !_latestValue.isPlaying && !_dragging
+                  ? 1.0
+                  : 0.0,
+              duration: Duration(milliseconds: 300),
+              child: GestureDetector(
+                child: Container(
+                  decoration: BoxDecoration(
+                    color: Theme.of(context).dialogBackgroundColor,
+                    borderRadius: BorderRadius.circular(48.0),
+                  ),
+                  child: Padding(
+                    padding: EdgeInsets.all(12.0),
+                    child: Icon(Icons.play_arrow, size: 32.0, color: Colors.black,),
+                  ),
+                ),
+              ),
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+
+  GestureDetector _buildMuteButton(
+      VideoPlayerController controller,
+      ) {
+    return GestureDetector(
+      onTap: () {
+        _cancelAndRestartTimer();
+
+        if (_latestValue.volume == 0) {
+          controller.setVolume(_latestVolume ?? 0.5);
+        } else {
+          _latestVolume = controller.value.volume;
+          controller.setVolume(0.0);
+        }
+      },
+      child: AnimatedOpacity(
+        opacity: _hideStuff ? 0.0 : 1.0,
+        duration: Duration(milliseconds: 300),
+        child: ClipRect(
+          child: Container(
+            child: Container(
+              height: barHeight,
+              padding: EdgeInsets.only(
+                left: 8.0,
+                right: 8.0,
+              ),
+              child: Icon(
+                (_latestValue != null && _latestValue.volume > 0)
+                    ? Icons.volume_up
+                    : Icons.volume_off,
+              ),
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+
+  GestureDetector _buildPlayPause(VideoPlayerController controller) {
+    return GestureDetector(
+      onTap: _playPause,
+      child: Container(
+        height: barHeight,
+        color: Colors.transparent,
+        margin: EdgeInsets.only(left: 8.0, right: 4.0),
+        padding: EdgeInsets.only(
+          left: 12.0,
+          right: 12.0,
+        ),
+        child: Image(image: AssetImage("assets/dub_user_play/${controller.value.isPlaying ? "stop.png" : "bofang.png"}", package: 'chewie'), width: 20, height: 20,),
+      ),
+    );
+  }
+
+  Widget _buildPosition(Color iconColor) {
+    final position = _latestValue != null && _latestValue.position != null
+        ? _latestValue.position
+        : Duration.zero;
+    final duration = _latestValue != null && _latestValue.duration != null
+        ? _latestValue.duration
+        : Duration.zero;
+
+    return Padding(
+      padding: EdgeInsets.only(right: 14.0),
+      child: Text(
+        '${formatDuration(position)}',
+        style: TextStyle(
+          color: Colors.white,
+          fontSize: 12.0,
+        ),
+      ),
+    );
+  }
+
+  Widget _buildFullPosition(Color iconColor) {
+    final position = _latestValue != null && _latestValue.position != null
+        ? _latestValue.position
+        : Duration.zero;
+    final duration = _latestValue != null && _latestValue.duration != null
+        ? _latestValue.duration
+        : Duration.zero;
+
+    return Padding(
+      padding: EdgeInsets.only(left: 14.0, right: 20.0),
+      child: Text(
+        '${formatDuration(duration)}',
+        style: TextStyle(
+          color: Colors.white,
+          fontSize: 12.0,
+        ),
+      ),
+    );
+  }
+
+  void _cancelAndRestartTimer() {
+    _hideTimer?.cancel();
+    _startHideTimer();
+    // 显示status bar
+    _showStatusBar();
+    setState(() {
+      _hideStuff = false;
+      _displayTapped = true;
+    });
+  }
+
+  Future<Null> _initialize() async {
+    controller.addListener(_updateState);
+
+    _updateState();
+
+    if ((controller.value != null && controller.value.isPlaying) ||
+        chewieController.autoPlay) {
+      _startHideTimer();
+    }
+
+    if (chewieController.showControlsOnInitialize) {
+      _initTimer = Timer(Duration(milliseconds: 200), () {
+        // 显示status bar
+        _showStatusBar();
+        setState(() {
+          _hideStuff = false;
+        });
+      });
+    }
+  }
+
+  void _hideStatusBar() {
+    SystemChrome.setEnabledSystemUIOverlays ([SystemUiOverlay.bottom]);
+  }
+
+  void _showStatusBar() {
+    SystemChrome.setEnabledSystemUIOverlays ([SystemUiOverlay.top, SystemUiOverlay.bottom]);
+  }
+
+  void _onExpandCollapse() {
+    // 隐藏status bar
+    _hideStatusBar();
+    setState(() {
+      _hideStuff = true;
+      chewieController.toggleFullScreen();
+      _showAfterExpandCollapseTimer = Timer(Duration(milliseconds: 300), () {
+        setState(() {
+          _cancelAndRestartTimer();
+        });
+      });
+    });
+  }
+
+  void _playPause() {
+    bool isFinished = _latestValue.position >= _latestValue.duration;
+
+    setState(() {
+      if (controller.value.isPlaying) {
+        // 显示status bar
+        _showStatusBar();
+        _hideStuff = false;
+        _hideTimer?.cancel();
+        controller.pause();
+      } else {
+        _cancelAndRestartTimer();
+
+        if (!controller.value.initialized) {
+          controller.initialize().then((_) {
+            controller.play();
+          });
+        } else {
+          if (isFinished) {
+            controller.seekTo(Duration(seconds: 0));
+          }
+          controller.play();
+        }
+      }
+    });
+  }
+
+  void _startHideTimer() {
+    _hideTimer = Timer(const Duration(seconds: 3), () {
+      // 隐藏status bar
+      _hideStatusBar();
+      setState(() {
+        _hideStuff = true;
+      });
+    });
+  }
+
+  void _updateState() {
+    setState(() {
+      _latestValue = controller.value;
+    });
+  }
+
+  Widget _buildProgressBar() {
+    return Expanded(
+      child: MaterialVideoProgressBar(
+        controller,
+        onDragStart: () {
+          setState(() {
+            _dragging = true;
+          });
+
+          _hideTimer?.cancel();
+        },
+        onDragEnd: () {
+          setState(() {
+            _dragging = false;
+          });
+
+          _startHideTimer();
+        },
+        colors: chewieController.materialProgressColors ??
+            ChewieProgressColors(
+                playedColor: Color(0xFFC7000B),
+                handleColor: Color(0xFFC7000B),
+                bufferedColor:  Color(0x5AC7000B),
+                backgroundColor: Color(0x5AFFFFFF)),
+      ),
+    );
+  }
+
+  void onTapBack() {
+    if (chewieController.isFullScreen) {
+      chewieController.exitFullScreen();
+    } else {
+      Navigator.of(context).maybePop();
+    }
+  }
+}

+ 2 - 0
pubspec.yaml

@@ -24,3 +24,5 @@ dev_dependencies:
 
 flutter:
   uses-material-design: true
+  assets:
+    - assets/dub_user_play/