Flutter开发日常练习-小猫咪杂货店(新增欢迎页,广告页和侧滑页面)
养小猫咪的伙伴来我的店铺逛逛吧!抖音商城搜索#早睡早起的猫咪小铺子
Flutter开发日常练习-小猫咪杂货店(新增动画和跳转抖音)_workersJiaDa的博客-CSDN博客URL Launcher是一个Flutter插件,它允许您的应用程序启动网络浏览器、地图应用程序、拨号器应用程序、邮件应用程序等。设定好每个图片的id,通过id作为 'Hero' 组件的标识,id不能重,否则会报错,在这两个页面中必须相同。给列表上的文字加了个缩放的提示动画,感觉很有意思,也有别的效果可以自己试一下。之前的练习加了个详情页面,然后跳转第三方页面抖音用户详情页面。跳转详情页添加了Hero的动画,共享元素过度。https://blog.csdn.net/zxc8890304/article/details/130317615
猫咪杂货铺项目持续更新中
APP设计思路的话改成猫咪百科好了,不会后端,数据源抓包,本地存着了
- 登录注册,个人信息添加本地存储修改
- 国际化版本
- 白天黑夜模式
- 购物车物品删除
- 下单到订单支付流程
- 工具类整理(字体大小,字体颜色,主题颜色等)
- 图片库工具处理
- webview页面拦截优化
- 整体性能优化
- 打包处理
sp_util 是个不错的工具类
flutter_screenutil
在使用的时候需要注册宽度和高度
class MyApp extends StatelessWidget {const MyApp({super.key});// This widget is the root of your application.@overrideWidget build(BuildContext context) {return ScreenUtilInit(designSize: const Size(375, 681),builder: (BuildContext context, Widget? child) => ChangeNotifierProvider(create: (context) => CarModel(),child: MaterialApp(debugShowCheckedModeBanner: false,theme: ThemeData(primarySwatch: Colors.blue,),home: const StartPage(),),),);}
}
webview_flutter
添加webview跳转
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:webview_flutter/webview_flutter.dart';class WebPage extends StatefulWidget {final String url;final String title;const WebPage({super.key, required this.url, required this.title});@overrideState<WebPage> createState() => _WebPageState(this.url, this.title);
}class _WebPageState extends State<WebPage> {final String url;final String title;late final WebViewController controller;_WebPageState(this.url, this.title);@overridevoid initState() {controller = WebViewController()..setJavaScriptMode(JavaScriptMode.unrestricted)..setBackgroundColor(const Color(0x00000000))..setNavigationDelegate(NavigationDelegate(onProgress: (int progress) {// Update loading bar.},onPageStarted: (String url) {},onPageFinished: (String url) {},onWebResourceError: (WebResourceError error) {},onNavigationRequest: (NavigationRequest request) {if (request.url.startsWith('https://pub.dev/')) {return NavigationDecision.prevent;}return NavigationDecision.navigate;},),)..loadRequest(Uri.parse(url));super.initState();}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(title),),body: Column(children: [Expanded(child: WebViewWidget(controller: controller),),],),);}
}
倒计时的广告,使用Timer来倒计时实现,
second_index是设定时间
设定时间自己修改,也可以服务端来修改
import 'dart:async';import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_cat_1/pages/intro_page.dart';
import 'package:flutter_cat_1/tools/tools.dart';
import 'package:flutter_cat_1/web/web_page.dart';
import 'package:google_fonts/google_fonts.dart';import '../main.dart';class WelcomePage extends StatefulWidget {const WelcomePage({super.key});@overrideState<WelcomePage> createState() => _WelcomePageState();
}class _WelcomePageState extends State<WelcomePage> {int second_index = 3;int timeIndex = 0;late Timer timer;@overridevoid initState() {super.initState();timer = Timer.periodic(Duration(milliseconds: 50),(sd) {setState(() {timeIndex += 1;if (timeIndex % 20 == 0) {second_index -= 1;}});if (timeIndex >= 100) {_openMain();}},);}@overrideWidget build(BuildContext context) {return Scaffold(body: Stack(alignment: Alignment.center,children: <Widget>[Container(width: MediaQuery.of(context).size.width,height: MediaQuery.of(context).size.height,child: Image.asset("assets/IMG_8050.png",fit: BoxFit.cover,),),Container(alignment: Alignment.bottomRight,child: Container(width: 50,height: 50,decoration: BoxDecoration(borderRadius: BorderRadius.circular(25),),alignment: Alignment.center,margin: const EdgeInsets.all(25),child: GestureDetector(onTap: () {_openMain();},child: Stack(children: <Widget>[Container(alignment: Alignment.center,child: CircularProgressIndicator(value: timeIndex / 100,strokeWidth: 2,),),Container(alignment: Alignment.center,child: Text("跳过",style: TextStyle(fontSize: 12,color: Colors.white,fontWeight: FontWeight.bold,),),),],),),),),Container(alignment: Alignment.center,child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[RichText(text: TextSpan(text: "Flutter开发日常练习",style: GoogleFonts.notoSerif(color: Colors.black,fontSize: 17,),children: [TextSpan(text: "-小猫咪杂货店",style: GoogleFonts.notoSerif(color: Colors.black,fontSize: 17,// decoration: TextDecoration.underline,// decorationColor: Colors.blue[800],)),],),textDirection: TextDirection.ltr,),SizedBox(height: 10,),RichText(text: TextSpan(text: 'CSDN关注',style: GoogleFonts.notoSerif(fontSize: 17,color: Colors.black,),children: [TextSpan(text: 'workersJiaDa',style: GoogleFonts.notoSerif(fontSize: 17,color: Colors.blue[800],decoration: TextDecoration.underline,decorationColor: Colors.blue[800],fontWeight: FontWeight.bold,),recognizer: TapGestureRecognizer()..onTap = () {timer.cancel();Navigator.of(context).push(MaterialPageRoute(builder: (context) => WebPage(url:"https://blog.csdn.net/zxc8890304",title: "workersJiaDa的博客"),),).then((value) => reGetTimer());}),],),),SizedBox(height: 10,),RichText(text: TextSpan(text: '抖音商城搜索',style: GoogleFonts.notoSerif(color: Colors.black,fontSize: 17,),children: [TextSpan(text: "早睡早起的猫咪小铺子",style: GoogleFonts.notoSerif(fontSize: 17,color: Colors.blue[800],decoration: TextDecoration.underline,decorationColor: Colors.blue[800],fontWeight: FontWeight.bold,),recognizer: TapGestureRecognizer()..onTap = () {// timer.cancel();launchURL('snssdk1128://user/profile/88486395468');},),],),),],),),],),);}void _openMain() {timer.cancel();Navigator.pushAndRemoveUntil(context,MaterialPageRoute(builder: (context) => const IntroPage(),),(route) => false);}void reGetTimer() {timer = Timer.periodic(Duration(milliseconds: 50),(sd) {setState(() {timeIndex += 1;if (timeIndex % 20 == 0) {second_index -= 1;}});if (timeIndex >= 100) {_openMain();}},);}
}
欢迎页的话是
flutter_swiper_plus
非常简陋,简单的实现效果,要重新优化修改
添加了isFirst的判断,第一次打开APP才会显示,
之前做过国际化的项目,海外的需求是
只要是进入欢迎页不点跳过或者进入APP,每次进入APP都会再进入欢迎页面
这样做的话判断的条件需要重新修改一下
import 'dart:isolate';import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'package:flutter_cat_1/welcome/welcome_page.dart';
import 'package:flutter_swiper_plus/flutter_swiper_plus.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:sp_util/sp_util.dart';class StartPage extends StatefulWidget {const StartPage({super.key});@overrideState<StartPage> createState() => _StartPageState();
}class _StartPageState extends State<StartPage> {bool _isLogin = false;bool _isFirst = false;bool _islastPage = false;int pageInt = 1;final List _welcomeList = ["welcome_1.png", "welcome_2.png", "welcome_3.png"];@overridevoid initState() {super.initState();_isFirst = SpUtil.getBool("first")!;if (_isFirst) {String? tokenStr = SpUtil.getString('token');_isLogin = (tokenStr == null || tokenStr.isEmpty) ? false : true;new Future.delayed(Duration(seconds: 0), () {Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => WelcomePage(),),(route) => false);});}}@overrideWidget build(BuildContext context) {return Container(color: Colors.white,height: ScreenUtil().screenHeight,child: Stack(children: [Swiper(itemBuilder: (context, index) {return Image.asset("assets/${_welcomeList[index]}",fit: BoxFit.cover,);},itemCount: _welcomeList.length,loop: false,onIndexChanged: (index) {pageInt = index + 1;if (index == _welcomeList.length - 1) {setState(() {_islastPage = true;});} else {setState(() {_islastPage = false;});}},),Container(width: 100,height: 40,alignment: Alignment.center,margin: EdgeInsets.only(left: ScreenUtil().screenWidth / 2 - 50,bottom: 40,top: ScreenUtil().screenHeight - 80,right: ScreenUtil().screenWidth / 2 - 50,),child: Text("$pageInt / 3",style: const TextStyle(color: Colors.white,fontSize: 30,fontWeight: FontWeight.bold,decoration: TextDecoration.none),),),Container(width: 100,height: 40,margin: EdgeInsets.only(left: ScreenUtil().screenWidth / 2 + 100,bottom: 40,top: ScreenUtil().screenHeight - 80,// right: ScreenUtil().screenWidth / 2 - 10,),// decoration: BoxDecoration(// border: Border.all(color: Colors.blue[900], width: 2),// borderRadius: BorderRadius.circular(8),// ),child: Center(child: TextButton(onPressed:() => _jumpWelcome(),// Navigator.push(context, MaterialPageRoute(// builder: (context) {// },// ));child: _islastPage? Text("立即进入",style: GoogleFonts.notoSerif(fontSize: 17,color: Colors.blue[700],fontWeight: FontWeight.bold),): Text("跳过",style: GoogleFonts.notoSerif(fontSize: 17,color: Colors.blue[700],fontWeight: FontWeight.bold),),),),)],),);}_jumpWelcome() {SpUtil.putBool('first',true);String? tokenStr = SpUtil.getString("token");_isLogin = (tokenStr == null || tokenStr.isEmpty) ? false : true;Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => WelcomePage(),),(route) => false);}
}
侧滑栏也是,比较简陋
import 'package:flutter/material.dart';
import 'package:flutter_cat_1/welcome/start_page.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';class DrawerPage extends StatelessWidget {const DrawerPage({super.key});@overrideWidget build(BuildContext context) {return Drawer(elevation: 300,child: Stack(children: <Widget>[Column(children: <Widget>[UserAccountsDrawerHeader(accountName: Text("铲屎官铲屎官铲屎官"),accountEmail: Text("饲养员饲养员饲养员"),currentAccountPicture: CircleAvatar(backgroundImage: AssetImage("assets/IMG_9406.png"),),arrowColor: Colors.red,onDetailsPressed: () {},decoration: BoxDecoration(boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.5),offset: Offset(10, 10),blurRadius: 45,spreadRadius: 0.0,),],image: DecorationImage(image: AssetImage("assets/IMG_0259.png",),fit: BoxFit.cover),),),Expanded(child: ListView(padding: EdgeInsets.symmetric(vertical: 10),children: <Widget>[ListTile(title: Text('个人中心'),),Divider(),ListTile(title: Text('我的小猫咪'),),Divider(),ListTile(title: Text("我的订单"),),Divider(),ListTile(title: Text("关于我们"),),Divider(),],),),],),Positioned(bottom: 20,right: 20,child: InkWell(child: Row(mainAxisAlignment: MainAxisAlignment.end,crossAxisAlignment: CrossAxisAlignment.end,children: <Widget>[GestureDetector(onTap: () => Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) {return StartPage();},), (route) => false),child: MenuItemButton(child: Column(children: const <Widget>[Icon(Icons.power_settings_new_outlined,color: Colors.red,),Text("退出登录",style: TextStyle(color: Colors.red,fontSize: 12,),),],)),),],),),),],),);}
}
DEMO地址
GitHub - HelloJiada/flutter_cat_1Contribute to HelloJiada/flutter_cat_1 development by creating an account on GitHub.https://github.com/HelloJiada/flutter_cat_1.git
Flutter开发日常练习-小猫咪杂货店(新增欢迎页,广告页和侧滑页面)相关推荐
- 【DevFest 2020】嘉宾实录总结:《Flutter 开发日常》by 崔振平 孔想容 | 主会场
排版:圆子 审核:溪客 11月22日,在上海,第 10 届 DevFest如约而至**.**我们与万名线上观众.1500+ 线下开发者.工程师,以及行业重磅嘉宾一起,尽享了一场技术盛宴! 在整场活动中 ...
- Flutter开发实战 高仿微信(二)发现页
Flutter开发实战 高仿微信(二)发现页 Flutter开发实战 高仿微信(二)发现页 1.1 微信发现页面简述 1.2 APP框架优化 1.2.1 配置APP Logo和启动图片 1.2.2 配 ...
- Flutter开发日常练习-pageview滑动视图动画
养小猫咪的伙伴来我的店铺逛逛吧!抖音商城搜索#早睡早起的猫咪小铺子 学着写一下滑动页面 pageview实现左右滑动视图 class SlidingContainer extends Stateful ...
- flutter git 拉不起来_「干货」Flutter开发环境配置备忘录
为什么要用Flutter? 嗯,本篇文章不会讲,因为我认为想看这篇文章的应该已经下定决心要学习Flutter. Flutter开发环境支持安装在Windows.Mac OS和Linux下,区别在于Wi ...
- Flutter开发使用PlatformView显示iOS原生View(50)
我们在使用Flutter开发跨平台开发移动APP时,会遇到Flutter的组件满足不了原生的效果,部分控件不如原生控件好用时,就想在Flutter 的Widget 中使用iOS原生View来组合实现良 ...
- [转载] flutter开发桌面程序_在开始使用Flutter开发应用程序之前要了解的5条提示
参考链接: Python中的桌面通知程序 flutter开发桌面程序 1.始终取消您的流订阅: (1. Always cancel your stream subscription:) When I ...
- Flutter开发环境配置
文章目录 前言 一.打开Flutter官网 二.安装和环境配置 1.查看中国网络环境下使用flutter这篇文章 2.Mac上设置 3.Windows上设置 4.AndroidStudio插件安装 前 ...
- Flutter 开发踩坑记录(干货总结)
Flutter 太好学了!BUG 真的太少了!issues 只有 5000 多!也就那么亿点!简单得我都枯了!毕竟每次遇到问题,???????? 都是直接去找群里的法佬.低调.Alex 等几位大佬(? ...
- flutter开发小程序_为什么我认为Flutter是移动应用程序开发的未来
flutter开发小程序 I dabbled a bit in Android and iOS development quite a few years back using Java and Ob ...
最新文章
- 「SAP技术」SAP 如何看序列号被包在哪些HU里?
- r语言 svm 大样本_r语言基于SVM模型的文本分类研究 附数据代码
- Cramer-Rao Lower Bound (CRLB) Simple Introduction
- mysql数据库表的连接查询_mysql数据库多表连接查询问题
- C#——《C#语言程序设计》实验报告——数据库编程——基于ADO.NET技术的数据库操作DEMO
- java 手势识别,AndroidStudio:手势识别
- einops包中的rearrange,reduce, repeat及einops.layers.torch中的Rearrange,Reduce。对高维数据的处理方式
- Inline Method(内联函数)
- Go语言中的单元测试及反向代理
- 【leetcode】 Unique Binary Search Trees (middle)☆
- 【牛客练习赛60:C】操作集锦(dp+子序列计数)
- CMMI4 培训计划
- 央企:中国航天建设集团2022年毕业生招聘
- JAVA基础知识之BufferedWriter流
- 怎样和求职者聊天_我如何学会欣赏求职者
- Mockito单元测试
- 为 Drupal 7 构建一个新主题
- 新手安卓开发详细教程
- java文件分割与合并
- 实验四:app内页面跳转