I have built a custom widget that it is a custom video player with chewie, it works on Test Mode but not on iphone.
Custom Video Player doesnt work on iphone.
Custom Code
Ask AI and check communities.
// Automatic FlutterFlow imports
import '/backend/backend.dart';
import '/backend/schema/structs/index.dart';
import '/backend/schema/enums/enums.dart';
import '/backend/supabase/supabase.dart';
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/custom_code/widgets/index.dart'; // Imports other custom widgets
import '/custom_code/actions/index.dart'; // Imports custom actions
import '/flutter_flow/custom_functions.dart'; // Imports custom functions
import 'package:flutter/material.dart';
// Begin custom widget code
// DO NOT REMOVE OR MODIFY THE CODE ABOVE!
import 'package:video_player/video_player.dart';
import 'package:chewie/chewie.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:visibility_detector/visibility_detector.dart';
class ChewieVideoPlayer extends StatefulWidget {
final String videoPath;
final double width;
final double height;
ChewieVideoPlayer({
required this.videoPath,
required this.width,
required this.height,
});
@override
_ChewieVideoPlayerState createState() => _ChewieVideoPlayerState();
}
class _ChewieVideoPlayerState extends State<ChewieVideoPlayer> {
VideoPlayerController? _videoController;
ChewieController? _chewieController;
bool _isLoading = true;
bool _currentlyVisible = false;
bool _videoInitialized = false;
GlobalKey videoKey = GlobalKey();
static List<GlobalKey> videoKeys = [];
static List<VideoPlayerController> allVideoControllers =
[]; // Lista de todos los controladores
static VideoPlayerController?
_currentlyPlayingController; // Video actualmente en reproducción
Future<void>? _initializationFuture;
@override
void initState() {
super.initState();
_loadVideoUrl();
_ChewieVideoPlayerState.videoKeys.add(videoKey);
}
Future<void> _loadVideoUrl() async {
if (!_videoInitialized) {
try {
String videoUrl = await FirebaseStorage.instance
.ref(widget.videoPath)
.getDownloadURL();
if (mounted) {
_initializationFuture = _initializePlayer(videoUrl);
}
} catch (e) {
debugPrint("Error loading video: $e");
if (mounted) {
setState(() => _isLoading = false);
}
}
}
}
Future<void> _initializePlayer(String videoUrl) async {
try {
_videoController = VideoPlayerController.network(videoUrl);
await _videoController?.initialize();
if (!mounted) return;
allVideoControllers
.add(_videoController!); // Agregar el controlador a la lista
_chewieController = ChewieController(
videoPlayerController: _videoController!,
autoPlay: false,
looping: true,
showControls: false,
aspectRatio: _videoController!.value.aspectRatio,
);
setState(() {
_isLoading = false;
_videoInitialized = true;
});
_videoController?.addListener(() {
if (_videoController?.value.hasError ?? false) {
debugPrint(
"Video error: ${_videoController?.value.errorDescription}");
}
});
// Reproducir automáticamente si está visible
if (_currentlyVisible) {
_playVideo();
}
} catch (e) {
debugPrint("Error initializing player: $e");
if (mounted) {
setState(() => _isLoading = false);
}
}
}
void _onVisibilityChanged(VisibilityInfo info) {
bool isVisible = info.visibleFraction > 0.9; // Umbral de 0.5 para pausa
if (_currentlyVisible != isVisible) {
setState(() {
_currentlyVisible = isVisible;
});
// Si el video está visible y ha sido inicializado, reproducirlo
if (_videoInitialized) {
if (_currentlyVisible) {
_playVideo();
} else {
_videoController?.pause();
}
}
}
}
void _playVideo() {
if (_currentlyPlayingController != null &&
_currentlyPlayingController != _videoController &&
_currentlyPlayingController!.value.isPlaying) {
_currentlyPlayingController?.pause();
}
_currentlyPlayingController = _videoController;
_videoController?.play();
}
void _togglePlayback() {
setState(() {
if (_videoController?.value.isPlaying ?? false) {
_videoController?.pause();
} else {
_playVideo();
}
});
}
@override
void dispose() {
if (_initializationFuture != null) {
_initializationFuture = null;
}
allVideoControllers
.remove(_videoController); // Remover el controlador al hacer dispose
if (_videoController?.value.isPlaying ?? false) {
_videoController?.pause(); // Pausa al hacer dispose
}
_videoController?.dispose();
_chewieController?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
double videoAspectRatio = _videoController?.value.aspectRatio ?? 16 / 9;
double videoHeight = screenWidth / videoAspectRatio;
return VisibilityDetector(
key: Key(widget.videoPath),
onVisibilityChanged: _onVisibilityChanged,
child: GestureDetector(
onTap: _togglePlayback,
child: Center(
child: SizedBox(
key: videoKey,
width: screenWidth,
height: videoHeight,
child: _isLoading
? const Center(child: CircularProgressIndicator())
: (_chewieController != null
? ClipRRect(
borderRadius: BorderRadius.zero,
child: FittedBox(
fit: BoxFit.cover,
child: SizedBox(
width: screenWidth,
height: videoHeight,
child: Chewie(controller: _chewieController!),
),
),
)
: const SizedBox.shrink()),
),
),
),
);
}
}
No
1