simple_player 3.0.1
simple_player: ^3.0.1 copied to clipboard
SimplePlayer offers all the essential tools for viewing videos in your mobile applications in a simplified way!
import 'package:flutter/material.dart';
import 'package:simple_player/simple_player.dart';
void main() {
runApp(const MaterialApp(
debugShowCheckedModeBanner: false,
home: MyHomePage(),
));
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
SimpleController simpleController = SimpleController();
// Example link provided in the video_player package on which SimplePlayer is based.
String url =
'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4';
// Attributes
String currentPosition = '...';
String stremPosition = '...';
// Drives the BoxFit demo below.
BoxFit fit = BoxFit.cover;
BoxFit fullScreenFit = BoxFit.contain;
// This is where the lsitener for the decorator of the video playback seconds starts.
void _initListener() {
simpleController.listenPosition().listen((event) {
// Updated seconds in the interface.
// Requires setState to update seconds counter.
setState(() {
stremPosition = event.toString();
});
});
}
@override
void initState() {
// initialize listener.
_initListener();
super.initState();
}
@override
void dispose() {
// dispose the control to avoid complications and conflicts
// with other playable controllers that can be used.
simpleController.dispose();
super.dispose();
}
// Small helper to switch a BoxFit at runtime.
Widget _fitSelector({
required String label,
required BoxFit value,
required ValueChanged<BoxFit> onChanged,
}) {
const List<BoxFit> options = [
BoxFit.contain,
BoxFit.cover,
BoxFit.fill,
BoxFit.fitWidth,
BoxFit.fitHeight,
];
return Row(
children: [
Expanded(child: Text(label)),
DropdownButton<BoxFit>(
value: value,
items: [
for (final BoxFit option in options)
DropdownMenuItem<BoxFit>(
value: option,
child: Text(option.name),
),
],
onChanged: (BoxFit? selected) {
if (selected != null) onChanged(selected);
},
),
],
);
}
// Here a basic interface will be built,
// with the player and its simple controls,
// and also the use of the player through
// SimpleController in a very simplified way!
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('SimplePlayer Example'),
backgroundColor: Colors.grey),
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
// Player wrapped in a padding.
//
// The player box is a 1:1 square while the video is 16:9, so with
// `fit: BoxFit.cover` the video is cropped to fill the square and
// the controls stay fully visible on top of it.
Padding(
padding: const EdgeInsets.all(8.0),
child: SimplePlayer(
simpleController: simpleController,
simplePlayerSettings: SimplePlayerSettings.network(
// Only the path is required, all other parameters are optional
path: url,
label: 'Bee',
aspectRatio: 1 / 1,
autoPlay: true,
loopMode: false,
fit: fit,
fullScreenFit: fullScreenFit,
colorAccent: Colors.red,
),
),
),
// BoxFit playground.
Container(
margin: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8.0),
color: Colors.green.withValues(alpha: 0.1),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'BoxFit',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16, color: Colors.green),
),
const Divider(thickness: 2),
_fitSelector(
label: 'fit (inline)',
value: fit,
onChanged: (value) => setState(() => fit = value),
),
_fitSelector(
label: 'fullScreenFit',
value: fullScreenFit,
onChanged: (value) =>
setState(() => fullScreenFit = value),
),
],
),
),
// Start using the controller.
Container(
margin: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(8.0),
color: Colors.blue.withValues(alpha: 0.1),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'Using the controller',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16, color: Colors.red),
),
const Divider(thickness: 2),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
TextButton.icon(
label: const Text("Play Video"),
icon: const Icon(Icons.play_arrow_rounded),
onPressed: () {
// Does not require setState to play.
simpleController.play();
},
),
TextButton.icon(
label: const Text("Pause Video"),
icon: const Icon(Icons.pause_rounded),
onPressed: () {
// Does not require setState to pause.
simpleController.pause();
},
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
TextButton.icon(
label: const Text("Get Current Position"),
icon: const Icon(Icons.timer_outlined),
onPressed: () {
//Requires setState to update seconds counter.
setState(() {
currentPosition =
simpleController.position.toString();
});
},
),
Text(currentPosition)
],
),
// Here the result of the listener is displayed
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
TextButton.icon(
label: const Text(" Stream Position"),
icon: const Icon(Icons.ondemand_video_rounded,
color: Colors.red),
onPressed: null,
),
Text(stremPosition)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
for (final double rate in <double>[0.5, 1.0, 1.5, 2.0])
TextButton(
onPressed: () => simpleController.setSpeed(rate),
child: Text('${rate}x'),
),
],
),
const Divider(),
const Text(
'.delete() This method does not need to be called in normal cases, '
'SimplePlayer already has an AutoDispose to facilitate its correct use.',
style: TextStyle(color: Colors.orange),
textAlign: TextAlign.center,
),
TextButton.icon(
label: const Text(
"Dispose SimpleController",
style: TextStyle(color: Colors.grey),
),
icon: const Icon(
Icons.delete_forever_outlined,
color: Colors.grey,
),
onPressed: () {
// Does not require setState to play.
simpleController.delete();
},
),
],
),
),
],
),
),
);
}
}