flutter3-dart3-dymall原创仿抖音(直播+短视频+聊天)商城app系统模板

本文涉及的产品
可观测可视化 Grafana 版,10个用户账号 1个月
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
性能测试 PTS,5000VUM额度
简介: 基于最新版flutter3.27+dart3.x+Getx+mediaKit原创实战研发抖音app带货商城项目。集成了直播+短视频+聊天三大功能模块。实现了类似抖音app首页全屏沉浸式联动左右滑动页面模块、上下滑动短视频。

春节假期半个多月倾力研发,原创Flutter3.27+Dart3.6+Getx+MediaKit跨平台仿抖音app商城项目完结了 未标题-5.png

flutter3_douyin_mall采用最新版跨平台框架Flutter3.27架构开发。实现类似抖音app首页tab联动切换效果。


未标题-3.png

使用技术栈

  • 编码开发: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


p3.gif

p4.gif


如下图:类似抖音app首页tab联动切换

p4-1.gif


项目结构框架

360截图20250125003729216.png


p1.gif

002360截图20250124095719756.png 002360截图20250124095927981.png 003360截图20250124100327260.png 003360截图20250124100423015.png 003360截图20250124100643429.png 003360截图20250124101043956.png 003360截图20250124101336963.png 003360截图20250124101415860.png 003360截图20250124101459884.png 003360截图20250124101557788.png

项目入口配置

配置一些公共插件,路由信息等。

/// 入口文件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滚动吸附

71ecd2252566a5309cbb265e3d1be540_1289798-20250206111227634-1386910092.png


运用 CustomScrollView 组件实现页面滚动, SliverAppBar 组件实现顶部轮播图功能, SliverPersistentHeader 组件实现tab固定吸附效果。

7b466625ec48b5407f876fdbafd394e1_1289798-20250206112626811-938879545.gif

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),
);

004360截图20250124101744572.png 004360截图20250124102021036.png 004360截图20250124102245413.png 004360截图20250124102954806.png 004360截图20250124102954808.png 004360截图20250124103131939.png 004360截图20250124103203980.png 004360截图20250124103247506.png


Flutter3实现短视频+直播功能模块


3f5391ec5c940f9a31d7c0652266bcb8_1289798-20250206115619134-1814907728.png

@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(),
            ],
          ),
        ),
      ],
    ),
  );
}


86207e21d3ed97636d594d3bf679242c_1289798-20250206120337700-1453540506.png

如上图:直播模块包含了顶部信息、直播礼物左侧滑入、进场动效右侧滑入、弹幕消息、右侧讲解商品、底部操作栏等功能。


755014dc0b04b60fc07d77c3c4ac51be_1289798-20250206120608870-1221731002.png

// 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(
                                        ...
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                            ],
                          ),
                        ],
                      ),
                    ],
                  );
                },
              ),
            ],
          ),
        ),
      ],
    ),
  );
}

005360截图20250124104145938.png 005360截图20250124104216371.png 005360截图20250124104358499.png 005360截图20250124104528370.png 005360截图20250124104558867.png 005360截图20250124105020057.png 005360截图20250124105239169.png 005360截图20250124105309634.png 005360截图20250124105323097.png 005360截图20250124105339281.png 006360截图20250124105541377.png 006360截图20250124105631577.png 007360截图20250124105718305.png 007360截图20250124105821777.png


整个项目整合了短视频+直播+聊天功能模块。涉及到的知识点蛮多,希望以上分享对大家有所帮助~


目录
相关文章
|
9月前
|
安全 数据安全/隐私保护 iOS开发
iOS App 上架流程图文教学
在上架App 之前必须先准备好开发者帐号,但申请开发者帐号因法兰克早在之前已经申请好了,故就跳过此步骤,直接从产生凭证到上传App开始讲起。首先,要将自己辛苦写好的App 送审的话,则要依序做完下列几件事情即可。
|
9月前
|
安全 数据安全/隐私保护 开发者
|
14天前
|
Dart 前端开发 容器
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
58 18
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
19天前
|
移动开发 小程序
thinkphp+uniapp开发的多端商城系统源码/H5/小程序/APP支持DIY模板直播分销
thinkphp+uniapp开发的多端商城系统源码/H5/小程序/APP支持DIY模板直播分销
18 0
|
3月前
|
移动开发 小程序
仿青藤之恋社交交友软件系统源码 即时通讯 聊天 微信小程序 App H5三端通用
仿青藤之恋社交交友软件系统源码 即时通讯 聊天 微信小程序 App H5三端通用
126 3
|
5月前
|
开发工具
uniapp, 短剧视频类App实现参考,支持滑动播放,仿抖音 仿陌陌 短视频 无限滑动播放 视频流
阿里云点播服务web播放器sdk,短剧视频类App实现参考。仿抖音 仿陌陌 短视频 无限滑动播放 视频流。无uniapp video 原生组件的层级、遮挡、覆盖问题,适合与不同功能视图组合使用,实现丰富的应用功能。
uniapp, 短剧视频类App实现参考,支持滑动播放,仿抖音 仿陌陌 短视频 无限滑动播放 视频流
|
7月前
|
小程序
仿qq音乐播放微信小程序模板源码
手机qq音乐应用小程序,在线音乐播放器微信小程序网页模板。包含:音乐歌曲主页、推荐、排行榜、搜索、音乐播放器、歌单详情等。
73 1
|
9月前
|
iOS开发
|
7月前
Flutter-仿淘宝京东录音识别图标效果
Flutter-仿淘宝京东录音识别图标效果
39 0
|
9月前
uni-app 158发布朋友圈-上传短视频
uni-app 158发布朋友圈-上传短视频
79 0