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.rhkb.cn/news/250291.html

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

相关文章

k8s kubeadm部署安装详解

目录 kubeadm部署流程简述 环境准备 步骤简述 关闭 防火墙规则、selinux、swap交换 修改主机名 配置节点之间的主机名解析 调整内核参数 所有节点安装docker 安装依赖组件 配置Docker 所有节点安装kubeadm&#xff0c;kubelet和kubectl 定义kubernetes源并指定版本…

网络异常案例四_IP异常

问题现象 终端设备离线&#xff0c;现场根据设备ip&#xff0c;ping不通。查看路由器。 同一个路由器显示的终端设备&#xff08;走同一个wifi模块接入&#xff09;&#xff0c;包含不同网段的ip。 现场是基于三层的无线漫游&#xff0c;多个路由器wifi配置了相同的ssid信息&a…

某赛通电子文档安全管理系统 UploadFileToCatalog SQL注入漏洞复现

0x01 产品简介 某赛通电子文档安全管理系统(简称:CDG)是一款电子文档安全加密软件,该系统利用驱动层透明加密技术,通过对电子文档的加密保护,防止内部员工泄密和外部人员非法窃取企业核心重要数据资产,对电子文档进行全生命周期防护,系统具有透明加密、主动加密、智能…

【机器学习】AAAI 会议论文聚类分析

实验五&#xff1a;AAAI 会议论文聚类分析 ​ 本次实验以AAAI 2014会议论文数据为基础&#xff0c;要求实现或调用无监督聚类算法&#xff0c;了解聚类方法。 1 任务介绍 ​ 每年国际上召开的大大小小学术会议不计其数&#xff0c;发表了非常多的论文。在计算机领域的一些大…

【二进制漏洞】缓冲区溢出漏洞

天命&#xff1a;好像复现成功了&#xff0c;又好像没有完全成功 学习视频&#xff1a;抓住漏洞&#xff01;缓冲区溢出漏洞利用实例&#xff0c;如何利用溢出执行Shell Code_哔哩哔哩_bilibili 漏洞复现 实验环境&#xff1a;kali &#xff08;其实啥都试过&#xff0c;windo…

Linux基础知识合集

整理了一下学习的一些关于Linux的一些基础知识&#xff0c;同学们也可以通过公众号菜单栏查看&#xff01; 一、基础知识 Linux基础知识 Linux命令行基础学习 Linux用户与组概念初识 Linux文件与目录权限基础 Linux中文件内容的查看 Linux系统之计划任务管理 二、服务器管理 Vm…

通过与chatGPT交流实现零样本事件抽取

1、写作动机&#xff1a; 近来的大规模语言模型&#xff08;例如Chat GPT&#xff09;在零样本设置下取得了很好的表现&#xff0c;这启发作者探索基于提示的方法来解决零样本IE任务。 2、主要贡献&#xff1a; 提出了基于chatgpt的多阶段的信息抽取方法&#xff1a;在第一阶…

DHCP简介

定义 动态主机配置协议DHCP&#xff08;Dynamic Host Configuration Protocol&#xff09;是一种用于集中对用户IP地址进行动态管理和配置的技术。即使规模较小的网络&#xff0c;通过DHCP也可以使后续增加网络设备变得简单快捷。 DHCP是在BOOTP&#xff08;BOOTstrap Protoc…

[GN] 设计模式—— 创建型模式

文章目录 创建型模式单例模式 -- 确保对象唯一性例子优化饿汉式懒汉式 优缺点使用场景 简单工厂模式例子&#xff1a;优化优缺点适用场景 工厂方法模式 -- 多态工厂的实现例子优缺点优化适用场景 抽象工厂模式 -- 产品族的创建例子优缺点适用场景 总结 创建型模式 单例模式 –…

公共用例库计划--个人版(六)典型Bug页面设计与开发

1、任务概述 本次计划的核心任务是开发一个&#xff0c;个人版的公共用例库&#xff0c;旨在将各系统和各类测试场景下的通用、基础以及关键功能的测试用例进行系统性地归纳整理&#xff0c;并以提高用例的复用率为目标&#xff0c;力求最大限度地减少重复劳动&#xff0c;提升…

接口安全测试

一、后台接口分类 1、接口类别&#xff1a;restful(json) soap(xml) 2、协议 &#xff1a;http https(ssl) 3、restful接口请求类型 get操作是安全的 post的操作是不安全的 同put delete也是不安全的 4、现状和问题 大部分APP的接口都采用restful架构&#xff0c;restful…

G7-Semi-Supervised GAN解读

本文为&#x1f517;365天深度学习训练营 中的学习记录博客 原作者&#xff1a;K同学啊|接辅导、项目定制 我的环境&#xff1a; 1.语言&#xff1a;python3.7 2.编译器&#xff1a;pycharm 3.深度学习框架Pytorch 1.8.0cu111 论文地址 一、理论理解 半监督生成对抗网络&…

C语言系列-联合

&#x1f308;个人主页: 会编程的果子君 ​&#x1f4ab;个人格言:“成为自己未来的主人~” 目录 联合体 联合体类型的声明 联合体的特点 相同成员的结构体和联合体对比 联合体大小的计算 联合的一个练习 联合体 联合体类型的声明 像结构体一样&#xff0c;联合体也是由…

闲聊电脑(4)硬盘分区

夜深人静&#xff0c;万籁俱寂&#xff0c;老郭趴在电脑桌上打盹&#xff0c;桌子上的小黄鸭和桌子旁的冰箱又开始窃窃私语…… 小黄鸭&#xff1a;冰箱大哥&#xff0c;上次你说的那个“分区”和“格式化”是什么意思&#xff1f; 冰箱&#xff1a;分区么&#xff0c;就是分…

Jasperreport 生成 PDF之省纸模式

省纸模式顾名思义就是节省纸张&#xff0c;使用 Jasper 去生成 PDF 的时候如果进行分组打印的时候&#xff0c;一页 A4 纸只会打印一组数据。这种情况下&#xff0c;如果每组数据特别少&#xff0c;只有几行&#xff0c;一页 A4 纸张根本用不了&#xff0c;就会另起一页继续打印…

elementui中的tree自定义图标

需求&#xff1a;实现如下样式的树形列表 自定义树的图标以及点击时&#xff0c;可以根据子级的关闭&#xff0c;切换图标 <el-tree :data"treeList" :props"defaultProps"><template #default"{ node, data }"><span class&quo…

linux中vim的操作

(码字不易&#xff0c;关注一下吧w~~w) 命令模式&#xff1a; 当我们按下esc键时&#xff0c;我们会进入命令模式&#xff1b;当使用vi打开一个文件时也是进入命令模式。 光标移动&#xff1a; 1 保存退出&#xff1a;ZZ 2 代码格式化&#xff1a;ggG 3 光标移动&#xff…

谁懂啊!性能测试还能这么快学好。。。。。。

前言 互联网普及&#xff0c;用户群体庞大&#xff0c;用户体验非常重要。性能是一种指标&#xff0c;是软件系统对于及时性的符合程度。对于一个产品根据响应时间和吞吐量衡量性能的及时性&#xff0c;响应时间是一个http完整的请求流程时间之和。对用户而言&#xff0c;响应…

【开源】基于Qt5的ROS1/ROS2人机交互软件(支持地图编辑/多点导航)

本项目基于Qt5开发&#xff0c;基于CMake进行构建&#xff0c;可以实现一套代码同时在ROS1/ROS2系统中使用(本项目已接入CI,保证多ROS版本/系统版本可用性) 项目地址&#xff1a; https://github.com/chengyangkj/Ros_Qt5_Gui_App 软件在编译时会自动识别环境变量中的ROS1/ROS…

Redis -- list列表

只有克服了情感的波动&#xff0c;才能专心致志地追求事业的成功 目录 列表 list命令 lpush lpushx rpush rpushx lrange lpop rpop lindex linsert llen lrem ltrim 阻塞命令 小结 列表 列表相当于 数组或者顺序表。 列表类型是用来存储多个有序的字符串&…