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

Flutter实现视频结束后显示问答组件的问题求助

解决Quiz App视频播放完再显示题目的问题

问题根源

  1. 精度匹配问题:视频播放结束时,_videoPlayerController.value.position和_videoPlayerController.value.duration几乎不会完全相等(比如视频时长10.000秒,position可能停在9.999秒就触发结束),直接判断相等会导致条件不触发。
  2. 初始状态误判:应用启动或切换题目时,视频控制器的position和duration初始都是Duration.zero,此时相等条件成立,导致题目提前显示。

解决方案

用独立状态变量控制题目显示,配合视频播放状态监听,同时加入精度容错:

  • 定义_showQuiz布尔变量,初始设为false,专门控制题目是否显示。
  • 给视频控制器添加监听,判断播放进度是否接近结束(留100毫秒容错空间),满足条件时将_showQuiz设为true。
  • 切换题目或重启时,重置_showQuiz并重新初始化视频控制器。

修改后的代码示例

import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';

class QuizVideoScreen extends StatefulWidget {
  const QuizVideoScreen({super.key});

  @override
  State<QuizVideoScreen> createState() => _QuizVideoScreenState();
}

class _QuizVideoScreenState extends State<QuizVideoScreen> {
  bool _showQuiz = false;
  late VideoPlayerController _videoPlayerController;

  @override
  void initState() {
    super.initState();
    _initVideoController();
  }

  // 初始化视频控制器
  void _initVideoController() {
    _showQuiz = false; // 重置题目显示状态
    _videoPlayerController = VideoPlayerController.network(
      'https://example.com/your-video.mp4', // 替换为你的视频地址
    )..initialize().then((_) {
        setState(() {});
        _videoPlayerController.play();
        // 添加播放状态监听
        _videoPlayerController.addListener(_checkVideoEnd);
      });
  }

  // 检查视频是否播放结束
  void _checkVideoEnd() {
    final position = _videoPlayerController.value.position;
    final duration = _videoPlayerController.value.duration;

    // 视频已初始化,且进度接近结束(留100毫秒容错)
    if (duration != Duration.zero && position >= duration - const Duration(milliseconds: 100)) {
      setState(() {
        _showQuiz = true;
      });
      // 移除监听避免重复触发
      _videoPlayerController.removeListener(_checkVideoEnd);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          // 视频播放区域
          if (_videoPlayerController.value.isInitialized)
            AspectRatio(
              aspectRatio: _videoPlayerController.value.aspectRatio,
              child: VideoPlayer(_videoPlayerController),
            ),
          // 测验题目区域(仅当_showQuiz为true时显示)
          if (_showQuiz)
            Expanded(
              child: Padding(
                padding: const EdgeInsets.all(16.0),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    const Text(
                      '这是测验题目?',
                      style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                    ),
                    const SizedBox(height: 20),
                    ElevatedButton(onPressed: () {}, child: const Text('选项A')),
                    ElevatedButton(onPressed: () {}, child: const Text('选项B')),
                    ElevatedButton(onPressed: () {}, child: const Text('选项C')),
                  ],
                ),
              ),
            ),
          // 切换题目按钮
          Padding(
            padding: const EdgeInsets.all(16.0),
            child: ElevatedButton(
              onPressed: () {
                // 释放旧控制器,重新初始化
                _videoPlayerController.dispose();
                _initVideoController();
              },
              child: const Text('切换到下一题'),
            ),
          ),
        ],
      ),
    );
  }

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

关键优化点

  • 用_showQuiz独立控制显示,彻底避免初始状态的误判。
  • 采用position >= duration - 100ms的判断逻辑,解决精度匹配问题。
  • 视频结束后移除监听,防止后续状态变化重复触发。
  • 切换题目时重置状态并重新初始化控制器,确保新视频播放前题目不显示。

内容的提问来源于stack exchange,提问作者Sultanshah Rajguru

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 10:45:45