嗨,正在掉头发的大家好,我是洋小洋,本集我们接着聊一下GooGle的“亲儿子”Flutter。那自从上篇文章分享以后,有一些掘友也发表了一些颇有意思的评论。那我们首先来回顾一下git
在这里挑选3位的评论,以为挺有趣,毕竟咱也不是设计师,这也不得不证实了一个产品的UI是多么的重要,固然也是随机在评论区,贴上他们的连接,也能够看看对方会不会有什么技术上的专栏,你们互相学习。以后的每一段路,我也都对从评论区贴上大家的奇葩评论github
掘金社区Flutter模块7天内热榜第1算法
掘金社区Flutter模块热门第3windows
掘金社区Flutter模块最新第8markdown
截止目前25赞10评论app
虽然我也不太喜欢掘金的搜索算法,据说更新了,期待愈来愈好,你们可以分享本身对于技术的探索框架
不知不觉一周又过去了,实际开发的过程当中仍是会有不少坑的,这个按部就班会和你们分享,包括像Provider和后台交互的流程等。Dio的企业化配置等。那在本集我们仍是画界面less
如图所示,仍是那么一个Low的界面,下面的内容可能会有点无聊,不过真的很肝,期待与你相遇async
谷歌开发的移动UI框架,能够快速在iOS和Android上构建高质量的原生用户界面 Flutter No.7ide
一些数据的指数
那因为一个APP 一上来就直接登陆页或者注册页。是有点生硬的,对用户来讲是极为不友好的,凡事都要慢慢来,有个过程不是吗?其实在闪屏的过程当中,是会作一些判断的,你如判断用户有没有登陆等
发现咱们并无提交更新
接着我们新建一个开发分支,用来记录新的一个章节,这个章节我们要作的是闪屏和引导页,如题
在上周的时候 咱们是经过在项目的根目录下flutter run
运行项目,而后R
与r
进行切换
本周我们借助Vscode
debug 调试模式
在评论区,有掘友提到,底部的导航也太大,其实咱们是已经适配过屏幕的不是吗?经过一个插件flutter_screenutil
,固然也能够采起其余的方式,好比MediaQuery
能够拿到widget
以及设备的的宽高
那么什么是全局变量呢, 全局变量就是单纯指会贯穿整个APP生命周期的变量,用于单纯的保存一些信息,或者封装一些全局工具和方法的对象。
咱们先打算新建一个global.dart
用来存放好比说经常使用的宽度、高度、以及字体大小
cd utils
copy nul > global.dart // 新建一个global.dart(windows下)
复制代码
import 'package:flutter_screenutil/flutter_screenutil.dart';
/// 页面常见的宽度与高度
// 宽度
double width100 = ScreenUtil.getInstance().setWidth(100);
// 高度
double height100 = ScreenUtil.getInstance().setHeight(100);
复制代码
接着咱们在底部的导航栏看下直接用咱们的变量,固然第一步仍是引入
import '../utils/global.dart';
复制代码
咱们来进行测试下,把上一段结尾我们引入的图片所有先删除,写上一段测试文字
当咱们重启以后,显然是能够的
咱们第一步仍是新建一个page页面,并命名为splash_screen_page
/// 闪屏的页面
import 'package:flutter/material.dart';
class SplashScreenPage extends StatelessWidget {
const SplashScreenPage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Text('闪屏页面'),
),
);
}
}
复制代码
而后在main.dart
引用并使用,这时咱们已经再也不引入底部的导航界面了
return MaterialApp(
debugShowCheckedModeBanner: false, // 去除调试
title: '孤岛',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SplashScreenPage()); // 这里使用引导页,也就是说当用户一进来的时候,是一个闪屏
}
复制代码
接着我们就写属于这个孤岛APP 闪屏页,首先了解下几个部件
这里咱们使用一下渐变 gradient
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
// 线性渐变 有个渐变的过程
Color.fromRGBO(0, 0, 0, 0.2),
Color.fromRGBO(0, 0, 0, 0.4)
],
begin: FractionalOffset.topCenter, // 顶部居中
end: FractionalOffset.bottomCenter)), //
复制代码
效果是这个样子的
这个时候应用的第一个页面即是闪屏页面,而后咱们写这个页面的主要内容
child: Container(
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 30),
),
//
Text('孤岛',
style: TextStyle(
fontSize: fontSize200, fontWeight: FontWeight.w600))
],
),
),
复制代码
这里注意,fontSize: fontSize200
咱们直接使用公共的global的声明定义好的大小就可
好了 跑一下
不尽如意的是,报了错误
The method '/' was called on null.
复制代码
这个问题很简单,实际上是咱们在使用屏幕适配的时候,并无初始化
显然这样就能够了,咱们接着插入一张图片,放在这儿就会好些了
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(assetName)
)
),
复制代码
放什么图片呢,就仍是放一张保守点的吧,感受她愈来愈不像《孤岛App》了
**图片资源来自B站UP主 **wlop- (若有侵权,请联系 Blog)
老规矩我们仍是须要在pubspec.yaml
中配置一下,闪屏静态时候的样子我们暂且这个样子
0215
还记得咱们上一段旅程有一块儿看过MaterialApp
的源码
const MaterialApp({
Key key,
this.navigatorKey,
this.home,
this.routes = const <String, WidgetBuilder>{}, // 咱们暂时会用到这个路由的配置
this.initialRoute,
this.onGenerateRoute,
this.onUnknownRoute,
this.navigatorObservers = const <NavigatorObserver>[],
this.builder,
this.title = '',
this.onGenerateTitle,
this.color,
this.theme,
this.darkTheme,
this.themeMode = ThemeMode.system,
this.locale,
this.localizationsDelegates,
this.localeListResolutionCallback,
this.localeResolutionCallback,
this.supportedLocales = const <Locale>[Locale('en', 'US')],
this.debugShowMaterialGrid = false,
this.showPerformanceOverlay = false,
this.checkerboardRasterCacheImages = false,
this.checkerboardOffscreenLayers = false,
this.showSemanticsDebugger = false,
this.debugShowCheckedModeBanner = true,
})
复制代码
主要目的即是当闪屏结束的时候,跳转到引导页面
return MaterialApp(
debugShowCheckedModeBanner: false, // 去除调试
title: '孤岛',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SplashScreenPage(),
routes: {
'guidePages': (context) {
return GuidePages(); // 跳转到引导页面
}
},
);
复制代码
设计一个计时器,用来等计时器结束的时候,跳转
/// 设计一个计时器,用来等计时器结束的时候,跳转
jumpPage(){
return Timer(duration, callback);
}
/// 源码实际上是这样的
factory Timer(Duration duration, void callback()) {
if (Zone.current == Zone.root) {
// No need to bind the callback. We know that the root's timer will
// be invoked in the root zone.
return Zone.current.createTimer(duration, callback);
}
return Zone.current
.createTimer(duration, Zone.current.bindCallbackGuarded(callback));
}
复制代码
因为以前我们是用的是StatelessWidget
也就是说咱们须要在一个时间调用页面跳转的方法暂时咱们改用有状态的部件StatefulWidget
,完整代码是这样
import 'dart:async';
/// 闪屏的页面
import 'package:flutter/material.dart';
import '../utils/global.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class SplashScreenPage extends StatefulWidget {
SplashScreenPage({Key key}) : super(key: key);
@override
_SplashScreenPageState createState() => _SplashScreenPageState();
}
class _SplashScreenPageState extends State<SplashScreenPage> {
/// 设计一个计时器,用来等计时器结束的时候,跳转
jumpPage() {
return Timer(Duration(milliseconds: 3000), () {
Navigator.pushReplacementNamed(context, 'guidePages');
});
}
@override
void initState() {
super.initState();
jumpPage();
}
@override
Widget build(BuildContext context) {
ScreenUtil.instance = ScreenUtil(width: 750, height: 1334)..init(context);
return Scaffold(
backgroundColor: Colors.white, // 背景色
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/splash_screen.jpg'),
fit: BoxFit.cover)), // 添加背景图片
child: Container(
child: Center(
child: SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 30),
),
Text('欢迎来到孤岛',
style: TextStyle(
fontSize: fontSize40,
color: Colors.white10,
fontWeight: FontWeight.w600)),
SizedBox(
height: height100,
),
Text('By 洋小洋',
style: TextStyle(
fontSize: fontSize40,
color: Colors.white10,
fontWeight: FontWeight.w600))
],
),
),
),
),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
// 线性渐变 有个渐变的过程
Color.fromRGBO(0, 0, 0, 0.2),
Color.fromRGBO(0, 0, 0, 0.5)
],
begin: FractionalOffset.topCenter, // 顶部居中
end: FractionalOffset.bottomCenter)), // 底部居中
),
));
}
}
复制代码
好了,咱们先阶段性的看下一块儿实现的效果
在走过了闪屏以后,咱们指望能有个引导页,顾名思义就是引导用户下一步下一步,这里我们采用第三方的包intro_views_flutter 2.8.0
截止目前包的版本是2.8.0
包名 | 传送 |
---|---|
intro_views_flutter | intro_views_flutter |
将此添加到包的pubspec.yaml文件中:
dependencies:
intro_views_flutter: ^2.8.0
复制代码
您能够从命令行安装软件包:
$ flutter pub get
复制代码
如今,在Dart代码中,您可使用:
import 'package:intro_views_flutter/intro_views_flutter.dart';
复制代码
一波流操做后,就能够是使用了,具体使用的方法仍是须要看一下API
属性 | 数据类型 | 描述 | 默认值 |
---|---|---|---|
pageColor | Color | 设置页面的颜色。 | Null |
mainImage | Image / Widget | 设置页面的主图像。 | Null |
title | Text / Widget | 设置页面的标题文本。 | Null |
body | Text / Widget | 设置页面的正文。 | Null |
iconImageAssetPath | String | 设置将在页面气泡中显示的图标图像路径。 | Null |
iconColor | Color | 设置页面气泡图标的颜色。 | Null |
bubbleBackgroundColor | Color | 设置页面气泡背景色。 | Colors.white / Color(0x88FFFFFF) |
textStyle | TextStyle | 为标题和正文设置TextStyle | title: color: Colors.white , fontSize: 50.0 body: color: Colors.white , fontSize: 24.0 |
titleTextStyle | TextStyle | 设置标题的TextStyle | color: Colors.white , fontSize: 50.0 |
bodyTextStyle | TextStyle | 为正文设置TextStyle | color: Colors.white , fontSize: 24.0 |
bubble | Widget | 为内部气泡设置自定义小部件 | null |
那我们就根据使用的小细则定义一个PageViewModel
PageViewModel(
pageColor: const Color(0xFF03A9F4),
// iconImageAssetPath: 'assets/air-hostess.png',
iconColor: Colors.pink,
bubbleBackgroundColor: Colors.pink,
// bubble: Image.asset('images/jiche.jpg'),
body: Text(
'这是属于你个人孤岛',
),
title: Text(
'No.1',
),
// titleTextStyle: TextStyle(fontFamily: 'MyFont', color: Colors.white),
// bodyTextStyle: TextStyle(fontFamily: 'MyFont', color: Colors.white),
mainImage: Container(
decoration:
BoxDecoration(border: Border.all(width: 1, color: Colors.red)),
child: Image.asset(
// 图片
'images/jiche.jpg',
height: width750,
width: height1314,
fit: BoxFit.cover,
// alignment: Alignment.center, // 居中显示
),
)),
复制代码
在images
文件夹我们又新增了几张图片,用于引导页的展现,图片素材有的是在这儿找的
那如今效果就差很少了,来一块儿看下
很高兴你能耐住性子看到这儿,尤为是在这个快节奏的生活和工做中,咱们在今天的这段旅程已经完成了两部分
写到如今已是凌晨2:35分了
因为这周看了下这个
又出去浪荡了一圈,不过也尚未断更,也算对本身的一个激励吧,因此也请你给个鼓励,评论点赞,固然是感受还行的话,说不定就出如今下一章节的[读读评论]
我是洋小洋,下回见,本节代码会同步更新仓库 github.com/yayxs/flutt…
--END