200 lines
6.5 KiB
Dart
200 lines
6.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:video_player/video_player.dart';
|
|
|
|
class VideoPage extends StatefulWidget {
|
|
const VideoPage({
|
|
super.key,
|
|
required this.title,
|
|
required this.videoPath,
|
|
});
|
|
|
|
final String title;
|
|
final String videoPath;
|
|
|
|
@override
|
|
State<VideoPage> createState() => _VideoPageState();
|
|
}
|
|
|
|
class _VideoPageState extends State<VideoPage> {
|
|
late final VideoPlayerController _controller;
|
|
late final Future<void> _initializeVideo;
|
|
bool _fullscreen = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
final uri = Uri.tryParse(widget.videoPath);
|
|
_controller = uri != null && uri.hasScheme
|
|
? VideoPlayerController.networkUrl(uri)
|
|
: VideoPlayerController.asset(widget.videoPath);
|
|
_initializeVideo = _controller.initialize().then((_) {
|
|
_controller
|
|
..setLooping(true)
|
|
..play();
|
|
if (mounted) {
|
|
setState(() {});
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
|
SystemChrome.setPreferredOrientations(DeviceOrientation.values);
|
|
_controller.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
void _togglePlayPause() {
|
|
setState(() {
|
|
_controller.value.isPlaying ? _controller.pause() : _controller.play();
|
|
});
|
|
}
|
|
|
|
Future<void> _toggleFullscreen() async {
|
|
setState(() => _fullscreen = !_fullscreen);
|
|
if (_fullscreen) {
|
|
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
|
|
await SystemChrome.setPreferredOrientations([
|
|
DeviceOrientation.landscapeLeft,
|
|
DeviceOrientation.landscapeRight,
|
|
]);
|
|
return;
|
|
}
|
|
|
|
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
|
await SystemChrome.setPreferredOrientations(DeviceOrientation.values);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: Colors.black,
|
|
body: Stack(
|
|
fit: StackFit.expand,
|
|
children: [
|
|
Center(
|
|
child: FutureBuilder<void>(
|
|
future: _initializeVideo,
|
|
builder: (context, snapshot) {
|
|
if (snapshot.connectionState != ConnectionState.done) {
|
|
return const DecoratedBox(
|
|
decoration: BoxDecoration(color: Colors.black),
|
|
child: Center(
|
|
child: CircularProgressIndicator(
|
|
color: Color(0xFF14B8C4),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
if (snapshot.hasError || _controller.value.hasError) {
|
|
return Padding(
|
|
padding: const EdgeInsets.all(24),
|
|
child: Text(
|
|
'Video wisata gagal dimuat.',
|
|
textAlign: TextAlign.center,
|
|
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.w800,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
return SizedBox.expand(
|
|
child: FittedBox(
|
|
fit: BoxFit.cover,
|
|
child: SizedBox(
|
|
width: _controller.value.size.width,
|
|
height: _controller.value.size.height,
|
|
child: VideoPlayer(_controller),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
const DecoratedBox(
|
|
decoration: BoxDecoration(
|
|
gradient: LinearGradient(
|
|
begin: Alignment.topCenter,
|
|
end: Alignment.bottomCenter,
|
|
colors: [
|
|
Color(0xCC000000),
|
|
Color(0x22000000),
|
|
Color(0xBB000000),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
SafeArea(
|
|
child: Padding(
|
|
padding: const EdgeInsets.fromLTRB(12, 8, 12, 20),
|
|
child: Column(
|
|
children: [
|
|
Row(
|
|
children: [
|
|
IconButton.filledTonal(
|
|
tooltip: 'Kembali',
|
|
onPressed: () => Navigator.pop(context),
|
|
icon: const Icon(Icons.arrow_back_rounded),
|
|
),
|
|
const SizedBox(width: 10),
|
|
Expanded(
|
|
child: Text(
|
|
widget.title,
|
|
maxLines: 2,
|
|
overflow: TextOverflow.ellipsis,
|
|
style:
|
|
Theme.of(context).textTheme.titleLarge?.copyWith(
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.w900,
|
|
),
|
|
),
|
|
),
|
|
IconButton.filledTonal(
|
|
tooltip:
|
|
_fullscreen ? 'Keluar fullscreen' : 'Fullscreen',
|
|
onPressed: _toggleFullscreen,
|
|
icon: Icon(
|
|
_fullscreen
|
|
? Icons.fullscreen_exit_rounded
|
|
: Icons.fullscreen_rounded,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const Spacer(),
|
|
ValueListenableBuilder<VideoPlayerValue>(
|
|
valueListenable: _controller,
|
|
builder: (context, value, child) {
|
|
return IconButton.filled(
|
|
tooltip: value.isPlaying ? 'Jeda' : 'Putar',
|
|
onPressed:
|
|
value.isInitialized ? _togglePlayPause : null,
|
|
iconSize: 40,
|
|
style: IconButton.styleFrom(
|
|
backgroundColor: Colors.white,
|
|
foregroundColor: const Color(0xFF0F4C81),
|
|
padding: const EdgeInsets.all(18),
|
|
),
|
|
icon: Icon(
|
|
value.isPlaying
|
|
? Icons.pause_rounded
|
|
: Icons.play_arrow_rounded,
|
|
),
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|