养小猫咪的伙伴来我的店铺逛逛吧!抖音商城搜索#早睡早起的猫咪小铺子

Flutter开发日常练习-小猫咪杂货店(新增动画和跳转抖音)_workersJiaDa的博客-CSDN博客URL Launcher是一个Flutter插件,它允许您的应用程序启动网络浏览器、地图应用程序、拨号器应用程序、邮件应用程序等。设定好每个图片的id,通过id作为 'Hero' 组件的标识,id不能重,否则会报错,在这两个页面中必须相同。给列表上的文字加了个缩放的提示动画,感觉很有意思,也有别的效果可以自己试一下。之前的练习加了个详情页面,然后跳转第三方页面抖音用户详情页面。跳转详情页添加了Hero的动画,共享元素过度。https://blog.csdn.net/zxc8890304/article/details/130317615

猫咪杂货铺项目持续更新中

APP设计思路的话改成猫咪百科好了,不会后端,数据源抓包,本地存着了

  1. 登录注册,个人信息添加本地存储修改
  2. 国际化版本
  3. 白天黑夜模式
  4. 购物车物品删除
  5. 下单到订单支付流程
  6. 工具类整理(字体大小,字体颜色,主题颜色等)
  7. 图片库工具处理
  8. webview页面拦截优化
  9. 整体性能优化
  10. 打包处理

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开发日常练习-小猫咪杂货店(新增欢迎页,广告页和侧滑页面)相关推荐

  1. 【DevFest 2020】嘉宾实录总结:《Flutter 开发日常》by 崔振平 孔想容 | 主会场

    排版:圆子 审核:溪客 11月22日,在上海,第 10 届 DevFest如约而至**.**我们与万名线上观众.1500+ 线下开发者.工程师,以及行业重磅嘉宾一起,尽享了一场技术盛宴! 在整场活动中 ...

  2. Flutter开发实战 高仿微信(二)发现页

    Flutter开发实战 高仿微信(二)发现页 Flutter开发实战 高仿微信(二)发现页 1.1 微信发现页面简述 1.2 APP框架优化 1.2.1 配置APP Logo和启动图片 1.2.2 配 ...

  3. Flutter开发日常练习-pageview滑动视图动画

    养小猫咪的伙伴来我的店铺逛逛吧!抖音商城搜索#早睡早起的猫咪小铺子 学着写一下滑动页面 pageview实现左右滑动视图 class SlidingContainer extends Stateful ...

  4. flutter git 拉不起来_「干货」Flutter开发环境配置备忘录

    为什么要用Flutter? 嗯,本篇文章不会讲,因为我认为想看这篇文章的应该已经下定决心要学习Flutter. Flutter开发环境支持安装在Windows.Mac OS和Linux下,区别在于Wi ...

  5. Flutter开发使用PlatformView显示iOS原生View(50)

    我们在使用Flutter开发跨平台开发移动APP时,会遇到Flutter的组件满足不了原生的效果,部分控件不如原生控件好用时,就想在Flutter 的Widget 中使用iOS原生View来组合实现良 ...

  6. [转载] flutter开发桌面程序_在开始使用Flutter开发应用程序之前要了解的5条提示

    参考链接: Python中的桌面通知程序 flutter开发桌面程序 1.始终取消您的流订阅: (1. Always cancel your stream subscription:) When I ...

  7. Flutter开发环境配置

    文章目录 前言 一.打开Flutter官网 二.安装和环境配置 1.查看中国网络环境下使用flutter这篇文章 2.Mac上设置 3.Windows上设置 4.AndroidStudio插件安装 前 ...

  8. Flutter 开发踩坑记录(干货总结)

    Flutter 太好学了!BUG 真的太少了!issues 只有 5000 多!也就那么亿点!简单得我都枯了!毕竟每次遇到问题,???????? 都是直接去找群里的法佬.低调.Alex 等几位大佬(? ...

  9. flutter开发小程序_为什么我认为Flutter是移动应用程序开发的未来

    flutter开发小程序 I dabbled a bit in Android and iOS development quite a few years back using Java and Ob ...

最新文章

  1. 「SAP技术」SAP 如何看序列号被包在哪些HU里?
  2. r语言 svm 大样本_r语言基于SVM模型的文本分类研究 附数据代码
  3. Cramer-Rao Lower Bound (CRLB) Simple Introduction
  4. mysql数据库表的连接查询_mysql数据库多表连接查询问题
  5. C#——《C#语言程序设计》实验报告——数据库编程——基于ADO.NET技术的数据库操作DEMO
  6. java 手势识别,AndroidStudio:手势识别
  7. einops包中的rearrange,reduce, repeat及einops.layers.torch中的Rearrange,Reduce。对高维数据的处理方式
  8. Inline Method(内联函数)
  9. Go语言中的单元测试及反向代理
  10. 【leetcode】 Unique Binary Search Trees (middle)☆
  11. 【牛客练习赛60:C】操作集锦(dp+子序列计数)
  12. CMMI4 培训计划
  13. 央企:中国航天建设集团2022年毕业生招聘
  14. JAVA基础知识之BufferedWriter流
  15. 怎样和求职者聊天_我如何学会欣赏求职者
  16. Mockito单元测试
  17. 为 Drupal 7 构建一个新主题
  18. 新手安卓开发详细教程
  19. java文件分割与合并
  20. 实验四:app内页面跳转

热门文章

  1. 八股总结(二)计算机网络与网络编程
  2. JVM笔记-性能监控与分析工具
  3. 免费APP内测分发托管平台,支持应用合并、内测分发、扫码下载,下载量安装量统计,版本记录和应用在线封装打包app
  4. 云服务器ECS常见的计费方式
  5. 上个厕所的功夫,搞懂MySQL事务隔离级别,Java学习视频百度云盘
  6. 对账 概念 - 账证核对,账账核对,账实核对,账表核对
  7. Java面试题-微服务
  8. padding不会撑开盒子的情况
  9. php copy函数 失败,wamp中的copy函数bug
  10. 浅谈Deferred(延迟对象)