You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
350 lines
8.5 KiB
350 lines
8.5 KiB
|
|
import 'dart:async';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:recook/widgets/play_widget/utils.dart';
|
|
import 'package:video_player/video_player.dart';
|
|
|
|
import 'chewie_progress_colors.dart';
|
|
import 'material_progress_bar.dart';
|
|
|
|
class ShortVideoController extends StatefulWidget {
|
|
VideoPlayerController controller;
|
|
@override
|
|
State<StatefulWidget> createState() {
|
|
return _MaterialControlsState(controller);
|
|
}
|
|
ShortVideoController(this.controller);
|
|
}
|
|
|
|
class _MaterialControlsState extends State<ShortVideoController> {
|
|
VideoPlayerValue _latestValue;
|
|
double _latestVolume;
|
|
bool _hideStuff = true;
|
|
Timer _hideTimer;
|
|
Timer _initTimer;
|
|
Timer _showAfterExpandCollapseTimer;
|
|
bool _dragging = false;
|
|
bool _displayTapped = false;
|
|
bool _isChangeTime = false;
|
|
|
|
final barHeight = 48.0;
|
|
final marginSize = 5.0;
|
|
|
|
VideoPlayerController controller;
|
|
|
|
_MaterialControlsState(this.controller) {
|
|
_latestValue = this.controller.value;
|
|
}
|
|
|
|
@override
|
|
void initState() {
|
|
// TODO: implement initState
|
|
super.initState();
|
|
_initialize();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return MouseRegion(
|
|
onHover: (_) {
|
|
_cancelAndRestartTimer();
|
|
},
|
|
child: GestureDetector(
|
|
onTap: () {
|
|
_cancelAndRestartTimer();
|
|
_playPause();
|
|
},
|
|
child: AbsorbPointer(
|
|
absorbing: _hideStuff,
|
|
child: Column(
|
|
children: <Widget>[
|
|
// _latestValue != null &&
|
|
// !_latestValue.isPlaying &&
|
|
// _latestValue.duration == null ||
|
|
if (_latestValue.isBuffering)
|
|
const Expanded(
|
|
child: Center(
|
|
child: CircularProgressIndicator(),
|
|
),
|
|
)
|
|
else
|
|
_buildHitArea(),
|
|
_buildBottomBar(context),
|
|
SizedBox(height: 20,)
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
void _dispose() {
|
|
controller.removeListener(_updateState);
|
|
_hideTimer?.cancel();
|
|
_initTimer?.cancel();
|
|
_showAfterExpandCollapseTimer?.cancel();
|
|
}
|
|
|
|
AnimatedOpacity _buildBottomBar(
|
|
BuildContext context,
|
|
) {
|
|
final iconColor = Colors.white;
|
|
|
|
return AnimatedOpacity(
|
|
opacity: _hideStuff ? 0.0 : 1.0,
|
|
duration: Duration(milliseconds: 300),
|
|
child: Container(
|
|
height: barHeight,
|
|
color: Colors.transparent,
|
|
child: Column(
|
|
children: <Widget>[
|
|
//_buildPlayPause(controller),
|
|
|
|
_isChangeTime?_buildPosition(iconColor):SizedBox(height: 15.5,),
|
|
_buildProgressBar(),
|
|
//_buildMuteButton(controller),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Expanded _buildHitArea() {
|
|
return Expanded(
|
|
child: GestureDetector(
|
|
onTap: () {
|
|
_playPause();
|
|
if ( _latestValue.isPlaying) {
|
|
|
|
if (_displayTapped) {
|
|
|
|
setState(() {
|
|
_hideStuff = true;
|
|
});
|
|
} else
|
|
_cancelAndRestartTimer();
|
|
} else {
|
|
|
|
|
|
setState(() {
|
|
_hideStuff = false;
|
|
});
|
|
}
|
|
},
|
|
child: Container(
|
|
color: Colors.transparent,
|
|
child: Center(
|
|
child: AnimatedOpacity(
|
|
opacity:
|
|
!_latestValue.isPlaying && !_dragging
|
|
? 1.0
|
|
: 0.0,
|
|
duration: Duration(milliseconds: 300),
|
|
child: GestureDetector(
|
|
child: Container(
|
|
// decoration: BoxDecoration(
|
|
// color: Colors.white.withOpacity(0.3),
|
|
// borderRadius: BorderRadius.circular(48.0),
|
|
// ),
|
|
child: Padding(
|
|
padding: EdgeInsets.all(12.0),
|
|
child: Icon(Icons.play_arrow_rounded, size: 112.0,color: Colors.white.withOpacity(0.3),),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
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: Icon(
|
|
controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
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: 24.0),
|
|
child: Text(
|
|
'${formatDuration(position)} / ${formatDuration(duration)}',
|
|
style: TextStyle(
|
|
fontSize: 14.0,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _cancelAndRestartTimer() {
|
|
_hideTimer?.cancel();
|
|
_startHideTimer();
|
|
|
|
setState(() {
|
|
_hideStuff = false;
|
|
_displayTapped = true;
|
|
});
|
|
}
|
|
|
|
Future<Null> _initialize() async {
|
|
controller.addListener(_updateState);
|
|
|
|
_updateState();
|
|
|
|
if (controller.value.isPlaying) {
|
|
_startHideTimer();
|
|
}
|
|
_initTimer = Timer(Duration(milliseconds: 200), () {
|
|
setState(() {
|
|
_hideStuff = false;
|
|
});
|
|
});
|
|
}
|
|
|
|
void _playPause() {
|
|
bool isFinished;
|
|
if (_latestValue.duration != null) {
|
|
isFinished = _latestValue.position >= _latestValue.duration;
|
|
} else {
|
|
isFinished = false;
|
|
}
|
|
|
|
setState(() {
|
|
if (controller.value.isPlaying) {
|
|
_hideStuff = false;
|
|
_hideTimer?.cancel();
|
|
controller.pause();
|
|
} else {
|
|
_cancelAndRestartTimer();
|
|
controller.play();
|
|
if (!controller.value.isInitialized) {
|
|
controller.initialize().then((_) {
|
|
controller.play();
|
|
});
|
|
} else {
|
|
print('_playPause.else');
|
|
if (isFinished) {
|
|
controller.seekTo(Duration(seconds: 0));
|
|
}
|
|
controller.play();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
void _startHideTimer() {
|
|
_hideTimer = Timer(const Duration(seconds: 3), () {
|
|
setState(() {
|
|
_hideStuff = true;
|
|
});
|
|
});
|
|
}
|
|
|
|
void _updateState() {
|
|
setState(() {
|
|
_latestValue = controller.value;
|
|
});
|
|
}
|
|
|
|
Widget _buildProgressBar() {
|
|
return Expanded(
|
|
child: Padding(
|
|
padding: EdgeInsets.only(right: 20.0,left: 20.0),
|
|
child: MaterialVideoProgressBar(
|
|
controller,
|
|
onDragStart: () {
|
|
setState(() {
|
|
_dragging = true;
|
|
_isChangeTime = true;
|
|
});
|
|
|
|
_hideTimer?.cancel();
|
|
},
|
|
onDragEnd: () {
|
|
setState(() {
|
|
_dragging = false;
|
|
_isChangeTime = false;
|
|
});
|
|
|
|
_startHideTimer();
|
|
},
|
|
onDragUpdate: (){
|
|
if(!controller.value.isPlaying)
|
|
controller.play();
|
|
},
|
|
colors: ChewieProgressColors(
|
|
playedColor: Colors.white,
|
|
handleColor: Colors.white,
|
|
bufferedColor: Color(0xFF999999),
|
|
backgroundColor: Color(0xFF999999),
|
|
),
|
|
),
|
|
)
|
|
);
|
|
}
|
|
}
|