Created
June 26, 2023 16:09
-
-
Save hoc081098/88382f87ea40a6d57c670751db2eb3e6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:video_player/video_player.dart'; | |
class VideoQuestion extends StatefulWidget { | |
final String videoUrl; | |
VideoQuestion({Key? key, required this.videoUrl}) | |
: super(key: key); | |
@override | |
State<VideoQuestion> createState() => _VideoQuestionState(); | |
} | |
class _VideoQuestionState extends State<VideoQuestion> { | |
late final _controller = VideoPlayerController.network( | |
widget.videoUrl, | |
); | |
final _touched = ValueNotifier<bool>(false); | |
late final Future<void> _initFuture; | |
@override | |
void initState() { | |
super.initState(); | |
_initFuture = _controller.initialize(); | |
_touched.addListener(() => debugPrint('touched: ${_touched.value}')); | |
} | |
@override | |
void dispose() { | |
_touched.dispose(); | |
_controller.dispose(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Column( | |
crossAxisAlignment: CrossAxisAlignment.stretch, | |
children: [ | |
FutureBuilder<void>( | |
future: _initFuture, | |
builder: (context, snapshot) { | |
if (snapshot.connectionState == ConnectionState.done) { | |
if (_controller.value.hasError) { | |
final width = MediaQuery.of(context).size.width - 18 * 2; | |
final height = width * 9 / 16; | |
return Container( | |
width: width, | |
height: height, | |
color: Colors.white.withOpacity(0.5), | |
child: Center( | |
child: Column( | |
mainAxisSize: MainAxisSize.min, | |
children: const [ | |
Icon(Icons.error, color: Colors.white), | |
SizedBox(height: 8.0), | |
Text( | |
'Error', | |
style: TextStyle( | |
color: Colors.white, | |
), | |
), | |
], | |
), | |
), | |
); | |
} | |
return GestureDetector( | |
onTap: () { | |
if (_controller.value.isPlaying) { | |
_touched.value = !_touched.value; | |
} | |
}, | |
child: AspectRatio( | |
aspectRatio: _controller.value.aspectRatio, | |
child: Stack( | |
children: [ | |
Positioned.fill( | |
child: AspectRatio( | |
aspectRatio: _controller.value.aspectRatio, | |
child: VideoPlayer(_controller), | |
), | |
), | |
Positioned.fill( | |
child: ValueListenableBuilder<VideoPlayerValue>( | |
valueListenable: _controller, | |
builder: _buildOverlay, | |
), | |
), | |
], | |
), | |
), | |
); | |
} else { | |
final width = MediaQuery.of(context).size.width - 18 * 2; | |
final height = width * 9 / 16; | |
return Container( | |
height: height, | |
width: width, | |
color: Colors.white.withOpacity(0.2), | |
child: const Center( | |
child: CircularProgressIndicator( | |
strokeWidth: 2, | |
), | |
), | |
); | |
} | |
}, | |
), | |
const SizedBox(height: 50), | |
], | |
); | |
} | |
Widget _buildOverlay( | |
BuildContext context, | |
VideoPlayerValue value, | |
Widget? child, | |
) { | |
if (value.isBuffering) { | |
return const Center( | |
child: CircularProgressIndicator( | |
strokeWidth: 2, | |
), | |
); | |
} | |
if (value.isPlaying) { | |
return ValueListenableBuilder<bool>( | |
valueListenable: _touched, | |
builder: (context, touched, child) { | |
if (touched) { | |
return Container( | |
color: Colors.white.withOpacity(0.2), | |
child: Center( | |
child: IconButton( | |
onPressed: _controller.pause, | |
icon: const Icon( | |
Icons.pause_circle_filled, | |
color: Colors.white, | |
), | |
iconSize: 56, | |
), | |
), | |
); | |
} | |
return const SizedBox.expand(); | |
}, | |
); | |
} | |
return Container( | |
color: Colors.white.withOpacity(0.2), | |
child: Center( | |
child: IconButton( | |
onPressed: () async { | |
_touched.value = false; | |
await _controller.seekTo(Duration.zero); | |
await _controller.play(); | |
}, | |
icon: const Icon( | |
Icons.play_circle_fill, | |
color: Colors.white, | |
), | |
iconSize: 56, | |
), | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment