full funcing video player in flutter

Video Player

  



     import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
import 'package:flutter/services.dart'; // SystemChrome ke liye
import 'dart:async'; // Timer ke liye


class VideoPlayerApp extends StatelessWidget {
  const VideoPlayerApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ExoPlayer-like Video Player',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: const HomeScreen(), // HomeScreen ab bhi initial route hai
    );
  }
}

// Screen 1: Home Screen
class HomeScreen extends StatefulWidget { // Changed to StatefulWidget to use initState
  const HomeScreen({super.key});

  @override
  State createState() => _HomeScreenState();
}

class _HomeScreenState extends State {
  // Hardcoded video URL jise hum pass karenge
  final String _hardcodedVideoUrl = 'https://cdn-st0.mootion.com/videos/7b73f8f78d7f40c6b1d7f35725ec3748.mp4';

  @override
  void initState() {
    super.initState();
    // Use addPostFrameCallback to navigate after the first frame is built
    WidgetsBinding.instance.addPostFrameCallback((_) {
      Navigator.pushReplacement( // Use pushReplacement to remove HomeScreen from stack
        context,
        MaterialPageRoute(
          builder: (context) => VideoPlayerScreen(videoUrl: _hardcodedVideoUrl),
        ),
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Video Player App'),
      ),
      body: const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            CircularProgressIndicator(), // Show a loading indicator
            SizedBox(height: 16),
            Text('Loading video...', style: TextStyle(fontSize: 18)),
          ],
        ),
      ),
    );
  }
}

// Screen 2: Video Player Screen (jo VideoPlayerWidget ko use karegi)
class VideoPlayerScreen extends StatefulWidget {
  final String videoUrl; // Video URL ko receive karne ke liye

  const VideoPlayerScreen({super.key, required this.videoUrl});

  @override
  State createState() => _VideoPlayerScreenState();
}

class _VideoPlayerScreenState extends State {
  bool _isFullScreen = false; // VideoPlayerScreen mein fullscreen state rakhenge

  void _setFullScreen(bool isFullScreen) {
    setState(() {
      _isFullScreen = isFullScreen;
    });
  }

  @override
  void dispose() {
    // Ye important hai: jab screen dispose ho to UI mode aur orientation restore karein
    SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
      DeviceOrientation.portraitDown,
      DeviceOrientation.landscapeLeft,
      DeviceOrientation.landscapeRight,
    ]);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // AppBar ko conditional hide/show karein
      appBar: _isFullScreen
          ? null // Fullscreen mein AppBar hide kar do
          : AppBar(
        title: const Text('Video Player'),
      ),
      // HERE IS THE CHANGE: Set background color to black when in full screen
      backgroundColor: _isFullScreen ? Colors.black : Theme.of(context).scaffoldBackgroundColor,
      body: Center(
        child: VideoPlayerWidget(
          videoUrl: widget.videoUrl,
          onFullScreenToggle: _setFullScreen, // Callback pass karo
        ),
      ),
    );
  }
}


// Naya Widget: VideoPlayerWidget (jo player ka core logic aur UI rakhega)
class VideoPlayerWidget extends StatefulWidget {
  final String videoUrl;
  final Function(bool) onFullScreenToggle; // Callback function added

  const VideoPlayerWidget({super.key, required this.videoUrl, required this.onFullScreenToggle});

  @override
  State createState() => _VideoPlayerWidgetState();
}

class _VideoPlayerWidgetState extends State {
  late VideoPlayerController _controller;
  bool _isControllerInitialized = false;
  bool _isControlsVisible = true;
  bool _isFullScreen = false; // VideoPlayerWidget mein bhi state rakhenge
  bool _hasError = false;
  double _seekPosition = 0.0; // Slider ke temporary seek position ke liye
  Timer? _hideControlsTimer; // For auto-hiding controls

  @override
  void initState() {
    super.initState();
    SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
    SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);

    _initializeVideoPlayer();
  }

  void _initializeVideoPlayer() {
    _controller = VideoPlayerController.networkUrl(Uri.parse(widget.videoUrl))
      ..addListener(() {
        if (mounted) {
          setState(() {
            // Slider ko update karne ke liye current position ko bhi update karein
            _seekPosition = _controller.value.position.inMilliseconds.toDouble();

            // Auto-hide controls jab video play ho aur controls visible hon
            if (_controller.value.isPlaying && _isControlsVisible) {
              _startHideControlsTimer();
            } else {
              _hideControlsTimer?.cancel(); // Pause ya buffering pe timer cancel karo
            }
          });
        }
      })
      ..initialize().then((_) {
        setState(() {
          _isControllerInitialized = true;
          _controller.play(); // Video automatically plays here
          _isControlsVisible = true; // Initial controls visible
          _hasError = false;
          _startHideControlsTimer(); // Start timer after playing
        });
      }).catchError((error) {
        print("Error initializing video: $error");
        setState(() {
          _isControllerInitialized = false;
          _isControlsVisible = false;
          _hasError = true;
        });
      });
  }

  void _startHideControlsTimer() {
    _hideControlsTimer?.cancel(); // Puraane timer ko cancel karo
    _hideControlsTimer = Timer(const Duration(seconds: 3), () {
      if (mounted && _isControlsVisible) { // Check if mounted and controls are still visible
        setState(() {
          _isControlsVisible = false;
        });
      }
    });
  }

  void _toggleControlsVisibility() {
    setState(() {
      _isControlsVisible = !_isControlsVisible;
      if (_isControlsVisible) {
        _startHideControlsTimer(); // Controls visible hone pe timer reset karo
      } else {
        _hideControlsTimer?.cancel(); // Controls hidden hone pe timer cancel karo
      }
    });
  }

  void _toggleFullscreen() {
    setState(() {
      _isFullScreen = !_isFullScreen;
      widget.onFullScreenToggle(_isFullScreen); // Parent ko notify karo

      if (_isFullScreen) {
        SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
        SystemChrome.setPreferredOrientations([
          DeviceOrientation.landscapeLeft,
          DeviceOrientation.landscapeRight,
        ]);
      } else {
        SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
        SystemChrome.setPreferredOrientations([
          DeviceOrientation.portraitUp,
        ]);
      }
      _startHideControlsTimer(); // Fullscreen toggle par timer reset karo
    });
  }

  // Duration ko HH:MM:SS ya MM:SS format mein convert karne ke liye helper function
  String _formatDuration(Duration duration) {
    String twoDigits(int n) => n.toString().padLeft(2, '0');
    final hours = twoDigits(duration.inHours);
    final minutes = twoDigits(duration.inMinutes.remainder(60));
    final seconds = twoDigits(duration.inSeconds.remainder(60));
    if (duration.inHours > 0) {
      return '$hours:$minutes:$seconds';
    }
    return '$minutes:$seconds';
  }

  // Back button press ko handle karne ke liye
  Future _onWillPop() async {
    if (_isFullScreen) {
      _toggleFullscreen(); // Fullscreen se exit karo
      return false; // Pop ko block karo
    }
    return true; // Normal back button behavior
  }

  @override
  void dispose() {
    _controller.dispose();
    _hideControlsTimer?.cancel(); // Timer ko dispose karna zaroori hai
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope( // WillPopScope add kiya back button handling ke liye
      onWillPop: _onWillPop,
      child: _isControllerInitialized
          ? GestureDetector(
        onTap: _toggleControlsVisibility,
        child: Stack( // Wrap everything in a Stack to layer video and controls
          children: [
            // Video Player
            _isFullScreen
                ? SizedBox.expand(
              child: FittedBox(
                fit: BoxFit.contain,
                child: SizedBox(
                  width: _controller.value.size.width,
                  height: _controller.value.size.height,
                  child: VideoPlayer(_controller), // Only VideoPlayer here
                ),
              ),
            )
                : AspectRatio(
              aspectRatio: _controller.value.aspectRatio,
              child: VideoPlayer(_controller),
            ),

            // Controls, positioned over the video
            if (_isControlsVisible)
              Positioned.fill(
                child: Container(
                  color: Colors.black.withOpacity(0.3),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: [
                      // Current time and total duration
                      Padding(
                        padding: const EdgeInsets.symmetric(horizontal: 16.0),
                        child: Row(
                          children: [
                            Text(
                              _formatDuration(_controller.value.position),
                              style: const TextStyle(color: Colors.white),
                            ),
                            Expanded(
                              child: SliderTheme(
                                data: SliderTheme.of(context).copyWith(
                                  activeTrackColor: Colors.red,
                                  inactiveTrackColor: Colors.grey,
                                  thumbColor: Colors.red, // Thumb ka color
                                  overlayColor: Colors.red.withOpacity(0.3),
                                  thumbShape: const RoundSliderThumbShape(enabledThumbRadius: 10.0), // Bada dot
                                  overlayShape: const RoundSliderOverlayShape(overlayRadius: 20.0), // Jab press karein to bada circle
                                ),
                                child: Slider(
                                  value: _seekPosition,
                                  min: 0.0,
                                  max: _controller.value.duration.inMilliseconds.toDouble(),
                                  onChanged: (value) {
                                    setState(() {
                                      _seekPosition = value; // Temporary update for visual feedback
                                    });
                                    _startHideControlsTimer(); // User interaction, reset timer
                                  },
                                  onChangeEnd: (value) {
                                    _controller.seekTo(Duration(milliseconds: value.toInt()));
                                    _startHideControlsTimer(); // User interaction, reset timer
                                  },
                                ),
                              ),
                            ),
                            Text(
                              _formatDuration(_controller.value.duration),
                              style: const TextStyle(color: Colors.white),
                            ),
                          ],
                        ),
                      ),
                      Row(
                        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                        children: [
                          IconButton(
                            icon: Icon(
                              _controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
                              color: Colors.white,
                              size: 30, // Keep a consistent size
                            ),
                            onPressed: () {
                              setState(() {
                                _controller.value.isPlaying
                                    ? _controller.pause()
                                    : _controller.play();
                              });
                              _startHideControlsTimer(); // User interaction, reset timer
                            },
                          ),
                          IconButton(
                            icon: const Icon(Icons.stop, color: Colors.white, size: 30), // Consistent size
                            onPressed: () {
                              setState(() {
                                _controller.seekTo(Duration.zero);
                                _controller.pause();
                              });
                              _startHideControlsTimer(); // User interaction, reset timer
                            },
                          ),
                          IconButton(
                            icon: Icon(
                              _controller.value.volume > 0 ? Icons.volume_up : Icons.volume_off,
                              color: Colors.white,
                              size: 30, // Consistent size
                            ),
                            onPressed: () {
                              setState(() {
                                _controller.setVolume(_controller.value.volume > 0 ? 0.0 : 1.0);
                              });
                              _startHideControlsTimer(); // User interaction, reset timer
                            },
                          ),
                          // Fullscreen button
                          IconButton(
                            icon: Icon(
                              _isFullScreen ? Icons.fullscreen_exit : Icons.fullscreen,
                              color: Colors.white,
                              size: 30, // Consistent size
                            ),
                            onPressed: _toggleFullscreen, // This already calls _startHideControlsTimer
                          ),
                        ],
                      ),
                      const SizedBox(height: 10),
                    ],
                  ),
                ),
              ),
          ],
        ),
      )
          : Container(
        height: _isFullScreen ? MediaQuery.of(context).size.height : 200,
        color: Colors.black,
        child: Center(
          // Replaced Text with CircularProgressIndicator
          child: _hasError
              ? const Text(
            'Video load nahi ho paya.',
            style: TextStyle(color: Colors.white),
          )
              : const CircularProgressIndicator(
            valueColor: AlwaysStoppedAnimation(Colors.white),
          ),
        ),
      ),
    );
  }
}


 

  

Post a Comment

0 Comments