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

Flutter视频上传时圆形进度条实现求助(附FilePicker代码)

实现视频上传圆形进度条方案

1. 定义状态变量

在你的页面State类中添加两个核心变量,分别控制加载状态和上传进度:

bool isLoading = false;
double uploadProgress = 0.0;

2. 改造上传逻辑(以Dio为例,可适配其他网络库)

在VideoWIllSaveScreen中实现带进度回调的上传方法,实时更新进度状态:

Future<void> uploadVideo() async {
  setState(() {
    isLoading = true;
    uploadProgress = 0.0;
  });

  try {
    Dio dio = Dio();
    FormData formData = FormData.fromMap({
      'video': await MultipartFile.fromFile(
        videoFile.path,
        filename: 'uploaded_video.mp4',
      ),
      // 补充你需要的其他参数:subject、connection_id等
    });

    await dio.post(
      '你的服务器上传接口地址',
      data: formData,
      onSendProgress: (sentBytes, totalBytes) {
        if (totalBytes != -1) {
          setState(() {
            uploadProgress = sentBytes / totalBytes;
          });
        }
      },
    );

    // 上传成功后的逻辑:比如提示、页面跳转
    customSnackBar('视频上传成功', 'Success');
  } catch (e) {
    customSnackBar('上传失败: ${e.toString()}', 'Error');
  } finally {
    setState(() {
      isLoading = false;
    });
  }
}

3. 在UI中嵌入圆形进度条

在VideoWIllSaveScreen的build方法里,通过Stack布局叠加进度遮罩,根据状态显示/隐藏:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: const Text('上传视频')),
    body: Stack(
      children: [
        // 原有页面内容:视频预览、上传按钮等
        Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              if (videoFile != null)
                VideoPlayer(VideoPlayerController.file(videoFile!)),
              const SizedBox(height: 20),
              ElevatedButton(
                onPressed: isLoading ? null : uploadVideo,
                child: Text(isLoading ? '上传中...' : '开始上传'),
              ),
            ],
          ),
        ),
        // 上传时显示的进度遮罩
        if (isLoading)
          Container(
            color: Colors.black54,
            child: Center(
              child: CircularProgressIndicator(
                value: uploadProgress,
                strokeWidth: 4,
                valueColor: const AlwaysStoppedAnimation<Color>(Colors.blueAccent),
              ),
            ),
          ),
      ],
    ),
  );
}

4. 优化原_getGallery函数

原函数中setState包裹Navigator.push属于冗余操作,直接调整为:

_getGallery() async {
  FilePickerResult? result =
      await FilePicker.platform.pickFiles(type: FileType.video);
  print('result : $result');
  if (result != null) {
    if (!checkConnection()) {
      return;
    }
    if (subjectController.text == '') {
      warningSnackBar(context, 'Please enter the subject');
      return;
    }
    final videoFile = File(result.files.single.path.toString());
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (BuildContext builder) => VideoWIllSaveScreen(
            videoFile: videoFile,
            connection_id: connectionID,
            name: connectionName,
            deliver_type: deliver_type,
            subject: subjectController.text,
            videoUrl: ''),
      ),
    );
  } else {
    customSnackBar('Failed to load video', 'Error');
  }
}

这样就能实现:点击上传按钮后,页面弹出半透明遮罩和带实时进度的圆形加载条,上传过程中按钮禁用防止重复触发,完成后自动隐藏进度条并提示结果。

内容的提问来源于stack exchange,提问作者Pravin Suthar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 00:55:12