Skip to content

Instantly share code, notes, and snippets.

@hoc081098
Created June 26, 2023 16:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hoc081098/88382f87ea40a6d57c670751db2eb3e6 to your computer and use it in GitHub Desktop.
Save hoc081098/88382f87ea40a6d57c670751db2eb3e6 to your computer and use it in GitHub Desktop.
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