You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中YoutubePlayer全屏未占满屏幕及方向错误问题求助

YoutubePlayer全屏异常:仅横屏但未占满屏幕+方向切换错误

点击YoutubePlayer全屏按钮后,设备仅切换为横屏,但播放器无法占满整个屏幕,控制台输出以下错误:

Failed to change device orientation: Error Domain=UISceneErrorDomain Code=101 “None of the requested orientations are supported by the view controller. Requested: portrait; Supported: landscapeLeft, landscapeRight “ UserInfo={NSLocalizedDescription=None of the requested orientations are supported by the view controller. Requested: portrait; Supported: landscapeLeft, landscapeRight}

相关代码

Widget _buildRegularCard() {
    return Scaffold(
        appBar: AppBar(
            centerTitle: true,
            backgroundColor: Colors.black,
            leading: IconButton(
                onPressed: () => Navigator.pop(context, true),
                icon: const Icon(
                    Icons.arrow_back,
                    color: Colors.white,
                ),
            ),
        ),
        body: StreamBuilder(
            stream: FirebaseFirestore.instance
                .collection(widget.collectionName)
                .doc(widget.documentId)
                .snapshots(),
            builder: (context, snapshot) {
                if (snapshot.hasError) {
                    return const Text('Something went wrong');
                }

                if (snapshot.connectionState == ConnectionState.waiting) {
                    return const Center(
                        child: CircularProgressIndicator(
                            color: Colors.black,
                            strokeWidth: 15,
                            semanticsLabel: "Chargement",
                        )
                    );
                }

            String? videoId = YoutubePlayer.convertUrlToId(snapshot.data?["video"]);
            YoutubePlayerController controller = YoutubePlayerController(
                initialVideoId: videoId!,
                flags: const YoutubePlayerFlags(
                    autoPlay: false, 
                    mute: false, 
                    showLiveFullscreenButton: true
                ),
            );

            controller.addListener(() {
                if (controller.value.isFullScreen) {
                    SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
                } else {
                    SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
                }
            });

            return SingleChildScrollView(
                scrollDirection: Axis.vertical,
                child: Column(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                        Stack(
                            children: [
                                CachedNetworkImage(
                                    height: 400,
                                    width: double.infinity,
                                    fit: BoxFit.cover,
                                    imageUrl: snapshot.data?["image"],
                                ),
                                LikeButton(
                                    mainAxisAlignment: MainAxisAlignment.end,
                                    isLiked: isInFavorites,
                                    size: 60,
                                    onTap: (isLiked) async {
                                        String uid = FirebaseAuth.instance.currentUser?.uid ?? "";

                                        if (uid.isNotEmpty) {
                                            if (isInFavorites == true) {
                                                await FirebaseFirestore.instance
                                                    .collection('Utilisateurs')
                                                    .doc(uid)
                                                    .collection('favoris')
                                                    .doc(widget.documentId)
                                                    .delete();
                                                print("******* Suppresion du jeux");
                                            } else {
                                                await FirebaseFirestore.instance
                                                    .collection('Utilisateurs')
                                                    .doc(uid)
                                                    .collection('favoris')
                                                    .doc(widget.documentId)
                                                    .set({
                                                        'nom': snapshot.data?["nom"],
                                                        'image': snapshot.data?['image'],
                                                        'age': snapshot.data?['age'],
                                                        'but': snapshot.data?['but'],
                                                        'materiel': snapshot.data?['materiel'],
                                                        'nombreJoueurs': snapshot.data?['nombreJoueurs'],
                                                        'rating': snapshot.data?['rating'],
                                                        'type de jeux': snapshot.data?['type de jeux'],
                                                        'video': snapshot.data?['video'],
                                                    });
                                                print("Ajout du jeux");
                                            }

                                            setState(() {
                                                if (isInFavorites == true) {
                                                    isInFavorites = false;
                                                } else {
                                                    isInFavorites = true;
                                                }
                                            });
                                        }
                                    },
                                    bubblesColor: BubblesColor(
                                        dotPrimaryColor: Theme.of(context).primaryColor,
                                        dotSecondaryColor: Theme.of(context).secondaryHeaderColor,
                                    ),
                                    circleColor: const CircleColor(
                                        start: Colors.yellow, 
                                        end: Colors.green
                                    ),
                                    likeBuilder: (test) {
                                        isInFavorites = test;
                                        test == false
                                            ? Image.asset("assets/icons/unlike.png")
                                            : Image.asset("assets/icons/like.png");
                                    },
                                ),
                            ],
                        ),
                        RatingStarFix(
                            size: 40,
                            collectionName: widget.collectionName,
                            documentId: widget.documentId,
                        ),
                        TextActivitesDescriptionTitle(
                            text: snapshot.data?["nom"],
                            color: const Color(0xffe2324e),
                            size: 50,
                        ),
                        CardActivitiesDescription(
                            text: snapshot.data?["nom"],
                            padding: 0,
                            color: Colors.black,
                            subtext: "Nom : ",
                        ),
                        CardActivitiesDescription(
                            text: "age",
                            padding: 0,
                            color: Colors.black,
                            subtext: 'Age : ',
                        ),
                        CardActivitiesDescription(
                            text: snapshot.data?["but"],
                            padding: 0,
                            color: Colors.black,
                            subtext: "But : ",
                        ),
                        CardActivitiesDescription(
                            text: snapshot.data?["materiel"],
                            padding: 0,
                            color: Colors.black,
                            subtext: "Materiel : ",
                        ),
                        CardActivitiesDescription(
                            text: snapshot.data?["nombreJoueurs"],
                            padding: 0,
                            color: Colors.black,
                            subtext: 'Nombres Joueurs : ',
                        ),
                        CardActivitiesDescription(
                            text: snapshot.data?["deroulement"],
                            padding: 0,
                            color: Colors.black,
                            subtext: 'Deroullement : ',
                        ),
                        snapshot.data?["video"] == ""
                            ? Container(
                                height: 200,
                                width: 200,
                                child: const Center(
                                    child: Text("Video En cour de fabrication "),
                                ),
                            )
                            : Padding(
                                padding: const EdgeInsets.all(15),
                                child: YoutubePlayerBuilder(
                                    player: YoutubePlayer(
                                        controller: controller,
                                        aspectRatio: 16 / 7,
                                        showVideoProgressIndicator: true,
                                        progressIndicatorColor: Colors.amber,
                                        progressColors: const ProgressBarColors(
                                            playedColor: Colors.amber,
                                            handleColor: Colors.amberAccent,
                                        ),
                                        onReady: () {
                                            controller.addListener(() {});
                                        },
                                    ),
                                    builder: (BuildContext, player) {
                                        return Column(
                                            children: [
                                                player,
                                            ],
                                        );
                                    },
                                ),
                            ),
                        const Divider(height: 40, thickness: 2),
                        const Text(
                            "Commentaires",
                            style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
                        ),
                        StreamBuilder(
                            stream: FirebaseFirestore.instance
                                .collection(widget.collectionName)
                                .doc(widget.documentId)
                                .collection('comments')
                                .snapshots(),
                            builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
                                if (!snapshot.hasData) {
                                    return const Center(child: CircularProgressIndicator());
                                }

                                var comments = snapshot.data!.docs;
                                return ListView.builder(
                                    shrinkWrap: true,
                                    physics: const NeverScrollableScrollPhysics(),
                                    itemCount: comments.length,
                                    itemBuilder: (context, index) {
                                        var comment = comments[index];
                                        return ListTile(
                                            title: Text(comment['username']),
                                            subtitle: Text(comment['content']),
                                            trailing: RatingStarDisplay(
                                                size: 20,
                                                rating: comment['rating'],
                                            ),
                                        );
                                    },
                                );
                            },
                        ),
                        ElevatedButton(
                            onPressed: () {
                                Navigator.push(
                                    context,
                                    MaterialPageRoute(
                                        builder: (context) => AddCommentPage(
                                            documentId: widget.documentId,
                                            collectionName: widget.collectionName,
                                        ),
                                    ),
                                );
                            },
                            child: const Text("Ajouter un commentaire"),
                        ),
                    ],
                ),
            );
        },
    ),
);
}

问题原因

错误提示明确:退出全屏时,播放器请求切换回竖屏,但当前ViewController不支持竖屏方向,导致方向切换失败,进而破坏了全屏状态的正常流转,最终出现播放器无法占满屏幕的异常。另外,每次StreamBuilder重建都会重新创建YoutubePlayerController,导致状态丢失,也是问题的诱因之一。

修复方案

1. 允许页面支持所有所需方向

在当前页面的State类中添加方向控制逻辑:

@override
void initState() {
  super.initState();
  // 初始化时允许所有必要方向
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
    DeviceOrientation.landscapeLeft,
    DeviceOrientation.landscapeRight,
  ]);
}

@override
void dispose() {
  // 页面销毁后恢复默认竖屏(根据APP需求调整)
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
  super.dispose();
}

2. 避免重复创建YoutubePlayerController

将Controller移到State类中初始化,防止StreamBuilder重建时丢失状态:

late YoutubePlayerController _controller;

@override
void didChangeDependencies() {
  super.didChangeDependencies();
  // 从Stream数据中安全获取videoUrl并初始化Controller
  final videoUrl = snapshot.data?["video"];
  String? videoId = YoutubePlayer.convertUrlToId(videoUrl ?? "");
  _controller = YoutubePlayerController(
    initialVideoId: videoId!,
    flags: const YoutubePlayerFlags(
      autoPlay: false, 
      mute: false, 
      showLiveFullscreenButton: true
    ),
  );
  _controller.addListener(() {
    if (_controller.value.isFullScreen) {
      SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
    } else {
      SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
      // 确保退出全屏时方向可切换回竖屏
      SystemChrome.setPreferredOrientations([
        DeviceOrientation.portraitUp,
        DeviceOrientation.portraitDown,
        DeviceOrientation.landscapeLeft,
        DeviceOrientation.landscapeRight,
      ]);
    }
  });
}

@override
void dispose() {
  _controller.dispose();
  super.dispose();
}

3. 优化YoutubePlayerBuilder布局

全屏模式下让播放器直接占满屏幕,避免被Column约束:

YoutubePlayerBuilder(
  player: YoutubePlayer(
    controller: _controller,
    aspectRatio: 16 / 7,
    showVideoProgressIndicator: true,
    progressIndicatorColor: Colors.amber,
    progressColors: const ProgressBarColors(
      playedColor: Colors.amber,
      handleColor: Colors.amberAccent,
    ),
  ),
  builder: (context, player) {
    return _controller.value.isFullScreen ? player : Column(children: [player]);
  },
)

4. 检查全局方向设置

在main.dart中确保APP没有全局锁定方向:

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.landscapeLeft,
    DeviceOrientation.landscapeRight,
  ]);
  runApp(const MyApp());
}

内容的提问来源于stack exchange,提问作者nabil bouzid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 17:37:02