
解决邮箱无法接收验证码问题:添加白名单
当您在注册账号或绑定邮箱时,遇到邮箱无法接收验证码的情况,可能是由于邮件被误判为垃圾邮件或被邮箱服务商拦截。为了确保您能够顺利收到验证码邮件,您可以按照以下步骤将我们的邮件地址添加到您的邮箱白名单中。
1. 检查垃圾邮件文件夹
首先,请检查您的邮箱的垃圾邮件文件夹。有时候,验证码邮件可能会被误判为垃圾邮件,并被自动转移到该文件夹中。
2. 添加发件人邮箱到白名单
如果验证码邮件仍然没有出现在您的收件箱或垃圾邮件文件夹中,您可以通过以下方法将我们的发件人地址(mail.dcloud.net.cn
、mail.dcloud.io
)添加到您的邮箱白名单中。不同邮箱服务商的操作步骤可能会有所不同,以下是常见邮箱的操作方法:
1. 163邮箱
- 登录到您的 163邮箱 账号。
- 找到垃圾邮件文件夹,查看是否有验证码邮件。
- 如果找到了验证码邮件,打开邮件,然后点击“不是垃圾邮件”,系统会自动将其移回收件箱。
- 为了防止以后邮件被误判为垃圾邮件,您可以将我们的发件人邮箱添加到白名单:
- 在163邮箱主界面,点击左上角的 “设置”。
- 在设置页面,选择 “反垃圾/黑白名单” 选项卡。
- 在 “白名单设置” 中,点击 “添加白名单”,然后输入我们的发件人邮箱地址。
- 点击 “确定”。
2. QQ邮箱
- 登录到您的 QQ邮箱 账号。
- 找到垃圾邮件文件夹,查看是否有验证码邮件。
- 如果找到了验证码邮件,点击打开,然后点击 “不是垃圾邮件” 按钮,将邮件移回收件箱。
- 将我们的发件人邮箱添加到白名单:
- 在QQ邮箱的页面中,点击左上角的 “设置”。
- 在设置页面中,选择 “反垃圾” 标签。
- 在 “白名单” 部分,点击 “添加白名单”,输入我们的发件人邮箱地址。
- 点击 “保存”。
3. Gmail
- 打开Gmail,登录您的账号。
- 找到垃圾邮件文件夹,查看是否有我们的验证码邮件。
- 如果找到了验证码邮件,点击打开邮件。
- 点击邮件顶部的“更多”按钮(三个垂直点),选择“将发件人加入白名单”。
- 如果您没有找到邮件,可以添加我们的发件人地址到您的联系人列表中,这样未来的邮件就不会被误判为垃圾邮件。
4. Outlook
- 打开Outlook,登录您的账号。
- 进入“垃圾邮件”文件夹,查看是否有验证码邮件。
- 如果找到邮件,右键点击邮件,选择“标记为非垃圾邮件”。
- 您还可以手动将我们的发件人地址添加到“安全发件人”列表:
- 点击“设置”(齿轮图标),选择“查看所有 Outlook 设置”。
- 在“邮件”选项中,选择“垃圾邮件”。
- 在“安全发件人和域名”部分,点击“添加”并输入我们的发件人邮箱地址。
5. 其他邮箱服务
对于其他邮箱服务,您可以查看其帮助文档或联系其客服,了解如何将发件人邮箱地址添加到白名单中。大多数邮箱都有类似的垃圾邮件过滤和白名单设置选项。
3. 联系我们
如果您已按照上述步骤操作,但仍然无法收到验证码邮件,欢迎通过我们的客服邮箱(service@dcloud.io
)与我们联系,我们将尽力为您解决问题。
当您在注册账号或绑定邮箱时,遇到邮箱无法接收验证码的情况,可能是由于邮件被误判为垃圾邮件或被邮箱服务商拦截。为了确保您能够顺利收到验证码邮件,您可以按照以下步骤将我们的邮件地址添加到您的邮箱白名单中。
1. 检查垃圾邮件文件夹
首先,请检查您的邮箱的垃圾邮件文件夹。有时候,验证码邮件可能会被误判为垃圾邮件,并被自动转移到该文件夹中。
2. 添加发件人邮箱到白名单
如果验证码邮件仍然没有出现在您的收件箱或垃圾邮件文件夹中,您可以通过以下方法将我们的发件人地址(mail.dcloud.net.cn
、mail.dcloud.io
)添加到您的邮箱白名单中。不同邮箱服务商的操作步骤可能会有所不同,以下是常见邮箱的操作方法:
1. 163邮箱
- 登录到您的 163邮箱 账号。
- 找到垃圾邮件文件夹,查看是否有验证码邮件。
- 如果找到了验证码邮件,打开邮件,然后点击“不是垃圾邮件”,系统会自动将其移回收件箱。
- 为了防止以后邮件被误判为垃圾邮件,您可以将我们的发件人邮箱添加到白名单:
- 在163邮箱主界面,点击左上角的 “设置”。
- 在设置页面,选择 “反垃圾/黑白名单” 选项卡。
- 在 “白名单设置” 中,点击 “添加白名单”,然后输入我们的发件人邮箱地址。
- 点击 “确定”。
2. QQ邮箱
- 登录到您的 QQ邮箱 账号。
- 找到垃圾邮件文件夹,查看是否有验证码邮件。
- 如果找到了验证码邮件,点击打开,然后点击 “不是垃圾邮件” 按钮,将邮件移回收件箱。
- 将我们的发件人邮箱添加到白名单:
- 在QQ邮箱的页面中,点击左上角的 “设置”。
- 在设置页面中,选择 “反垃圾” 标签。
- 在 “白名单” 部分,点击 “添加白名单”,输入我们的发件人邮箱地址。
- 点击 “保存”。
3. Gmail
- 打开Gmail,登录您的账号。
- 找到垃圾邮件文件夹,查看是否有我们的验证码邮件。
- 如果找到了验证码邮件,点击打开邮件。
- 点击邮件顶部的“更多”按钮(三个垂直点),选择“将发件人加入白名单”。
- 如果您没有找到邮件,可以添加我们的发件人地址到您的联系人列表中,这样未来的邮件就不会被误判为垃圾邮件。
4. Outlook
- 打开Outlook,登录您的账号。
- 进入“垃圾邮件”文件夹,查看是否有验证码邮件。
- 如果找到邮件,右键点击邮件,选择“标记为非垃圾邮件”。
- 您还可以手动将我们的发件人地址添加到“安全发件人”列表:
- 点击“设置”(齿轮图标),选择“查看所有 Outlook 设置”。
- 在“邮件”选项中,选择“垃圾邮件”。
- 在“安全发件人和域名”部分,点击“添加”并输入我们的发件人邮箱地址。
5. 其他邮箱服务
对于其他邮箱服务,您可以查看其帮助文档或联系其客服,了解如何将发件人邮箱地址添加到白名单中。大多数邮箱都有类似的垃圾邮件过滤和白名单设置选项。
3. 联系我们
如果您已按照上述步骤操作,但仍然无法收到验证码邮件,欢迎通过我们的客服邮箱(service@dcloud.io
)与我们联系,我们将尽力为您解决问题。

Uniapp cli项目引用UTS插件(基于uniapp x)的一些异常问题
1.[plugin:uni:uts-uni_modules] compiler.compile is not a function
2.createUniXKotlinCompilerOnce is not a function
3.Definite Assignment Assertions is not supported.
我当前的环境:
HBuilderX版本:4.24
cli 的@dcloudio/uni-app版本: 3.0.0-4020420240722002
首先检查package.json中的@dcloudio/uni-uts-v1是否和别的@dcloudio/uni-xxx版本不一致,需要保持一致
如果有异常就执行下hx 菜单栏 -> 工具 -> 插件安装 -> 卸载重装uni-app(vue3),最好是让hx自动触发重新下载
上面的执行后还有问题可以尝试把uts相关的都删除重新安装一次,感觉像是有安装顺序的问题,我全部删除重新安装后就没问题了,不知道是啥原因造成的
#package.json的部分配置
"devDependencies": {
"@dcloudio/types": "3.4.8",
"@dcloudio/uni-automator": "3.0.0-4020420240722002",
"@dcloudio/uni-cli-shared": "3.0.0-4020420240722002",
"@dcloudio/uni-stacktracey": "3.0.0-4020420240722002",
###这个需要和其他的保持一样
"@dcloudio/uni-uts-v1": "3.0.0-4020420240722002",
###
"@dcloudio/vite-plugin-uni": "3.0.0-4020420240722002",
...
},
https://ask.dcloud.net.cn/question/195186
https://ask.dcloud.net.cn/question/202241
1.[plugin:uni:uts-uni_modules] compiler.compile is not a function
2.createUniXKotlinCompilerOnce is not a function
3.Definite Assignment Assertions is not supported.
我当前的环境:
HBuilderX版本:4.24
cli 的@dcloudio/uni-app版本: 3.0.0-4020420240722002
首先检查package.json中的@dcloudio/uni-uts-v1是否和别的@dcloudio/uni-xxx版本不一致,需要保持一致
如果有异常就执行下hx 菜单栏 -> 工具 -> 插件安装 -> 卸载重装uni-app(vue3),最好是让hx自动触发重新下载
上面的执行后还有问题可以尝试把uts相关的都删除重新安装一次,感觉像是有安装顺序的问题,我全部删除重新安装后就没问题了,不知道是啥原因造成的
#package.json的部分配置
"devDependencies": {
"@dcloudio/types": "3.4.8",
"@dcloudio/uni-automator": "3.0.0-4020420240722002",
"@dcloudio/uni-cli-shared": "3.0.0-4020420240722002",
"@dcloudio/uni-stacktracey": "3.0.0-4020420240722002",
###这个需要和其他的保持一样
"@dcloudio/uni-uts-v1": "3.0.0-4020420240722002",
###
"@dcloudio/vite-plugin-uni": "3.0.0-4020420240722002",
...
},
https://ask.dcloud.net.cn/question/195186
https://ask.dcloud.net.cn/question/202241

鸿蒙webview通信evalJS,不支持this.$scope.$getAppWebview().children()[0],需要使用使用uni.createWebviewContext
APP往webview通过evalJS注入方法时
鸿蒙不支持this.$scope.$getAppWebview().children()[0] ,使用uni.createWebviewContext
//template
<web-view id="webviewId" src="xxxxxx"></web-view>
//javascript
// #ifdef APP-HARMONY
this.currentWebview = uni.createWebviewContext('webviewId', this);
// #endif
// #ifdef APP-PLUS
this.currentWebview = this.$scope.$getAppWebview().children()[0];
// #endif
let token = uni.getStorageSync('token');
let tenant = uni.getStorageSync('tenantCode');
// 准备要传递的数据
let dataToPass = JSON.stringify({
token: token
});
this.currentWebview.evalJS(`uniappReceiveData('${JSON.stringify({ token: token,tenant: tenant})}')`)
APP往webview通过evalJS注入方法时
鸿蒙不支持this.$scope.$getAppWebview().children()[0] ,使用uni.createWebviewContext
//template
<web-view id="webviewId" src="xxxxxx"></web-view>
//javascript
// #ifdef APP-HARMONY
this.currentWebview = uni.createWebviewContext('webviewId', this);
// #endif
// #ifdef APP-PLUS
this.currentWebview = this.$scope.$getAppWebview().children()[0];
// #endif
let token = uni.getStorageSync('token');
let tenant = uni.getStorageSync('tenantCode');
// 准备要传递的数据
let dataToPass = JSON.stringify({
token: token
});
this.currentWebview.evalJS(`uniappReceiveData('${JSON.stringify({ token: token,tenant: tenant})}')`)
收起阅读 »

关于hx安卓输入证书密码的故事
前x:还记得不知道是多少年前了,那时候我还没老,还能coding,所以就喜欢折腾,把公司前程序员写的安卓原生客户端用uniapp实现了。
但是上架的时候发现一个问题,证书密码和别名密码原来是两个,但是hx只能输入一个,也就是hx里面这2个密码只能一致。
这个时候头大了,只有把包名都改了,老用户全部得重新安装。
转眼间到了2025了,人也老了,hx正式版更新到了4.45,这个时候可以输入2个密码了!!!!
然人老手脚不便了,输不动了。吾与在座各位都习惯了只输入一个密码,输入2个太麻烦了。
总结:可以增加一个功能吗,别名密码那里勾选和证书密码一致?也就是我只想输入一次。
前x:还记得不知道是多少年前了,那时候我还没老,还能coding,所以就喜欢折腾,把公司前程序员写的安卓原生客户端用uniapp实现了。
但是上架的时候发现一个问题,证书密码和别名密码原来是两个,但是hx只能输入一个,也就是hx里面这2个密码只能一致。
这个时候头大了,只有把包名都改了,老用户全部得重新安装。
转眼间到了2025了,人也老了,hx正式版更新到了4.45,这个时候可以输入2个密码了!!!!
然人老手脚不便了,输不动了。吾与在座各位都习惯了只输入一个密码,输入2个太麻烦了。
总结:可以增加一个功能吗,别名密码那里勾选和证书密码一致?也就是我只想输入一次。
收起阅读 »
uni-popup无法弹出 连接服务器超时,点击屏幕重试
浏览器的广告拦截插件会将uni-popup目录下的keypress.js识别为追踪器并将其拦截,导致报错
<DevToolsErrorMessage>
uni-popup.vue:3
GET /uni_modules/uni-popup/components/uni-popup/keypress.js net::ERR_BLOCKED_BY_CLIENT
</DevToolsErrorMessage>
并导致keypress.js无响应。
然后我就不清楚为啥了。
反正会导致提示 连接服务器超时,点击屏幕重试
关掉插件或加入白名单就解决了
浏览器的广告拦截插件会将uni-popup目录下的keypress.js识别为追踪器并将其拦截,导致报错
<DevToolsErrorMessage>
uni-popup.vue:3
GET /uni_modules/uni-popup/components/uni-popup/keypress.js net::ERR_BLOCKED_BY_CLIENT
</DevToolsErrorMessage>
并导致keypress.js无响应。
然后我就不清楚为啥了。
反正会导致提示 连接服务器超时,点击屏幕重试
关掉插件或加入白名单就解决了

"[uni-ai-chat]: Cannot read property 'getLLMManager' of undefined"
接入 ai时,我遇到了 "[uni-ai-chat]: Cannot read property 'getLLMManager' of undefined",不过这个我的问题是 nodejs的版本问题。修改后重新上传云对象就好了。
接入 ai时,我遇到了 "[uni-ai-chat]: Cannot read property 'getLLMManager' of undefined",不过这个我的问题是 nodejs的版本问题。修改后重新上传云对象就好了。

uts组件插件 使用this.$emit 时提示 fireEvent must be called by main thread
要在 emit 触发的外层使用
UTSAndroid.getDispatcher("main").async(function (_) {
}, null)
包括(必须在第一层)
UTSAndroid.getDispatcher("main").async(function (_) {
this.$emit('disconnectCallBack')
}, null)
要在 emit 触发的外层使用
UTSAndroid.getDispatcher("main").async(function (_) {
}, null)
包括(必须在第一层)
UTSAndroid.getDispatcher("main").async(function (_) {
this.$emit('disconnectCallBack')
}, null)
收起阅读 »

无阻碍点击事件
是否可以在这个基础上我定制个无阻碍点击事件,如1. 用户在微信中点击“按住说话”按钮。
AccessibilityService
检测到点击事件。AccessibilityService
通过WebView.evaluateJavascript
调用 JavaScript 函数onWeChatButtonClicked
。- JavaScript 函数执行相应的逻辑(如弹出提示)
是否可以在这个基础上我定制个无阻碍点击事件,如1. 用户在微信中点击“按住说话”按钮。
AccessibilityService
检测到点击事件。AccessibilityService
通过WebView.evaluateJavascript
调用 JavaScript 函数onWeChatButtonClicked
。- JavaScript 函数执行相应的逻辑(如弹出提示)

Flutter3.27实战2025抖音app直播商城
原创自研flutter3.27+dart3.6
实战抖音短视频+聊天+直播电商带货app商城应用程序。
Flutter3.27仿抖音短视频+直播+聊天app商城系统
技术栈
- 编辑器: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首页左右滑动切换页面内容,上下滑动切换短视频效果。
项目框架
目前flutter3-douyin-mall短视频直播商城项目已经同步到我的原创作品集。
Flutter3.27仿抖音短视频+直播+聊天app商城系统
flutter3实现首页轮播图+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 Scaffold(
key: scaffoldKey,
extendBodyBehindAppBar: true,
appBar: AppBar(
forceMaterialTransparency: true,
backgroundColor: [0, 1, 4, 5].contains(videoModuleController.videoTabIndex.value) ? null : Colors.transparent,
foregroundColor: [0, 1, 4, 5].contains(videoModuleController.videoTabIndex.value) ? Colors.black : Colors.white,
titleSpacing: 1.0,
leading: Obx(() => IconButton(
icon: Badge.count(
backgroundColor: Colors.red,
count: 6,
child: Icon(Icons.sort_rounded, color: tabColor(),),
),
onPressed: () {
// 自定义打开右侧drawer
scaffoldKey.currentState?.openDrawer();
},
)),
title: Obx(() {
return ScrollConfiguration(
behavior: CustomScrollBehavior().copyWith(scrollbars: false),
child: TabBar(
...
),
);
}),
actions: [
Obx(() => IconButton(icon: Icon(Icons.search_rounded, color: tabColor(),), onPressed: () {},),),
],
),
body: ScrollConfiguration(
behavior: CustomScrollBehavior().copyWith(scrollbars: false),
child: PageView(
controller: pageController,
onPageChanged: (index) {
videoModuleController.updateVideoTabIndex(index);
setState(() {
tabController.animateTo(index, duration: Duration(milliseconds: 200), curve: Curves.easeInOut);
});
},
children: [
...tabModules
],
),
),
// 侧边栏
drawer: Drawer(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.horizontal(right: Radius.circular(15.0))),
clipBehavior: Clip.antiAlias,
width: 300,
child: Container(
...
),
),
);
}
flutter3实现直播功能
// flutter3直播模块 Q:282310962
@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(
...
),
),
],
),
),
],
),
],
),
],
);
},
),
],
),
),
],
),
);
}
以上就是flutter3.27.1实战抖音app商城的一些知识分享,整个项目涉及到知识点蛮多。希望以上分享对小伙伴们有些帮助哈~~
往期热文
https://segmentfault.com/a/1190000045042968
https://segmentfault.com/a/1190000045245775
https://segmentfault.com/a/1190000045381943
https://segmentfault.com/a/1190000045556523
https://segmentfault.com/a/1190000045667190
作者:xiaoyan2017
链接: https://segmentfault.com/a/1190000046075489
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
原创自研flutter3.27+dart3.6
实战抖音短视频+聊天+直播电商带货app商城应用程序。
Flutter3.27仿抖音短视频+直播+聊天app商城系统
技术栈
- 编辑器: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首页左右滑动切换页面内容,上下滑动切换短视频效果。
项目框架
目前flutter3-douyin-mall短视频直播商城项目已经同步到我的原创作品集。
Flutter3.27仿抖音短视频+直播+聊天app商城系统
flutter3实现首页轮播图+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 Scaffold(
key: scaffoldKey,
extendBodyBehindAppBar: true,
appBar: AppBar(
forceMaterialTransparency: true,
backgroundColor: [0, 1, 4, 5].contains(videoModuleController.videoTabIndex.value) ? null : Colors.transparent,
foregroundColor: [0, 1, 4, 5].contains(videoModuleController.videoTabIndex.value) ? Colors.black : Colors.white,
titleSpacing: 1.0,
leading: Obx(() => IconButton(
icon: Badge.count(
backgroundColor: Colors.red,
count: 6,
child: Icon(Icons.sort_rounded, color: tabColor(),),
),
onPressed: () {
// 自定义打开右侧drawer
scaffoldKey.currentState?.openDrawer();
},
)),
title: Obx(() {
return ScrollConfiguration(
behavior: CustomScrollBehavior().copyWith(scrollbars: false),
child: TabBar(
...
),
);
}),
actions: [
Obx(() => IconButton(icon: Icon(Icons.search_rounded, color: tabColor(),), onPressed: () {},),),
],
),
body: ScrollConfiguration(
behavior: CustomScrollBehavior().copyWith(scrollbars: false),
child: PageView(
controller: pageController,
onPageChanged: (index) {
videoModuleController.updateVideoTabIndex(index);
setState(() {
tabController.animateTo(index, duration: Duration(milliseconds: 200), curve: Curves.easeInOut);
});
},
children: [
...tabModules
],
),
),
// 侧边栏
drawer: Drawer(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.horizontal(right: Radius.circular(15.0))),
clipBehavior: Clip.antiAlias,
width: 300,
child: Container(
...
),
),
);
}
flutter3实现直播功能
// flutter3直播模块 Q:282310962
@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(
...
),
),
],
),
),
],
),
],
),
],
);
},
),
],
),
),
],
),
);
}
以上就是flutter3.27.1实战抖音app商城的一些知识分享,整个项目涉及到知识点蛮多。希望以上分享对小伙伴们有些帮助哈~~
往期热文
https://segmentfault.com/a/1190000045042968
https://segmentfault.com/a/1190000045245775
https://segmentfault.com/a/1190000045381943
https://segmentfault.com/a/1190000045556523
https://segmentfault.com/a/1190000045667190
作者:xiaoyan2017
链接: https://segmentfault.com/a/1190000046075489
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。