Flutter项目如何通过API获取YouTube视频缩略图并在列表中展示
实现步骤
1. (可选)添加图片缓存依赖
如果需要实现缩略图本地缓存、加载状态自动处理,推荐使用cached_network_image库,在pubspec.yaml中添加依赖:
dependencies: flutter: sdk: flutter cached_network_image: ^3.2.3 # 可替换为库的最新稳定版本
执行flutter pub get完成安装。
2. 扩展Video类生成缩略图地址
你的视频地址为YouTube链接,可直接通过平台规则拼接缩略图地址,在Video类中新增两个getter:
class Video { // 原有代码保持不变 // 新增:提取YouTube视频ID String? get youtubeVideoId { final regExp = RegExp(r'(?<=v=)[^&]+'); final match = regExp.firstMatch(url); return match?.group(0); } // 新增:生成缩略图地址 String? get thumbnailUrl { final id = youtubeVideoId; if (id == null) return null; // hqdefault为高清缩略图,可替换为mqdefault(普清)、maxresdefault(最高清) return 'https://img.youtube.com/vi/$id/hqdefault.jpg'; } }
3. 修改列表视图加载缩略图
完善video_widget.dart中的build逻辑,增加加载状态判断、空数据处理,以及列表项的缩略图渲染:
@override Widget build(BuildContext context) { // 加载中显示进度指示器 if (_loading) { return const Center(child: CircularProgressIndicator()); } // 无数据提示 if (_videos.isEmpty) { return const Center(child: Text('暂无视频内容')); } return ListView.builder( itemCount: _videos.length, itemBuilder: (context, index) { Video video = _videos[index]; return Card( margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), child: Padding( padding: const EdgeInsets.all(8.0), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 缩略图区域 SizedBox( width: 120, height: 80, child: video.thumbnailUrl != null ? // 使用cached_network_image的示例 CachedNetworkImage( imageUrl: video.thumbnailUrl!, fit: BoxFit.cover, placeholder: (context, url) => const Center( child: CircularProgressIndicator(strokeWidth: 2), ), errorWidget: (context, url, error) => const Icon(Icons.broken_image, size: 40), ) // 不使用第三方库的原生Image.network写法 /* Image.network( video.thumbnailUrl!, fit: BoxFit.cover, loadingBuilder: (context, child, progress) { if (progress == null) return child; return const Center(child: CircularProgressIndicator(strokeWidth: 2)); }, errorBuilder: (context, error, trace) => const Icon(Icons.broken_image, size: 40), ) */ : const Icon(Icons.video_library, size: 40), ), const SizedBox(width: 12), // 视频信息区域 Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( video.topicName, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500), ), const SizedBox(height: 8), Text('视频ID:${video.videoId}', style: const TextStyle(color: Colors.grey, fontSize: 12)), ], ), ) ], ), ), ); }, ); }
内容的提问来源于stack exchange,提问作者Dhaval Chaudhari
相关产品推荐
相关产品推荐

