Selaa lähdekoodia

More refined Cupertino style

Brian Egan 8 vuotta sitten
vanhempi
commit
31848f4216

+ 17 - 8
example/lib/chewie_player.dart

@@ -15,10 +15,11 @@ class ChewiePlayer extends StatefulWidget {
   ChewiePlayer({
     Key key,
     @required this.controller,
-    @required this.aspectRatio,
+    this.aspectRatio,
     this.autoPlay = false,
     this.looping = false,
-  }) : super(key: key);
+  })
+      : super(key: key);
 
   @override
   State<StatefulWidget> createState() {
@@ -30,12 +31,11 @@ class _ChewiePlayerState extends State<ChewiePlayer> {
   @override
   Widget build(BuildContext context) {
     return new PlayerWithControls(
-      controller: widget.controller,
-      onExpandCollapse: () {
-        return _pushFullScreenWidget(context);
-      },
-      aspectRatio: widget.aspectRatio,
-    );
+        controller: widget.controller,
+        onExpandCollapse: () {
+          return _pushFullScreenWidget(context);
+        },
+        aspectRatio: widget.aspectRatio ?? _calculateAspectRatio(context));
   }
 
   @override
@@ -94,4 +94,13 @@ class _ChewiePlayerState extends State<ChewiePlayer> {
       SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
     });
   }
+
+  double _calculateAspectRatio(BuildContext context) {
+    final size = MediaQuery.of(context).size;
+    final width = size.width;
+    final height = size.height;
+
+    return width > height ? width / height : height / width;
+
+  }
 }

+ 94 - 67
example/lib/cupertino_controls.dart

@@ -2,6 +2,7 @@ import 'dart:async';
 import 'dart:math' as math;
 import 'dart:ui';
 
+import 'package:chewie_example/cupertino_progress_bar.dart';
 import 'package:chewie_example/utils.dart';
 import 'package:flutter/material.dart';
 import 'package:meta/meta.dart';
@@ -35,7 +36,6 @@ class _CupertinoControlsState extends State<CupertinoControls> {
   bool _hideStuff = true;
   bool _disposed = false;
   Timer _hideTimer;
-  final barHeight = 30.0;
   final marginSize = 5.0;
 
   @override
@@ -43,12 +43,16 @@ class _CupertinoControlsState extends State<CupertinoControls> {
     final backgroundColor = widget.backgroundColor;
     final iconColor = widget.iconColor;
     final controller = widget.controller;
+    final orientation = MediaQuery.of(context).orientation;
+    final barHeight = orientation == Orientation.portrait ? 30.0 : 47.0;
+    final buttonPadding = orientation == Orientation.portrait ? 16.0 : 24.0;
 
     return new Column(
       children: <Widget>[
-        _buildTopBar(backgroundColor, iconColor, controller),
+        _buildTopBar(
+            backgroundColor, iconColor, controller, barHeight, buttonPadding),
         _buildHitArea(),
-        _buildBottomBar(backgroundColor, iconColor, controller),
+        _buildBottomBar(backgroundColor, iconColor, controller, barHeight),
       ],
     );
   }
@@ -67,8 +71,12 @@ class _CupertinoControlsState extends State<CupertinoControls> {
     super.initState();
   }
 
-  AnimatedOpacity _buildBottomBar(Color backgroundColor, Color iconColor,
-      VideoPlayerController controller) {
+  AnimatedOpacity _buildBottomBar(
+    Color backgroundColor,
+    Color iconColor,
+    VideoPlayerController controller,
+    double barHeight,
+  ) {
     return new AnimatedOpacity(
       opacity: _hideStuff ? 0.0 : 1.0,
       duration: new Duration(milliseconds: 300),
@@ -92,11 +100,11 @@ class _CupertinoControlsState extends State<CupertinoControls> {
               ),
               child: new Row(
                 children: <Widget>[
-                  _buildSkipBack(iconColor),
-                  _buildPlayPause(controller, iconColor),
-                  _buildSkipForward(iconColor),
+                  _buildSkipBack(iconColor, barHeight),
+                  _buildPlayPause(controller, iconColor, barHeight),
+                  _buildSkipForward(iconColor, barHeight),
                   _buildPosition(iconColor),
-                  new _ProgressBar(controller),
+                  _buildProgressBar(),
                   _buildRemaining(iconColor)
                 ],
               ),
@@ -107,7 +115,12 @@ class _CupertinoControlsState extends State<CupertinoControls> {
     );
   }
 
-  GestureDetector _buildExpandButton(Color backgroundColor, Color iconColor) {
+  GestureDetector _buildExpandButton(
+    Color backgroundColor,
+    Color iconColor,
+    double barHeight,
+    double buttonPadding,
+  ) {
     return new GestureDetector(
       onTap: _onExpandCollapse,
       child: new AnimatedOpacity(
@@ -119,8 +132,8 @@ class _CupertinoControlsState extends State<CupertinoControls> {
             child: new Container(
               height: barHeight,
               padding: new EdgeInsets.only(
-                left: 16.0,
-                right: 16.0,
+                left: buttonPadding,
+                right: buttonPadding,
               ),
               decoration: new BoxDecoration(
                 color: backgroundColor,
@@ -163,8 +176,13 @@ class _CupertinoControlsState extends State<CupertinoControls> {
     );
   }
 
-  GestureDetector _buildMuteButton(VideoPlayerController controller,
-      Color backgroundColor, Color iconColor) {
+  GestureDetector _buildMuteButton(
+    VideoPlayerController controller,
+    Color backgroundColor,
+    Color iconColor,
+    double barHeight,
+    double buttonPadding,
+  ) {
     return new GestureDetector(
       onTap: () {
         _cancelAndRestartTimer();
@@ -192,8 +210,8 @@ class _CupertinoControlsState extends State<CupertinoControls> {
               child: new Container(
                 height: barHeight,
                 padding: new EdgeInsets.only(
-                  left: 16.0,
-                  right: 16.0,
+                  left: buttonPadding,
+                  right: buttonPadding,
                 ),
                 child: new Icon(
                   (_latestValue != null && _latestValue.volume > 0)
@@ -211,7 +229,10 @@ class _CupertinoControlsState extends State<CupertinoControls> {
   }
 
   GestureDetector _buildPlayPause(
-      VideoPlayerController controller, Color iconColor) {
+    VideoPlayerController controller,
+    Color iconColor,
+    double barHeight,
+  ) {
     return new GestureDetector(
       onTap: _playPause,
       child: new Container(
@@ -262,7 +283,7 @@ class _CupertinoControlsState extends State<CupertinoControls> {
     );
   }
 
-  GestureDetector _buildSkipBack(Color iconColor) {
+  GestureDetector _buildSkipBack(Color iconColor, double barHeight) {
     return new GestureDetector(
       onTap: _skipBack,
       child: new Container(
@@ -288,7 +309,7 @@ class _CupertinoControlsState extends State<CupertinoControls> {
     );
   }
 
-  GestureDetector _buildSkipForward(Color iconColor) {
+  GestureDetector _buildSkipForward(Color iconColor, double barHeight) {
     return new GestureDetector(
       onTap: _skipForward,
       child: new Container(
@@ -310,8 +331,13 @@ class _CupertinoControlsState extends State<CupertinoControls> {
     );
   }
 
-  Widget _buildTopBar(Color backgroundColor, Color iconColor,
-      VideoPlayerController controller) {
+  Widget _buildTopBar(
+    Color backgroundColor,
+    Color iconColor,
+    VideoPlayerController controller,
+    double barHeight,
+    double buttonPadding,
+  ) {
     return new Container(
       height: barHeight,
       margin: new EdgeInsets.only(
@@ -321,9 +347,11 @@ class _CupertinoControlsState extends State<CupertinoControls> {
       ),
       child: new Row(
         children: <Widget>[
-          _buildExpandButton(backgroundColor, iconColor),
+          _buildExpandButton(
+              backgroundColor, iconColor, barHeight, buttonPadding),
           new Expanded(child: new Container()),
-          _buildMuteButton(controller, backgroundColor, iconColor),
+          _buildMuteButton(
+              controller, backgroundColor, iconColor, barHeight, buttonPadding),
         ],
       ),
     );
@@ -369,6 +397,49 @@ class _CupertinoControlsState extends State<CupertinoControls> {
     });
   }
 
+  Widget _buildProgressBar() {
+    return new Expanded(
+      child: new Padding(
+        padding: new EdgeInsets.only(right: 12.0),
+        child: new CupertinoVideoProgressBar(
+          widget.controller,
+          onDragStart: () {
+            _hideTimer?.cancel();
+          },
+          onDragEnd: () {
+            _startHideTimer();
+          },
+          colors: new VideoProgressColors(
+            playedColor: new Color.fromARGB(
+              120,
+              255,
+              255,
+              255,
+            ),
+            handleColor: new Color.fromARGB(
+              255,
+              255,
+              255,
+              255,
+            ),
+            bufferedColor: new Color.fromARGB(
+              60,
+              255,
+              255,
+              255,
+            ),
+            disabledColor: new Color.fromARGB(
+              20,
+              255,
+              255,
+              255,
+            ),
+          ),
+        ),
+      ),
+    );
+  }
+
   void _playPause() {
     setState(() {
       if (widget.controller.value.isPlaying) {
@@ -413,47 +484,3 @@ class _CupertinoControlsState extends State<CupertinoControls> {
     });
   }
 }
-
-class _ProgressBar extends StatelessWidget {
-  final VideoPlayerController controller;
-
-  _ProgressBar(this.controller);
-
-  @override
-  Widget build(BuildContext context) {
-    return new Expanded(
-      child: new Padding(
-        padding: new EdgeInsets.only(right: 12.0),
-        child: new ClipRRect(
-          borderRadius: new BorderRadius.all(new Radius.circular(10.0)),
-          child: new Container(
-            height: 5.0,
-            child: new VideoProgressBar(
-              controller,
-              colors: new VideoProgressColors(
-                playedColor: new Color.fromARGB(
-                  255,
-                  255,
-                  255,
-                  255,
-                ),
-                handleColor: new Color.fromARGB(
-                  255,
-                  255,
-                  255,
-                  255,
-                ),
-                bufferedColor: new Color.fromARGB(
-                  140,
-                  255,
-                  255,
-                  255,
-                ),
-              ),
-            ),
-          ),
-        ),
-      ),
-    );
-  }
-}

+ 197 - 0
example/lib/cupertino_progress_bar.dart

@@ -0,0 +1,197 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+import 'package:video_player/video_player.dart';
+
+class CupertinoVideoProgressBar extends StatefulWidget {
+  final VideoPlayerController controller;
+  final VideoProgressColors colors;
+  final Function() onDragStart;
+  final Function() onDragEnd;
+  final Function() onDragUpdate;
+
+  CupertinoVideoProgressBar(this.controller, {
+    VideoProgressColors colors,
+    this.onDragEnd,
+    this.onDragStart,
+    this.onDragUpdate,
+  })
+      : colors = colors ?? new VideoProgressColors();
+
+  @override
+  _VideoProgressBarState createState() {
+    return new _VideoProgressBarState();
+  }
+}
+
+class _VideoProgressBarState extends State<CupertinoVideoProgressBar> {
+  VoidCallback listener;
+
+  bool _controllerWasPlaying = false;
+
+  _VideoProgressBarState() {
+    listener = () {
+      setState(() {});
+    };
+  }
+
+  VideoPlayerController get controller => widget.controller;
+
+  @override
+  void initState() {
+    super.initState();
+    controller.addListener(listener);
+  }
+
+  @override
+  void deactivate() {
+    controller.removeListener(listener);
+    super.deactivate();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    void seekToRelativePosition(Offset globalPosition) {
+      final RenderBox box = context.findRenderObject();
+      final Offset tapPos = box.globalToLocal(globalPosition);
+      final double relative = tapPos.dx / box.size.width;
+      final Duration position = controller.value.duration * relative;
+      controller.seekTo(position);
+    }
+
+    return new GestureDetector(
+      child: (controller.value.isErroneous)
+          ? new Text(controller.value.errorDescription)
+          : new Center(
+        child: new Container(
+          height: MediaQuery
+              .of(context)
+              .size
+              .height,
+          width: MediaQuery
+              .of(context)
+              .size
+              .width,
+          color: Colors.transparent,
+          child: new CustomPaint(
+            painter: new _ProgressBarPainter(
+              controller.value,
+              widget.colors,
+            ),
+          ),
+        ),
+      ),
+      onHorizontalDragStart: (DragStartDetails details) {
+        if (!controller.value.initialized) {
+          return;
+        }
+        _controllerWasPlaying = controller.value.isPlaying;
+        if (_controllerWasPlaying) {
+          controller.pause();
+        }
+
+        if (widget.onDragStart != null) {
+          widget.onDragStart();
+        }
+      },
+      onHorizontalDragUpdate: (DragUpdateDetails details) {
+        if (!controller.value.initialized) {
+          return;
+        }
+        seekToRelativePosition(details.globalPosition);
+
+
+        if (widget.onDragUpdate != null) {
+          widget.onDragUpdate();
+        }
+      },
+      onHorizontalDragEnd: (DragEndDetails details) {
+        if (_controllerWasPlaying) {
+          controller.play();
+        }
+
+        if (widget.onDragEnd != null) {
+          widget.onDragEnd();
+        }
+      },
+      onTapDown: (TapDownDetails details) {
+        if (!controller.value.initialized) {
+          return;
+        }
+        seekToRelativePosition(details.globalPosition);
+      },
+    );
+  }
+}
+
+class _ProgressBarPainter extends CustomPainter {
+  VideoPlayerValue value;
+  VideoProgressColors colors;
+
+  _ProgressBarPainter(this.value, this.colors);
+
+  @override
+  bool shouldRepaint(CustomPainter painter) {
+    return true;
+  }
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    final barHeight = 5.0;
+    final handleHeight = 6.0;
+    final baseOffset = size.height / 2 - barHeight / 2.0;
+
+    canvas.drawRRect(
+      new RRect.fromRectAndRadius(
+        new Rect.fromPoints(
+          new Offset(0.0, baseOffset),
+          new Offset(size.width, baseOffset + barHeight),
+        ),
+        new Radius.circular(4.0),
+      ),
+      colors.disabledPaint,
+    );
+    if (!value.initialized) {
+      return;
+    }
+    final double playedPart = value.position.inMilliseconds /
+        value.duration.inMilliseconds *
+        size.width;
+    for (DurationRange range in value.buffered) {
+      final double start = range.startFraction(value.duration) * size.width;
+      final double end = range.endFraction(value.duration) * size.width;
+      canvas.drawRRect(
+        new RRect.fromRectAndRadius(
+          new Rect.fromPoints(
+            new Offset(start, baseOffset),
+            new Offset(end, baseOffset + barHeight),
+          ),
+          new Radius.circular(4.0),
+        ),
+        colors.bufferedPaint,
+      );
+    }
+    canvas.drawRRect(
+      new RRect.fromRectAndRadius(
+        new Rect.fromPoints(
+          new Offset(0.0, baseOffset),
+          new Offset(playedPart, baseOffset + barHeight),
+        ),
+        new Radius.circular(4.0),
+      ),
+      colors.playedPaint,
+    );
+
+    final shadowPath = new Path()
+      ..addOval(new Rect.fromCircle(
+          center: new Offset(playedPart, baseOffset + barHeight / 2),
+          radius: handleHeight
+      ));
+
+    canvas.drawShadow(shadowPath, Colors.black, 0.2, false);
+    canvas.drawCircle(
+      new Offset(playedPart, baseOffset + barHeight / 2),
+      handleHeight,
+      colors.handlePaint,
+    );
+  }
+}