春节假期半个多月倾力研发,原创Flutter3.27+Dart3.6+Getx+MediaKit跨平台仿抖音app商城项目完结了
flutter3_douyin_mall采用最新版跨平台框架Flutter3.27架构开发。实现类似抖音app首页tab联动切换效果。
使用技术栈
- 编码开发:vscode
- 技术框架:flutter3.27.1+Dart3.6.0
- 路由/状态管理:get: ^4.6.6
- 本地缓存服务:get_storage: ^2.1.1
- 瀑布流组件:flutter_staggered_grid_view^0.7.0
- 轮播图组件:card_swiper^3.0.1
- toast弹窗组件:shirne_dialog^4.8.3
- 视频套件:media_kit: ^1.1.11
如下图:类似抖音app首页tab联动切换。
项目结构框架
项目入口配置
配置一些公共插件,路由信息等。
/// 入口文件main.dart library; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; import 'package:media_kit/media_kit.dart'; import 'package:shirne_dialog/shirne_dialog.dart'; import 'utils/common.dart'; // 引入布局页面 import 'layouts/index.dart'; // 引入路由配置 import 'router/index.dart'; void main() async { // 初始化get_storage存储 await GetStorage.init(); // 初始化media_kit视频套件 WidgetsFlutterBinding.ensureInitialized(); MediaKit.ensureInitialized(); runApp(const App()); } class App extends StatelessWidget { const App({super.key}); @override Widget build(BuildContext context) { return GetMaterialApp( title: 'Flutter3 DYMALL', debugShowCheckedModeBanner: false, theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFFFF9900)), useMaterial3: true, fontFamily: Platform.isWindows ? 'Microsoft YaHei' : null ), home: const Layout(), // 初始化路由 initialRoute: Common.isLogin() ? '/' : '/login', // 路由页面 getPages: routePages, // 初始化弹窗key navigatorKey: MyDialog.navigatorKey, ); } }
Flutter3.x实现图片灯箱/tab滚动吸附
运用 CustomScrollView 组件实现页面滚动, SliverAppBar 组件实现顶部轮播图功能, SliverPersistentHeader 组件实现tab固定吸附效果。
return Scaffold( backgroundColor: Colors.grey[50], body: ScrollConfiguration( behavior: CustomScrollBehavior().copyWith(scrollbars: false), child: CustomScrollView( scrollBehavior: CustomScrollBehavior().copyWith(scrollbars: false), controller: scrollController, slivers: [ SliverAppBar( backgroundColor: Colors.transparent, foregroundColor: Colors.white, pinned: true, expandedHeight: 200.0, titleSpacing: 10.0, // 搜索框(高斯模糊背景) title: ClipRRect( borderRadius: BorderRadius.circular(30.0), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0), child: Container( ), ), ), actions: [ IconButton(icon: Icon(Icons.shopping_cart_outlined), onPressed: () {},), ], // 自定义伸缩区域(轮播图) flexibleSpace: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Color(0xFFFF5000), Color(0xFFfcaec4) ] ) ), child: FlexibleSpaceBar( background: Swiper.children( pagination: SwiperPagination( builder: DotSwiperPaginationBuilder( color: Colors.white70, activeColor: Colors.white, ) ), indicatorLayout: PageIndicatorLayout.SCALE, children: [ Image.network('https://m.360buyimg.com/babel/jfs/t20271217/224114/35/38178/150060/6760d559Fd654f946/968c156726b6e822.png',), Image.network('https://m.360buyimg.com/babel/jfs/t20280117/88832/5/48468/139826/6789cbcfF4e0b2a3d/9dc54355b6f65c40.jpg',), Image.network('https://m.360buyimg.com/babel/jfs/t20280108/255505/29/10540/137372/677ddbc1F6cdbbed0/bc477fadedef22a8.jpg',), ], ), ), ), ), // tabbar列表 SliverPersistentHeader( pinned: true, delegate: CustomStickyHeader( child: PreferredSize( preferredSize: Size.fromHeight(45.0), child: Container( ), ), ), ), // 瀑布流列表 ], ), ), // 返回顶部 floatingActionButton: Backtop(controller: scrollController, offset: scrollOffset), );
Flutter3实现短视频+直播功能模块
@override Widget build(BuildContext context) { return Container( color: Colors.black, child: Column( children: [ Expanded( child: Stack( children: [ PageView.builder( scrollDirection: Axis.vertical, controller: pageController, onPageChanged: (index) async { // 更新播放索引 videoModuleController.updateVideoPlayIndex(index); setState(() { // 重置slider参数 sliderValue = 0.0; sliderDraging = false; position = Duration.zero; duration = Duration.zero; }); player.stop(); await player.open(Media(videoList[index]['src'])); }, itemCount: videoList.length, itemBuilder: (context, index) { return Stack( children: [ // 视频区域 Positioned( top: 0, left: 0, right: 0, bottom: 0, child: GestureDetector( child: Stack( children: [ // 短视频插件 Visibility( visible: videoModuleController.videoPlayIndex.value == index && position > Duration.zero, child: Video( controller: videoController, fit: BoxFit.cover, ), ), // 播放/暂停按钮 StreamBuilder( stream: player.stream.playing, builder: (context, playing) { return Visibility( visible: playing.data == false, child: Center( child: IconButton( padding: EdgeInsets.zero, onPressed: () { player.playOrPause(); }, icon: Icon( playing.data == true ? Icons.pause : Icons.play_arrow_rounded, color: Colors.white60, size: 80, ), style: ButtonStyle( backgroundColor: WidgetStateProperty.all(Colors.black.withAlpha(15)) ), ), ), ); }, ), ], ), onTap: () { player.playOrPause(); }, ), ), // 右侧操作栏 Positioned( bottom: 15.0, right: 6.0, child: Column( spacing: 15.0, children: [ ], ), ), // 底部信息区域 Positioned( bottom: 15.0, left: 10.0, right: 80.0, child: Column( ), ), // mini播放进度条 Positioned( bottom: 0.0, left: 6.0, right: 6.0, child: Visibility( visible: videoModuleController.videoPlayIndex.value == index && position > Duration.zero, child: Listener( child: SliderTheme( data: SliderThemeData( trackHeight: sliderDraging ? 6.0 : 2.0, thumbShape: RoundSliderThumbShape(enabledThumbRadius: 4.0), // 调整滑块的大小 overlayShape: RoundSliderOverlayShape(overlayRadius: 0), // 去掉Slider默认上下边距间隙 inactiveTrackColor: Colors.white24, // 设置非活动进度条的颜色 activeTrackColor: Colors.white, // 设置活动进度条的颜色 thumbColor: Colors.white, // 设置滑块的颜色 overlayColor: Colors.transparent, // 设置滑块覆盖层的颜色 ), child: Slider( value: sliderValue, onChanged: (value) async { // debugPrint('当前视频播放时间$value'); setState(() { sliderValue = value; }); // 跳转播放时间 await player.seek(duration * value.clamp(0.0, 1.0)); }, onChangeEnd: (value) async { setState(() { sliderDraging = false; }); // 继续播放 if(!player.state.playing) { await player.play(); } }, ), ), onPointerMove: (e) { setState(() { sliderDraging = true; }); }, ), ), ), // 播放位置指示器 Positioned( bottom: 100.0, left: 10.0, right: 10.0, child: Visibility( visible: sliderDraging, child: DefaultTextStyle( style: TextStyle(color: Colors.white54, fontSize: 18.0, fontFamily: 'Arial'), child: Row( mainAxisAlignment: MainAxisAlignment.center, spacing: 8.0, children: [ Text(position.label(reference: duration), style: TextStyle(color: Colors.white)), Text('/', style: TextStyle(fontSize: 14.0)), Text(duration.label(reference: duration)), ], ), ) ), ), ], ); }, ), /// 固定层 // 红包广告 Ads(), ], ), ), ], ), ); }
如上图:直播模块包含了顶部信息、直播礼物左侧滑入、进场动效右侧滑入、弹幕消息、右侧讲解商品、底部操作栏等功能。
// flutter3直播模块核心片段 @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, extendBodyBehindAppBar: true, appBar: AppBar( forceMaterialTransparency: true, backgroundColor: Colors.black, foregroundColor: Colors.white, toolbarHeight: 0, ), body: Column( children: [ Expanded( child: Stack( children: [ PageView.builder( scrollBehavior: CustomScrollBehavior().copyWith(scrollbars: false), scrollDirection: Axis.vertical, controller: pageVerticalController, onPageChanged: (index) async { setState(() { liveIndex = index; }); player.stop(); await player.open(Media(liveJson[index]['src'])); }, itemCount: liveJson.length, itemBuilder: (context, index) { return Stack( children: [ // 视频区域 Positioned( ), /// 水平滚动模块(清屏/浮层) PageView( scrollDirection: Axis.horizontal, controller: pageHorizontalController, onPageChanged: (index) { // ... }, children: [ // 直播清屏 Container( ), // 直播浮层 Stack( children: [ // 顶部区域 Positioned( top: MediaQuery.of(context).padding.top + 7, left: 10.0, right: 0, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 直播间头像 Container( ), // 排名统计 Container( ), // 红包活动 Container( ), ], ), ), // 底部区域 Positioned( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 商品购买动效 Container( ), // 送礼物动效 AnimationLiveGift( giftQueryList: [ {'label': '小心心', 'gift': 'assets/images/gift/gift1.png', 'user': 'Jack', 'avatar': 'assets/images/avatar/img02.jpg', 'num': 12}, {'label': '棒棒糖', 'gift': 'assets/images/gift/gift2.png', 'user': 'Andy', 'avatar': 'assets/images/avatar/img06.jpg', 'num': 36}, {'label': '大啤酒', 'gift': 'assets/images/gift/gift3.png', 'user': '一条咸鱼', 'avatar': 'assets/images/avatar/img01.jpg', 'num': 162}, ], ), // 加入直播间动效 AnimationLiveJoin( joinQueryList: [ {'avatar': 'assets/images/logo.png', 'name': 'andy'}, {'avatar': 'assets/images/logo.png', 'name': 'jack'}, ], ), // 直播弹幕+商品讲解 Container( margin: EdgeInsets.only(top: 7.0), height: 200.0, child: Row( ), ), // 底部工具栏 Container( margin: const EdgeInsets.only(top: 7.0), child: Row( ), ), ], ), ), ], ), ], ), ], ); }, ), ], ), ), ], ), ); }
整个项目整合了短视频+直播+聊天功能模块。涉及到的知识点蛮多,希望以上分享对大家有所帮助~