Flutter 仿抖音 TikTok 上下滑动 播放视频

Flutter 仿抖音 TikTok 上下滑动 播放视频UI框架,视频播放使用 video_player

github:GitHub - PangHaHa12138/TiktokVideo: Flutter 仿抖音 TikTok 上下滑动 播放视频UI框架

实现功能:

1.上下滑动自动播放切换视频,loading 封面图占位

2.全屏播放横竖屏切换

3.播放进度条显示

4.仿抖音评论弹窗

效果图:

001.jpg

002.jpg

003.jpg

004.jpg

005.jpg

上代码:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:video_player/video_player.dart';class VideoPage extends StatefulWidget {const VideoPage({Key? key}) : super(key: key);@overrideState createState() => _VideoPageState();
}class _VideoPageState extends State<VideoPage> {late PageController _pageController;int currentPageIndex = 0; //当前播放索引int currentIndex = 0; //当前播放索引List<VideoData> videoDataList = []; //视频数据列表List<VideoType> videoTypeList = []; //视频分类数据列表@overridevoid initState() {loadData(false);loadVideoType();_pageController = PageController(initialPage: currentIndex);_pageController.addListener(_onPageScroll);super.initState();}void _onPageScroll() {final pageIndex = _pageController.page?.round();if (pageIndex != null && pageIndex != currentPageIndex) {currentPageIndex = pageIndex;print('=========> currentPageIndex: ${currentPageIndex}');if (currentPageIndex == videoDataList.length - 2) {loadData(true);}}}/// 视频数据 API请求Future<void> loadData(bool isLoadMore) async {// 延迟200ms 模拟网络请求await Future.delayed(const Duration(milliseconds: 200));if (isLoadMore) {print('=========> loadData');List<VideoData> newVideoDataList = [];newVideoDataList.clear();newVideoDataList.addAll(videoDataList);newVideoDataList.addAll(testVideoData);setState(() {videoDataList = newVideoDataList;});} else {setState(() {videoDataList = testVideoData;});}}/// 视频类型 API请求Future<void> loadVideoType() async {// 延迟200ms 模拟网络请求await Future.delayed(const Duration(milliseconds: 200));videoTypeList = testVideoType;setState(() {});}@overridevoid dispose() {_pageController.removeListener(_onPageScroll);_pageController.dispose();super.dispose();}@overrideWidget build(BuildContext context) {var size = MediaQuery.of(context).size;return Scaffold(resizeToAvoidBottomInset: false, //很重要,不加键盘弹出视频会被挤压body: Stack(children: [PageView.builder(scrollDirection: Axis.vertical,itemCount: videoDataList.length,controller: _pageController,onPageChanged: (currentPage) {//页面发生改变的回调},itemBuilder: (context, index) {return VideoPlayerFullPage(size: size,videoData: videoDataList[index],videoTypes: videoTypeList,);},),header(context,videoTypeList,),],));}Widget header(BuildContext context, List<VideoType> videoTypes) {var size = MediaQuery.of(context).size;return Padding(padding: const EdgeInsets.only(left: 15, top: 10, bottom: 10),child: SafeArea(child: Column(children: [Row(children: [IconButton(icon: const Icon(Icons.arrow_back_ios_new,color: Colors.white,),onPressed: () {if (Navigator.canPop(context)) {Navigator.pop(context);}}),GestureDetector(onTap: () {onSearchClick();},child: Container(width: size.width - 100,padding: const EdgeInsets.only(left: 15, right: 15, top: 5, bottom: 5),decoration: BoxDecoration(borderRadius: BorderRadius.circular(20.0),color: const Color(0x80444444),),child: Row(children: const [Icon(Icons.search,color: Colors.white,),SizedBox(width: 5,),Text('搜索社群',style: TextStyle(color: Colors.white,fontSize: 15,),),],),),),],),const SizedBox(height: 10),Wrap(spacing: 8.0, // 主轴(水平)方向间距runSpacing: 2.0, // 纵轴(垂直)方向间距children: videoTypes.map((item) {return GestureDetector(onTap: () {onVideoTypesClick(item);},child: Container(padding: const EdgeInsets.only(left: 12, right: 12, top: 4, bottom: 4),decoration: BoxDecoration(borderRadius: BorderRadius.circular(20.0), // 设置圆角color: const Color(0xFF69DCE5), // 设置背景颜色),child: Text(item.typeName,style: const TextStyle(color: Colors.white,fontSize: 12,),textAlign: TextAlign.center,),),);}).toList(),),],),),);}/// 顶部视频类型 点击Future<void> onVideoTypesClick(VideoType videoType) async {print('=====> 点击了视频类型');}/// 搜索点击Future<void> onSearchClick() async {print('=====> 点击了搜索');}
}class VideoPlayerFullPage extends StatefulWidget {final List<VideoType> videoTypes; //视频顶部分类final VideoData? videoData;const VideoPlayerFullPage({Key? key,required this.size,required this.videoTypes,required this.videoData,}) : super(key: key);final Size size;@overrideState createState() => _VideoPlayerFullPageState();
}class _VideoPlayerFullPageState extends State<VideoPlayerFullPage> {late VideoPlayerController videoController;bool isInitPlaying = false;bool isBuffering = false;List<CommentData> comments = []; //评论数据列表double videoWidth = 0;double videoHeight = 0;double _currentSliderValue = 0.0;@overridevoid initState() {videoController = VideoPlayerController.network(widget.videoData!.videoUrl)..initialize().then((value) {videoController.play();videoController.setLooping(true);setState(() {_currentSliderValue = 0.0;isInitPlaying = true;videoWidth = videoController.value.size.width;videoHeight = videoController.value.size.height;});});videoController.addListener(videoListener);super.initState();}void videoListener() {setState(() {isBuffering = videoController.value.isBuffering;_currentSliderValue = videoController.value.position.inSeconds.toDouble();});}@overridevoid dispose() {videoController.removeListener(videoListener);videoController.dispose();super.dispose();}/// 底部视频话题 点击Future<void> onVideoTagsClick(VideoTag videoTag) async {print('=====> 点击了视频话题');}///点赞Future<void> onLikeClick(VideoData videoData) async {print('=====> 点击了点赞');}///评论Future<void> onCommentClick(BuildContext context, VideoData videoData) async {print('=====> 点击了评论');// 延迟200ms 模拟网络请求await Future.delayed(const Duration(milliseconds: 200));comments = testCommentData;showCommentBottomSheet(context, comments, videoData);}///观看人数Future<void> onWatchClick(VideoData videoData) async {print('=====> 点击了观看人数');}///分享Future<void> onShareClick(VideoData videoData) async {print('=====> 点击了分享');}///加好友Future<void> onAddFriendClick(VideoData videoData) async {print('=====> 点击了加好友');}///发布人名称点击Future<void> onUserNameClick(VideoData videoData) async {print('=====> 点击了发布人名称');}@overrideWidget build(BuildContext context) {return Container(color: Colors.grey,height: widget.size.height,width: widget.size.width,child: widget.videoData == null? Center(child: Container(width: 200,height: 200,decoration: BoxDecoration(borderRadius: BorderRadius.circular(20.0),color: const Color(0x80444444),),child: Column(children: const [SizedBox(height: 20,),Icon(Icons.error_outline,size: 50,),SizedBox(height: 70,),Text('无数据',style: TextStyle(fontSize: 20, color: Colors.white),),],),),): GestureDetector(onTap: () {print('============>视频点击 ');setState(() {videoController.value.isPlaying? videoController.pause(): videoController.play();});},child: Container(height: widget.size.height,width: widget.size.width,decoration: const BoxDecoration(color: Colors.black),child: Stack(children: <Widget>[videoWidth > videoHeight? Center(child: AspectRatio(aspectRatio: videoController.value.aspectRatio,child: VideoPlayer(videoController),),): AspectRatio(aspectRatio: videoController.value.aspectRatio,child: VideoPlayer(videoController),),Center(child: !videoController.value.isPlaying && !isInitPlaying? Image.network(widget.videoData!.albumImg,width: widget.size.width,height: widget.size.height,fit: BoxFit.cover,): const SizedBox(),),Center(child: Container(decoration: const BoxDecoration(),child: isPlaying(),),),isBuffering || !videoController.value.isInitialized? const Center(child: SizedBox(width: 40,height: 40,child: CircularProgressIndicator(color: Color(0xFF69DCE5),),),): const SizedBox(),Padding(padding:const EdgeInsets.only(left: 0, top: 10, bottom: 10),child: SafeArea(child: Column(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: <Widget>[Expanded(child: Row(children: <Widget>[bottomPanel(widget.size,widget.videoData!,),rightPanel(context,widget.size,widget.videoData!,)],),),SizedBox(height: 10,child: SliderTheme(data: SliderTheme.of(context).copyWith(trackHeight: 3, // 轨道高度trackShape:const RoundedRectSliderTrackShape(), // 轨道形状,可以自定义activeTrackColor:const Color(0xFF444444), // 激活的轨道颜色inactiveTrackColor:const Color(0x80444444), // 未激活的轨道颜色thumbColor: const Color(0xFF999999), // 滑块颜色thumbShape: const RoundSliderThumbShape(//  滑块形状,可以自定义enabledThumbRadius: 4 // 滑块大小),overlayShape: const RoundSliderOverlayShape(overlayRadius: 10, // 设置滑块的覆盖层半径),),child: Slider(value: _currentSliderValue,min: 0.0,max: videoController.value.duration.inSeconds.toDouble(),onChanged: (value) {setState(() {_currentSliderValue = value;videoController.seekTo(Duration(seconds: value.toInt()));});},),),),],),),),videoWidth > videoHeight? GestureDetector(onTap: () {Navigator.push(context,MaterialPageRoute(builder: (context) => FullScreenVideoPage(videoController: videoController)),);},child: Padding(padding:const EdgeInsets.only(top: 500, left: 150),child: SizedBox(width: 110,height: 40,child: Container(decoration: BoxDecoration(borderRadius:BorderRadius.circular(20.0),color: const Color(0x80444444),),child: Row(mainAxisAlignment:MainAxisAlignment.spaceBetween,children: const [SizedBox(width: 3,),Icon(Icons.fullscreen,color: Colors.white,),Text('全屏观看',style: TextStyle(fontSize: 14,color: Colors.white,),),SizedBox(width: 3,),],)),))): const SizedBox(),],),),),);}Widget isPlaying() {if (videoController.value.isInitialized) {return videoController.value.isPlaying? const SizedBox(): Image.asset('assets/images/icon_play.png',width: 80,height: 80,);} else {return const SizedBox();}}String _formatDuration(Duration duration) {return '${duration.inMinutes.remainder(60).toString().padLeft(2, '0')}:${(duration.inSeconds % 60).toString().padLeft(2, '0')}';}Widget bottomPanel(Size size, VideoData videoData) {return Container(width: size.width * 0.8,height: size.height,padding: const EdgeInsets.only(left: 15),decoration: const BoxDecoration(),child: Column(mainAxisAlignment: MainAxisAlignment.end,crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[GestureDetector(onTap: () {onUserNameClick(videoData);},child: Text('@${videoData.userName}',style: const TextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 18),),),const SizedBox(height: 10,),Container(margin: const EdgeInsets.only(right: 30),child: Row(children: [videoData.type == "1"? Container(padding: const EdgeInsets.only(left: 4, right: 4, top: 2, bottom: 2),decoration: BoxDecoration(borderRadius: BorderRadius.circular(3.0), // 设置圆角color: const Color(0xFF8B452B), // 设置背景颜色),child: const Text('精',style: TextStyle(color: Color(0xFFF47947),fontSize: 13,fontWeight: FontWeight.bold,),textAlign: TextAlign.center,),): const SizedBox(),const SizedBox(width: 10,),Text(videoData.title,style: const TextStyle(color: Colors.white,fontSize: 16,fontWeight: FontWeight.bold,),),Text('  ·  ${videoData.time}',style: const TextStyle(color: Colors.grey,fontSize: 13,),),],),),const SizedBox(height: 5,),Container(margin: const EdgeInsets.only(right: 30),child: Text(videoData.description,style: const TextStyle(color: Colors.white,fontSize: 14,),),),const SizedBox(height: 10,),Wrap(spacing: 8.0, // 主轴(水平)方向间距runSpacing: 2.0, // 纵轴(垂直)方向间距children: videoData.videoTags.map((item) {return GestureDetector(onTap: () {onVideoTagsClick(item);},child: Container(padding: const EdgeInsets.only(left: 6, right: 6, top: 3, bottom: 3),decoration: BoxDecoration(borderRadius: BorderRadius.circular(20.0), // 设置圆角color: const Color(0xFF69DCE5), // 设置背景颜色),child: Text('#${item.tagName}',style: const TextStyle(color: Colors.white,fontSize: 12,),textAlign: TextAlign.center,),),);}).toList(),),const SizedBox(height: 10,),],),);}Widget rightPanel(BuildContext context, Size size, VideoData videoData) {return Expanded(child: SizedBox(height: size.height,child: Column(children: <Widget>[Container(height: size.height * 0.4,),Expanded(child: Column(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: <Widget>[getProfile(videoData),getLike(videoData, 25.0),getComment(context, videoData, 25.0),getWatch(videoData, 25.0),getShare(videoData, 25.0),const SizedBox(height: 60,),],))],),),);}Widget getLike(VideoData videoData, double size) {return GestureDetector(onTap: () {onLikeClick(videoData);},child: Column(children: <Widget>[videoData.likeStatus == "1"?//已点赞Image.asset('assets/images/icon_like.png',width: size,height: size,)//未点赞: Image.asset('assets/images/icon_like.png',width: size,height: size,),const SizedBox(height: 5,),Text(videoData.likes,style: const TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w700),)],),);}Widget getComment(BuildContext context, VideoData videoData, double size) {return GestureDetector(onTap: () {onCommentClick(context, videoData);},child: Column(children: <Widget>[Image.asset('assets/images/icon_comment.png',width: size,height: size,),const SizedBox(height: 5,),Text(videoData.comments,style: const TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w700),)],),);}Widget getWatch(VideoData videoData, double size) {return GestureDetector(onTap: () {onWatchClick(videoData);},child: Column(children: <Widget>[Image.asset('assets/images/icon_watch.png',width: size,height: size,),const SizedBox(height: 5,),Text(videoData.watchers,style: const TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w700),)],),);}Widget getShare(VideoData videoData, double size) {return GestureDetector(onTap: () {onShareClick(videoData);},child: Column(children: <Widget>[Image.asset('assets/images/icon_share.png',width: size,height: size,),const SizedBox(height: 5,),Text(videoData.shares,style: const TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w700),)],),);}Widget getProfile(VideoData videoData) {return GestureDetector(onTap: () {onAddFriendClick(videoData);},child: SizedBox(width: 50,height: 60,child: Stack(children: <Widget>[Container(width: 50,height: 50,decoration: BoxDecoration(border: Border.all(color: Colors.white),shape: BoxShape.circle,image: DecorationImage(image: NetworkImage(videoData.userAvatarUrl),fit: BoxFit.cover)),),Positioned(bottom: 3,left: 18,child: Container(width: 20,height: 20,decoration: const BoxDecoration(shape: BoxShape.circle, color: Color(0xFF69DCE5)),child: const Center(child: Icon(Icons.add,color: Colors.white,size: 15,)),))],),),);}void showCommentBottomSheet(BuildContext context, List<CommentData> comments,VideoData videoData) async {await showModalBottomSheet(context: context,shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(20)),),enableDrag: true,isScrollControlled: true,builder: (_) => CommentBottomSheet(commentData: comments,videoData: videoData,),);}
}class CommentBottomSheet extends StatefulWidget {final List<CommentData> commentData;final VideoData videoData;const CommentBottomSheet({Key? key,required this.commentData,required this.videoData,}) : super(key: key);@overrideState<CommentBottomSheet> createState() => _CommentsBottomSheetState();
}class _CommentsBottomSheetState extends State<CommentBottomSheet> {List<CommentData> comments = [];VideoData? videoData;TextEditingController textEditingController = TextEditingController();FocusNode focusNode = FocusNode();String hint = "写评论";@overridevoid initState() {comments = widget.commentData;videoData = widget.videoData;super.initState();}/// 发送评论onSendComment(String input) {print('========> 发送评论:$input');}/// 点赞评论onLikeComment(CommentData commentData) {print('========> 点赞评论');}/// 回复评论onReplayComment(CommentData commentData) {print('========> 回复评论');}/// 回复评论中的回复onReplayCommentReplay(CommentData commentData, CommentData replayComment) {print('========> 回复评论中的回复');}/// 查看全部评论onWatchAllComment(CommentData commentData) {print('========> 查看全部评论');for (int i = 0; i < comments.length; i++) {}}/// 底部输入框 点赞onBottomLike() {print('========> 底部输入框 点赞');}/// 底部输入框 分享onBottomShare() {print('========> 底部输入框 分享');}/// 底部输入框 收藏onBottomFavorite() {print('========> 底部输入框 收藏');}/// 底部输入框 评论onBottomComment() {print('========> 底部输入框 评论');}@overrideWidget build(BuildContext context) {return SizedBox(height: 500,child: Stack(children: [// 评论列表Padding(padding: const EdgeInsets.only(top: 60, bottom: 70),child: ListView.builder(shrinkWrap: true,itemCount: comments.length,itemBuilder: (BuildContext context, int index) {return CommentItem(comments[index], comments, index);},),),Align(alignment: Alignment.topCenter,child: // 评论数Container(padding: const EdgeInsets.only(top: 16, left: 16, right: 16, bottom: 0),decoration: BoxDecoration(borderRadius: BorderRadius.circular(15),color: Colors.white,),child: Column(mainAxisSize: MainAxisSize.min,children: [Row(mainAxisAlignment: MainAxisAlignment.start,children: <Widget>[Text('${comments.length}条评论',style:const TextStyle(fontSize: 15, color: Colors.grey),),],),const SizedBox(height: 15,),Container(margin: const EdgeInsets.only(left: 16, right: 16),child: const Divider(height: 1,color: Colors.grey,),)],),),),Align(alignment: Alignment.bottomCenter,child: // 输入框和操作栏Container(color: Colors.white,padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),child: Row(children: [Flexible(child: TextField(controller: textEditingController,focusNode: focusNode,onSubmitted: submitComment,onEditingComplete: () {submitComment(textEditingController.text);},keyboardType: TextInputType.multiline,maxLines: null,textInputAction: TextInputAction.send,decoration: InputDecoration(hintText: hint,filled: true,isDense: true,border: OutlineInputBorder(borderRadius: BorderRadius.circular(20),borderSide: BorderSide.none,),),),),const SizedBox(width: 4),SizedBox(width: 40,child: GestureDetector(onTap: () {onBottomFavorite();},child: Column(mainAxisSize: MainAxisSize.min,children: [const Icon(Icons.star_border,color: Color(0xFF9F9F9F),),Text('${videoData?.favorites}',style: const TextStyle(color: Color(0xFF9F9F9F),fontSize: 12,),),],)),),SizedBox(width: 40,child: GestureDetector(onTap: () {onBottomShare();},child: Column(mainAxisSize: MainAxisSize.min,children: [const Icon(Icons.ios_share_outlined,color: Color(0xFF9F9F9F),),Text('${videoData?.shares}',style: const TextStyle(color: Color(0xFF9F9F9F),fontSize: 12,),),],)),),SizedBox(width: 40,child: GestureDetector(onTap: () {onBottomComment();},child: Column(mainAxisSize: MainAxisSize.min,children: [const Icon(Icons.comment_outlined,color: Color(0xFF9F9F9F),),Text('${videoData?.comments}',style: const TextStyle(color: Color(0xFF9F9F9F),fontSize: 12,),),],)),),SizedBox(width: 40,child: GestureDetector(onTap: () {onBottomLike();},child: Column(mainAxisSize: MainAxisSize.min,children: [const Icon(Icons.thumb_up_alt_outlined,color: Color(0xFF9F9F9F),),Text('${videoData?.likes}',style: const TextStyle(color: Color(0xFF9F9F9F),fontSize: 12,),),],)),),],),),),],),);}void submitComment(String inputText) {if (textEditingController.text.isEmpty) return;onSendComment(textEditingController.text);textEditingController.clear();hint = '写评论';focusNode.unfocus();}Widget CommentItem(CommentData commentData, List<CommentData> comments, int index) {var size = MediaQuery.of(context).size;return Container(color: Colors.white,padding: const EdgeInsets.all(16),child: Column(crossAxisAlignment: CrossAxisAlignment.center,children: <Widget>[Row(mainAxisAlignment: MainAxisAlignment.start,crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[Container(width: 45,height: 45,decoration: BoxDecoration(border: Border.all(color: Colors.white),shape: BoxShape.circle,image: DecorationImage(image: NetworkImage(commentData.userAvatarUrl),fit: BoxFit.cover)),),const SizedBox(width: 10),Column(crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[Row(mainAxisAlignment: MainAxisAlignment.spaceAround,children: [Column(crossAxisAlignment: CrossAxisAlignment.start,children: [Text(commentData.userName,style: const TextStyle(fontSize: 18, color: Colors.black),),const SizedBox(height: 2),Text(commentData.time,style: const TextStyle(fontSize: 12, color: Colors.grey),),],),const SizedBox(width: 120),// 点赞数量GestureDetector(onTap: () {onLikeComment(commentData);},child: Row(mainAxisAlignment: MainAxisAlignment.end,children: [commentData.likeStatus == "1"? const Icon(Icons.thumb_up,color: Color(0xFF67DCE7),): const Icon(Icons.thumb_up_off_alt_outlined,color: Colors.grey,),const SizedBox(width: 4),Text(commentData.likes,style: TextStyle(fontSize: 17,color: commentData.likeStatus == "1"? const Color(0xFF67DCE7): Colors.grey,),),],),),],),const SizedBox(height: 10),Row(crossAxisAlignment: CrossAxisAlignment.start,children: [commentData.type == "1"? Container(padding: const EdgeInsets.only(left: 4, right: 4, top: 2, bottom: 2),decoration: BoxDecoration(borderRadius:BorderRadius.circular(3.0), // 设置圆角color: const Color(0xFFFFF0EC), // 设置背景颜色),child: const Text('精',style: TextStyle(color: Color(0xFFED7F55),fontSize: 13,fontWeight: FontWeight.bold,),textAlign: TextAlign.center,),): const SizedBox(),const SizedBox(width: 5,),GestureDetector(onTap: () {setState(() {hint = "回复 ${commentData.userName} : ";});FocusScope.of(context).requestFocus(focusNode);onReplayComment(commentData);},child: SizedBox(width: size.width - 148,child: Text(commentData.content,style: const TextStyle(fontSize: 17,color: Colors.black,),),),),const SizedBox(width: 30),],),const SizedBox(height: 8),// 回复内容Container(padding: const EdgeInsets.all(8),decoration: BoxDecoration(borderRadius: BorderRadius.circular(5.0), // 设置圆角color: const Color(0xFFF3F3F3),),child: Column(mainAxisAlignment: MainAxisAlignment.start,crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[...List.generate(commentData.replayList.length,(index) => ReplyItem(commentData,commentData.replayList[index], size.width),),const SizedBox(height: 5,),// 查看全部回复GestureDetector(onTap: () {// 处理查看全部回复逻辑onWatchAllComment(commentData);},child: Row(children: [Text('全部${commentData.replayList.length}条回复',style: const TextStyle(color: Colors.black, fontSize: 15),),const Icon(Icons.arrow_forward_ios_rounded,size: 15, color: Colors.black),],)),],),),],),],),index == comments.length - 1? Container(margin: const EdgeInsets.only(top: 10),child: const Text('- 没有更多了哦 -',style: TextStyle(fontSize: 14,color: Colors.grey,fontWeight: FontWeight.bold),),): const SizedBox(),],),);}Widget ReplyItem(CommentData commentData, CommentData replayComment, double width) {return GestureDetector(onTap: () {setState(() {hint = "回复 ${replayComment.userName} : ";});FocusScope.of(context).requestFocus(focusNode);onReplayCommentReplay(commentData, replayComment);},child: SizedBox(width: width - 120,child: RichText(text: TextSpan(children: [TextSpan(text: replayComment.userName,style: const TextStyle(color: Color(0xFF67DCE7),fontSize: 14,),),const TextSpan(text: ' 回复 ',style: TextStyle(fontSize: 14,color: Color(0xFF707070),),),TextSpan(text: replayComment.replayName,style: const TextStyle(color: Color(0xFF67DCE7),fontSize: 14,),),TextSpan(text: ' : ${replayComment.replayContent}',style: const TextStyle(color: Color(0xFF707070),fontSize: 14,),),],),),),);}
}class FullScreenVideoPage extends StatefulWidget {final VideoPlayerController videoController;const FullScreenVideoPage({Key? key, required this.videoController}): super(key: key);@override_FullScreenVideoPageState createState() => _FullScreenVideoPageState();
}class _FullScreenVideoPageState extends State<FullScreenVideoPage> {double _currentSliderValue = 0.0;bool isBuffering = false;bool isInitPlaying = false;@overridevoid initState() {super.initState();SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft,]);setState(() {_currentSliderValue = 0.0;isInitPlaying = true;});widget.videoController.addListener(videoListener);}void videoListener() {setState(() {isBuffering = widget.videoController.value.isBuffering;_currentSliderValue =widget.videoController.value.position.inSeconds.toDouble();});}@overridevoid dispose() {widget.videoController.removeListener(videoListener);super.dispose();}Widget isPlaying() {if (widget.videoController.value.isInitialized) {return widget.videoController.value.isPlaying? const SizedBox(): Image.asset('assets/images/icon_play.png',width: 80,height: 80,);} else {return const SizedBox();}}@overrideWidget build(BuildContext context) {return WillPopScope(child: Scaffold(backgroundColor: Colors.black,body: GestureDetector(onTap: () {setState(() {widget.videoController.value.isPlaying? widget.videoController.pause(): widget.videoController.play();});},child: Stack(children: [VideoPlayer(widget.videoController),Padding(padding: const EdgeInsets.only(top: 25, right: 20),child: IconButton(icon: const Icon(Icons.close,size: 30,),color: Colors.white,onPressed: () {SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp,]);Navigator.pop(context);},),),Center(child: Container(decoration: const BoxDecoration(),child: isPlaying(),),),isBuffering || !widget.videoController.value.isInitialized? const Center(child: SizedBox(width: 50,height: 50,child: CircularProgressIndicator(color: Color(0xFF69DCE5),),),): const SizedBox(),Align(alignment: Alignment.bottomCenter,child: Container(margin: const EdgeInsets.only(bottom: 10),height: 10,child: SliderTheme(data: SliderTheme.of(context).copyWith(trackHeight: 3, // 轨道高度trackShape:const RoundedRectSliderTrackShape(), // 轨道形状,可以自定义activeTrackColor: const Color(0xFF444444), // 激活的轨道颜色inactiveTrackColor: const Color(0x80444444),thumbColor: const Color(0xFF999999), // 未激活的轨道颜色thumbShape: const RoundSliderThumbShape(//  滑块形状,可以自定义enabledThumbRadius: 4 // 滑块大小),overlayShape: const RoundSliderOverlayShape(overlayRadius: 10, // 设置滑块的覆盖层半径),),child: Slider(value: _currentSliderValue,min: 0.0,max: widget.videoController.value.duration.inSeconds.toDouble(),onChanged: (value) {setState(() {_currentSliderValue = value;widget.videoController.seekTo(Duration(seconds: value.toInt()));});},),),),),],),),),onWillPop: () async {SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp,]);Navigator.pop(context);return false;});}
}class VideoData {final String id; // 唯一idfinal String uid; // 发布人 uidfinal String type; //type = 1 视频加 精final String videoUrl; //视频地址final String albumImg; //视频第一帧封面final String userName; //发布者名final String userAvatarUrl; //发布者头像final String description; //视频描述final String title; //视频标题final String likes; //视频点赞数final String likeStatus; //0未点赞 1 已点赞final String comments; //视频评论数final String shares; //视频分享数final String watchers; //视频观看数final String favorites; //视频收藏数final String time; //视频发布时间final List<VideoTag> videoTags; //视频关联话题VideoData({required this.id,required this.uid,required this.type,required this.videoUrl,required this.albumImg,required this.userName,required this.userAvatarUrl,required this.description,required this.title,required this.likes,required this.likeStatus,required this.comments,required this.shares,required this.watchers,required this.favorites,required this.time,required this.videoTags,});
}class VideoTag {final String tagId; //视频关联话题idfinal String tagName; //视频关联话题名VideoTag({required this.tagId,required this.tagName,});
}class VideoType {final String typeId; //视频分类idfinal String typeName; //视频分类名VideoType({required this.typeId,required this.typeName,});
}class CommentData {final String id; // 唯一idfinal String uid; // 评论用户uidfinal String userName; // 评论用户uidfinal String userAvatarUrl; // 评论用户uidfinal String time; // 发布评论时间final String type; //type = 1 评论加 精final String content; //评论文案final String likes; //评论点赞数final String likeStatus; //0未点赞 1 已点赞final String replayName; //被回复者final String replayUid; //被回复者 uidfinal String replayContent; //回复内容final List<CommentData> replayList;CommentData({required this.id,required this.uid,required this.userName,required this.userAvatarUrl,required this.time,required this.type,required this.content,required this.likes,required this.likeStatus,required this.replayName,required this.replayUid,required this.replayContent,required this.replayList,});
}/// 测试数据List<CommentData> testCommentData = <CommentData>[CommentData(id: "2524525",uid: "5254453",userName: "晴子",userAvatarUrl:"https://p16-tiktokcdn-com.akamaized.net/aweme/720x720/tiktok-obj/1663771856684033.jpeg",time: "2023/01/17 14:30:22",type: "1",content: "有情趣又热爱生活的人真好有情趣又热爱生活",likes: "100",likeStatus: "1",replayName: "虾仁",replayUid: "11111",replayContent: "奔驰发布全新旅行车更适合大家出行要不要试驾",replayList: [CommentData(id: "2545",uid: "11541",userName: "用户1",userAvatarUrl:"https://p16-tiktokcdn-com.akamaized.net/aweme/720x720/tiktok-obj/1663771856684033.jpeg",time: "2023/01/17 14:30:22",type: "1",content: "有情趣又热爱生活的人真好有情趣又热爱生活",likes: "100",likeStatus: "0",replayName: "虾仁",replayUid: "11111",replayContent: "奔驰发布全新旅行车更适合大家出行要不要试驾",replayList: [],),CommentData(id: "5383",uid: "57225",userName: "用户2",userAvatarUrl:"https://p16-tiktokcdn-com.akamaized.net/aweme/720x720/tiktok-obj/1663771856684033.jpeg",time: "2023/01/17 14:30:22",type: "1",content: "有情趣又热爱生活的人真好有情趣又热爱生活",likes: "100",likeStatus: "0",replayName: "虾仁",replayUid: "11111",replayContent: "奔驰发布全新旅行车更适合大家出行要不要试驾",replayList: [],),CommentData(id: "42458",uid: "245454",userName: "用户3",userAvatarUrl:"https://p16-tiktokcdn-com.akamaized.net/aweme/720x720/tiktok-obj/1663771856684033.jpeg",time: "2023/01/17 14:30:22",type: "1",content: "有情趣又热爱生活的人真好有情趣又热爱生活",likes: "100",likeStatus: "0",replayName: "虾仁",replayUid: "11111",replayContent: "奔驰发布全新旅行车更适合大家出行要不要试驾",replayList: [],),],),CommentData(id: "56535",uid: "52482",userName: "虾仁",userAvatarUrl:"https://p16-tiktokcdn-com.akamaized.net/aweme/720x720/tiktok-obj/1663771856684033.jpeg",time: "2023/01/17 14:30:22",type: "1",content: "有情趣又热爱生活的人真好有情趣又热爱生活",likes: "100",likeStatus: "0",replayName: "虾仁",replayUid: "11111",replayContent: "奔驰发布全新旅行车更适合大家出行要不要试驾",replayList: [CommentData(id: "5353",uid: "24535",userName: "用户4",userAvatarUrl:"https://p16-tiktokcdn-com.akamaized.net/aweme/720x720/tiktok-obj/1663771856684033.jpeg",time: "2023/01/17 14:30:22",type: "1",content: "有情趣又热爱生活的人真好有情趣又热爱生活",likes: "100",likeStatus: "0",replayName: "虾仁",replayUid: "11111",replayContent: "奔驰发布全新旅行车更适合大家出行要不要试驾",replayList: [],),CommentData(id: "5355",uid: "35434",userName: "用户5",userAvatarUrl:"https://p16-tiktokcdn-com.akamaized.net/aweme/720x720/tiktok-obj/1663771856684033.jpeg",time: "2023/01/17 14:30:22",type: "1",content: "有情趣又热爱生活的人真好有情趣又热爱生活",likes: "100",likeStatus: "0",replayName: "虾仁",replayUid: "11111",replayContent: "奔驰发布全新旅行车更适合大家出行要不要试驾",replayList: [],),CommentData(id: "5452",uid: "35572",userName: "用户6",userAvatarUrl:"https://p16-tiktokcdn-com.akamaized.net/aweme/720x720/tiktok-obj/1663771856684033.jpeg",time: "2023/01/17 14:30:22",type: "1",content: "有情趣又热爱生活的人真好有情趣又热爱生活",likes: "100",likeStatus: "0",replayName: "虾仁",replayUid: "11111",replayContent: "奔驰发布全新旅行车更适合大家出行要不要试驾",replayList: [],),],),CommentData(id: "87886",uid: "6765",userName: "晴子",userAvatarUrl:"https://p16-tiktokcdn-com.akamaized.net/aweme/720x720/tiktok-obj/1663771856684033.jpeg",time: "2023/01/17 14:30:22",type: "1",content: "有情趣又热爱生活的人真好有情趣又热爱生活",likes: "100",likeStatus: "0",replayName: "虾仁",replayUid: "11111",replayContent: "奔驰发布全新旅行车更适合大家出行要不要试驾",replayList: [CommentData(id: "8768",uid: "68737",userName: "用户7",userAvatarUrl:"https://p16-tiktokcdn-com.akamaized.net/aweme/720x720/tiktok-obj/1663771856684033.jpeg",time: "2023/01/17 14:30:22",type: "1",content: "有情趣又热爱生活的人真好有情趣又热爱生活",likes: "100",likeStatus: "0",replayName: "虾仁",replayUid: "11111",replayContent: "奔驰发布全新旅行车更适合大家出行要不要试驾",replayList: [],),CommentData(id: "68727",uid: "68778",userName: "用户8",userAvatarUrl:"https://p16-tiktokcdn-com.akamaized.net/aweme/720x720/tiktok-obj/1663771856684033.jpeg",time: "2023/01/17 14:30:22",type: "1",content: "有情趣又热爱生活的人真好有情趣又热爱生活",likes: "100",likeStatus: "0",replayName: "虾仁",replayUid: "11111",replayContent: "奔驰发布全新旅行车更适合大家出行要不要试驾",replayList: [],),CommentData(id: "12821",uid: "8755",userName: "用户9",userAvatarUrl:"https://p16-tiktokcdn-com.akamaized.net/aweme/720x720/tiktok-obj/1663771856684033.jpeg",time: "2023/01/17 14:30:22",type: "1",content: "有情趣又热爱生活的人真好有情趣又热爱生活",likes: "100",likeStatus: "0",replayName: "虾仁",replayUid: "11111",replayContent: "奔驰发布全新旅行车更适合大家出行要不要试驾",replayList: [],),],),
];List<VideoType> testVideoType = <VideoType>[VideoType(typeId: "1111", typeName: "热门"),VideoType(typeId: "1111", typeName: "分类一"),VideoType(typeId: "1111", typeName: "分类二"),VideoType(typeId: "1111", typeName: "分类三"),VideoType(typeId: "1111", typeName: "分类四"),
];List<VideoData> testVideoData = <VideoData>[VideoData(id: "111",uid: "1233",type: "1",videoUrl: "https://static.ybhospital.net/test-video-2.mp4",albumImg:"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fblog%2F202107%2F05%2F20210705100427_ee4b8.thumb.1000_0.jpg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1628415177&t=87962cc902fb5925da0a4d60d4c48ca9",userName: "发布人名称",userAvatarUrl:"https://p16-tiktokcdn-com.akamaized.net/aweme/720x720/tiktok-obj/1663771856684033.jpeg",description: "春日的暖阳,花开进度80%,准备和爱车路过全世界,感受独具魅力的岭南文化!",title: "视频标题",likes: "130",likeStatus: "1",comments: "186",shares: "135",watchers: "328",favorites: "636",time: "2023年12月16日",videoTags: [VideoTag(tagId: "1111", tagName: "今天去哪玩"),VideoTag(tagId: "1111", tagName: "南京车友圈"),VideoTag(tagId: "1111", tagName: "活动名称"),]),VideoData(id: "111",uid: "1233",type: "1",videoUrl: "https://static.ybhospital.net/test-video-3.mp4",albumImg:"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fblog%2F202107%2F05%2F20210705100427_ee4b8.thumb.1000_0.jpg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1628415177&t=87962cc902fb5925da0a4d60d4c48ca9",userName: "发布人名称",userAvatarUrl:"https://p16-tiktokcdn-com.akamaized.net/aweme/720x720/tiktok-obj/1663771856684033.jpeg",description: "春日的暖阳,花开进度80%,准备和爱车路过全世界,感受独具魅力的岭南文化!",title: "视频标题",likes: "130",likeStatus: "1",comments: "165",shares: "135",watchers: "320",favorites: "105",time: "2023年12月16日",videoTags: [VideoTag(tagId: "1111", tagName: "今天去哪玩"),VideoTag(tagId: "1111", tagName: "南京车友圈"),VideoTag(tagId: "1111", tagName: "活动名称"),]),VideoData(id: "111",uid: "1233",type: "1",videoUrl: "https://static.ybhospital.net/test-video-4.mp4",albumImg:"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fblog%2F202107%2F05%2F20210705100427_ee4b8.thumb.1000_0.jpg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1628415177&t=87962cc902fb5925da0a4d60d4c48ca9",userName: "发布人名称",userAvatarUrl:"https://p16-tiktokcdn-com.akamaized.net/aweme/720x720/tiktok-obj/1663771856684033.jpeg",description: "春日的暖阳,花开进度80%,准备和爱车路过全世界,感受独具魅力的岭南文化!",title: "视频标题",likes: "150",likeStatus: "1",comments: "185",shares: "136",watchers: "280",favorites: "500",time: "2023年12月16日",videoTags: [VideoTag(tagId: "1111", tagName: "今天去哪玩"),VideoTag(tagId: "1111", tagName: "南京车友圈"),VideoTag(tagId: "1111", tagName: "活动名称"),]),VideoData(id: "111",uid: "1233",type: "1",videoUrl: "https://static.ybhospital.net/test-video-5.mp4",albumImg:"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fblog%2F202107%2F05%2F20210705100427_ee4b8.thumb.1000_0.jpg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1628415177&t=87962cc902fb5925da0a4d60d4c48ca9",userName: "发布人名称",userAvatarUrl:"https://p16-tiktokcdn-com.akamaized.net/aweme/720x720/tiktok-obj/1663771856684033.jpeg",description: "春日的暖阳,花开进度80%,准备和爱车路过全世界,感受独具魅力的岭南文化!",title: "视频标题",likes: "365",likeStatus: "1",comments: "425",shares: "253",watchers: "854",favorites: "524",time: "2023年12月16日",videoTags: [VideoTag(tagId: "1111", tagName: "今天去哪玩"),VideoTag(tagId: "1111", tagName: "南京车友圈"),VideoTag(tagId: "1111", tagName: "活动名称"),]),VideoData(id: "111",uid: "1233",type: "1",videoUrl: "https://static.ybhospital.net/test-video-6.mp4",albumImg:"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fblog%2F202107%2F05%2F20210705100427_ee4b8.thumb.1000_0.jpg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1628415177&t=87962cc902fb5925da0a4d60d4c48ca9",userName: "发布人名称",userAvatarUrl:"https://p16-tiktokcdn-com.akamaized.net/aweme/720x720/tiktok-obj/1663771856684033.jpeg",description: "春日的暖阳,花开进度80%,准备和爱车路过全世界,感受独具魅力的岭南文化!",title: "视频标题",likes: "352",likeStatus: "1",comments: "585",shares: "425",watchers: "825",favorites: "245",time: "2023年12月16日",videoTags: [VideoTag(tagId: "1111", tagName: "今天去哪玩"),VideoTag(tagId: "1111", tagName: "南京车友圈"),VideoTag(tagId: "1111", tagName: "活动名称"),]),VideoData(id: "2525",uid: "35435",type: "1",videoUrl: "https://media.w3.org/2010/05/sintel/trailer.mp4",albumImg:"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fblog%2F202107%2F05%2F20210705100427_ee4b8.thumb.1000_0.jpg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1628415177&t=87962cc902fb5925da0a4d60d4c48ca9",userName: "发布人名称",userAvatarUrl:"https://p16-tiktokcdn-com.akamaized.net/aweme/720x720/tiktok-obj/1663771856684033.jpeg",description: "春日的暖阳,花开进度80%,准备和爱车路过全世界,感受独具魅力的岭南文化!",title: "视频标题",likes: "252",likeStatus: "1",comments: "424",shares: "245",watchers: "453",favorites: "523",time: "2023年12月16日",videoTags: [VideoTag(tagId: "1111", tagName: "今天去哪玩"),VideoTag(tagId: "1111", tagName: "南京车友圈"),VideoTag(tagId: "1111", tagName: "活动名称"),]),VideoData(id: "2525",uid: "35435",type: "1",videoUrl: "https://jomin-web.web.app/resource/video/video_iu.mp4",albumImg:"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fblog%2F202107%2F05%2F20210705100427_ee4b8.thumb.1000_0.jpg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1628415177&t=87962cc902fb5925da0a4d60d4c48ca9",userName: "发布人名称",userAvatarUrl:"https://p16-tiktokcdn-com.akamaized.net/aweme/720x720/tiktok-obj/1663771856684033.jpeg",description: "春日的暖阳,花开进度80%,准备和爱车路过全世界,感受独具魅力的岭南文化!",title: "视频标题",likes: "252",likeStatus: "1",comments: "424",shares: "245",watchers: "453",favorites: "523",time: "2023年12月16日",videoTags: [VideoTag(tagId: "1111", tagName: "今天去哪玩"),VideoTag(tagId: "1111", tagName: "南京车友圈"),VideoTag(tagId: "1111", tagName: "活动名称"),]),
];

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/664866.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

bash脚本学习笔记

一、扫盲 脚本文件是一种文本文件&#xff0c;其中包含了一系列的命令和指令&#xff0c;可以被操作系统解释器直接解释执行。脚本文件通常被用来完成特定的任务或执行重复性的操作。 脚本文件通常以某种编程语言的语法编写&#xff0c;例如 Bash、Python、Perl、Ruby 等等。…

二叉树的层平均值

给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[3.00000,14.50000,11.00000] 解释&#xff1a;第 0 层的平均值为 …

微服务架构风格

1 引言 微服务是一种架构风格&#xff0c;它将应用构建位为一个小型自治服务的集合&#xff0c;以业务领域为模型。通俗地说&#xff0c;就像蜜蜂通过对蜡制的等边六边形单元来构建它们的蜂巢。它们最初从使用材料的小单元开始&#xff0c;一点点的搭建出一个大型蜂巢。这些小单…

【OpenCV学习笔记27】- OpenCV 中的直方图 - 直方图 - 1:查找,绘图,分析

这是对于 OpenCV 官方文档中 图像处理 的学习笔记。学习笔记中会记录官方给出的例子&#xff0c;也会给出自己根据官方的例子完成的更改代码&#xff0c;同样彩蛋的实现也会结合多个知识点一起实现一些小功能&#xff0c;来帮助我们对学会的知识点进行结合应用。 如果有喜欢我笔…

1895_分离进程的能力

1895_分离进程的能力 全部学习汇总&#xff1a; g_unix: UNIX系统学习笔记 (gitee.com) 有些理念可能在控制类的嵌入式系统中不好实施&#xff0c;尤其是没有unix这样的系统搭载的情况下。如果是考虑在RTOS的基础上看是否有一些理念可以做尝试&#xff0c;我觉得还是可以有一定…

跟着pink老师前端入门教程-day17

2、CSS3 动画 动画&#xff08;animation&#xff09;是CSS3中就要有颠覆性的特征之一&#xff0c;可通过设置多个节点来精确控制一个或一组动画&#xff0c;常用来实现复杂的动画效果 相比较过渡&#xff0c;动画可以实现更多变化&#xff0c;更多控制&#xff0c;连续自动播…

【Simulink系列】——动态系统仿真 之 简单系统

引入 不同的系统具有不同的输入与输出。一般来说&#xff0c;输入输出数目越多&#xff0c;系统越复杂。最简单的系统只要一个输入一个输出&#xff08;SISO&#xff09;&#xff0c;且其任意时刻的输出只与当前时刻的输入有关。 一、简单系统定义 对于满足下列条件的系统&a…

通过 ChatGPT 的 Function Call 查询数据库

用 Function Calling 的方式实现手机流量包智能客服的例子。 def get_sql_completion(messages, model"gpt-3.5-turbo"):response client.chat.completions.create(modelmodel,messagesmessages,temperature0,tools[{ # 摘自 OpenAI 官方示例 https://github.com/…

移远(Quectel)物联网通信解决方案

一、方案简介 无线通信模块是具备无线通信的电路模块&#xff0c;它能通过无线连接传输数据&#xff0c;能识别分析主控制器发来的命令&#xff0c;控制节点设备的工作&#xff0c;或者向主控制器发送当前节点设备的工作状态。 市面上常用的无线通信模组包括蓝牙模组、WLAN模…

灵伴科技(Rokid)借助 Knative 实现 AI 应用云原生 Serverless 化

作者&#xff1a;朱炜栋、元毅、子白 公司介绍 Rokid 创立于 2014 年&#xff0c;是一家专注于人机交互技术的产品平台公司&#xff0c;2018 年即被评为国家高新技术企业。Rokid 作为行业的探索者、领跑者&#xff0c;目前致力于 AR 眼镜等软硬件产品的研发及以 YodaOS 操作系…

数据结构—基础知识:哈夫曼编码

文章目录 数据结构—基础知识&#xff1a;哈夫曼编码哈夫曼编码的主要思想有关编码的概念哈夫曼编码满足两个性质&#xff1a; 数据结构—基础知识&#xff1a;哈夫曼编码 哈夫曼编码的主要思想 在进行数据压缩时&#xff0c;为了使压缩后的数据文件尽可能短&#xff0c;可采…

使用Python的turtle模块实现简单的烟花效果

import turtle import random import math# 设置窗口大小 width, height 800, 600 screen turtle.Screen() screen.title("Fireworks Explosion") screen.bgcolor("black") screen.setup(width, height)# 定义烟花粒子类 class Particle(turtle.Turtle):…

STM32控制DHT11温湿度传感器模块获取温湿度数据

时间记录&#xff1a;2024/1/29 一、DHT11引脚介绍 &#xff08;1&#xff09;VCC&#xff1a;电源引脚&#xff0c;3.3-5.5V &#xff08;2&#xff09;DATA&#xff1a;数据输入输出引脚 &#xff08;3&#xff09;NC&#xff1a;保留引脚&#xff0c;悬空即可 &#xff08;…

颐和园龙纹珍宝展亮相,文物预防保护科技护航

在皇家园林颐和园的深处&#xff0c;一场独特的文化盛宴正静静上演。2月1日&#xff0c;“祥龙贺岁—颐和园藏龙纹题材文物特展”在德和园华丽揭幕。此次特展汇聚了66件珍贵文物&#xff0c;包括玉器、瓷器、书画、珐琅、家具等&#xff0c;每一件都是颐和园园藏的瑰宝。这些文…

clickhouse如何清除多个分区数据 alter table drop partition操作

官网drop partition操作 官网链接&#xff1a;https://clickhouse.com/docs/zh/sql-reference/statements/alter/partition#drop-partitionpart 官网上之有清除单个分区的例子&#xff0c;并没有对清除多个分区的场景进行描述&#xff0c;之前清除分区时也是按照官网例子进行…

【Python】【完整代码】解析Excel文件内容,按每列首行元素名打印出某个字符串的统计占比(超详细)

目录 1.示例&#xff1a; 1.1 实现代码1&#xff1a;列数为常量 运行结果&#xff1a; 1.2 实现代码2&#xff1a;列数为变量 运行结果&#xff1a; 1.示例&#xff1a; 开发需求&#xff1a;读取Excel文件&#xff0c;统计第3列到第5列中每列的"False"字段占…

【新书推荐】5.1节 16位汇编语言学习环境

第五章 16位汇编学习环境 16位汇编语言的学习环境是建立在8086计算机的基础上的&#xff0c;我将借助于DosBox虚拟机来实现16位汇编语言学习环境的搭建。 5.1节 16位汇编语言学习环境 本节内容&#xff1a;16位汇编学习环境的搭建。 ■汇编语言程序设计编程调试过程&#xff1…

【React】react组件传参

【React】react组件传参 一、props&#xff1a;父组件向子组件传参1、将普通的参数作为props传递2、将jsx作为props传递&#xff08;组件插槽&#xff09; 二、自定义事件&#xff1a;子父组件向父组件传参三、context进行多级组件传参四、redux全局状态管理 一、props&#xf…

MySQL篇----第四篇

系列文章目录 文章目录 系列文章目录前言一、数据库的三范式是什么二、第一范式(1st NF - 列都是不可再分)三、第二范式(2nd NF- 每个表只描述一件事情)四、第三范式(3rd NF- 不存在对非主键列的传递依赖)五、数据库是事务前言 前些天发现了一个巨牛的人工智能学习网站,通…

C++迷宫游戏详解

个人主页&#xff1a;[PingdiGuo_guo] 收录专栏&#xff1a;[C干货专栏] 大家好呀&#xff0c;我是PingdiGuo_guo&#xff0c;今天我们来学习用C实现一个迷宫游戏。 目录 1.迷宫的具体步骤 1.1.迷宫的初始化 1.2.寻路算法 1.DFS算法 2.BFS算法 1.3.移动 2.总结 C迷宫游…