赞
踩
Flutter 开发 Android & IOS 启动页 splash pag
Flutter 启动页(闪屏页)具体实现和原理分析
Flutter启动流程和原理分析
iOS13 开始 苹果要放弃LaunchImage适配启动图 , 改为必须走LaunchScreen.sb来启动
所以在iOS端,启动图适配,要么使用LaunchScreen.sb 内嵌UIImageView +AutoLayout 来适配(依旧使用整图), 要么就采用 页面布局的方式, 来开发启动页,具体可以参考下面这个链接
iOS 13使用LaunchScreen.storyboard适配各尺寸启动图
Flutter 的启动顺序,或者说是启动过程
iOS和Android端的原理其实是一样的, Android的MainActivity继承了FlutterActivity,FlutterActivity又通过FlutterActivityDelegate实现了生命周期的代理, 就是创建一个View并通过MainActivity的onCreate方法去加载显示出来,
同样的, iOS端也在AppDelegate中处理, AppDelegate: FlutterAppDelegate
所以总结来说, Flutter 的启动顺序依然和RN 一样, 先是各自从原生的Launch启动, 这一部分是iOS/Android原生处理,属于冷启动过程(机器不行就会等待较长时间), 还没有涉及到Flutter部分, 如果不做处理,将会有白屏或者黑屏短暂出现,
直到到Flutter层页面被加载出来, 此时启动就算结束了
举个例子(不算恰当), App登录已超时,如果App启动后直接进入首页, 然后由于某些原因必须退出到登录页, 这样的交互显的不那么完美, 最好的是在启动前,就能从接口处得知登录状态, 若登录失效,就直接进入登录页面,未失效就直接进入首页进行业务处理,
所以,请求的过程放到Flutter的启动页, 会显得比较合适
1.首先因为启动图比较简单, 我这边就找UI给了2x/3x 的两个图, 分别在iOS原生层和Flutter层添加这两张图片作
(截图有点早, 其实这边包括后面Flutter , 都是讲图片居于底部居中的布局方式,此处就不另行截图了)
iOS端冷启动页面比较简单,就在LaunchScreen.sb中放一个UIImageView, 做好约束就可以了,我这边因为启动页比较简单, 就让UI切一张图即可,背景色到时候改成白色基本就看不出来了,
图片的填充模式记得选择 Aspect Fill 填充
一个插曲…
刚开始使用AS创建Flutter项目的时候, 它默认创建的android/iOS ,分别是Kotlin和swift 模式, 鉴于对kotlin的不熟悉, 需要换成java的版本, 所以可以删除掉项目文件夹下的 android 文件,然后再终端重新创建一下
查看一下Flutter 的命令行工具
ruby flutter create -h
可以看到, 创建的默认就是 swift/ kotlin , 需要切换的就可以切换一下
修改Android ruby create -a java .
修改iOS ruby create -i objc
切换过后,
创建好的文件就便是纯java的了, 当然一些文件和配置, 就需要重新设置了…
如上图部分, FLutter 会在 AndroidManifest.xml中指定好Launch启动页入口
<!-- Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual
gap between the end of Android's launch screen and the painting of
Flutter's first frame. -->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background"
/>
所以我们可以在launch_background.xml中进行编辑…
对了, 建议在编辑的时候用AS再单独打开android的工程, 不然直接用Flutter下的, 有点辅助显示和跳转都不支持…
一开始我还以为是哪里出了问题
<?xml version="1.0" encoding="utf-8"?><!-- Modify this file to customize your launch splash screen --> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@color/colorPrimaryDark" > </item> <!-- You can insert your own image assets here --> <!-- <item> <bitmap android:gravity="center" android:src="@mipmap/launch_image" /> </item> --> <item android:gravity="bottom" android:bottom="0pt" android:left="0pt" android:right="0pt"> <bitmap android:src="@drawable/launch_icon" /> </item> </layer-list>
这里我对于xxxhdppi没有放图… 其实后期可以补上…, 但是相应的, 我们也要在Flutter下的4x文件夹放置对应图片
最后的效果是:
直接上代码吧, LaunchScreen.dart 中的build部分
@override Widget build(BuildContext context) { // TODO: implement build return Container( width: DeviceUtils.screenW, height: DeviceUtils.screenH, color: Color(0xffffffff), child: Stack( alignment: AlignmentDirectional.bottomCenter, children: [ Positioned( child: Image.asset( ImagesPath.launch_icon, width: 750.px, height: 220.px, fit: BoxFit.fill, ), bottom: 60.px, ) ], )); }
怀疑1
iOS原生和Flutter加载的图片不一样?
为了方便分析 , 干脆图片添加了不同文字来区分,
发现在iPhone 8 plus 上, iOS原生的LaunchScreen添加的是3x图片, Flutter的启动页面添加的是2x图片
在Flutter 里面, 如下图, 我忘记去掉图片上面的@2x @3x, 导致Flutter只识别@2x图片, (果然Flutter是谷歌儿子, 玩法都是和安卓一样…), 我丢图的时候忘记修改名字了
同时, 我测试发现, 在src/img 下, 其实不必再放1x图片, 现在目前市面上主流手机都是2x图片起步, 所以我这样改造
pubspec.yaml中这样
# 感觉目前手机(比如iOS, 1x的图片几乎没必要再使用了,因此此处img目录下直接存放2x图片,3x,4x图片通配)
assets:
- src/img/
- src/img/3x/
- src/img/4x/
iOS层和Flutter层中加载的均是3x图了
但是… 问题没有解决
怀疑2
高度单位换算问题
目前,单位换算基于iPhone6 的宽度 375 pt , 而高度的换算部分也基于375.
怀疑是高度换算不准确, 于是, 修改高度换算代码, 用667 pt 来进行换算, 具体实现网上都有, 这边给出log
原图的pt 是375 * 110 pt
debugPrint(DeviceUtils.screenW.toString()); debugPrint(DeviceUtils.screenH.toString()); debugPrint(750.px.toString()); debugPrint(220.px.toString()); debugPrint(220.pxH.toString()); log iPhone8 flutter: 414.0 flutter: 736.0 flutter: 414.00000000000006 flutter: 121.44000000000001 220.px flutter: 121.37931034482759 220.pxH iPhoneXR flutter: 414.0 flutter: 896.0 flutter: 414.00000000000006 flutter: 121.44000000000001 flutter: 147.76611694152925
可以看到, 基于375 基于667 换算下来的高度几乎是一样的
(其实在 iPhone XR 上差异就大了)
问题依旧没有解决, 两个启动页面的图片高度还是有高度差异…
(测试发现 . 在iPhoneSE2, iPhoneX 是表现OK的)
然后我突然反应过来…
然后我突然反应过来…
然后我突然反应过来…
此处的图片高度, 根本就不能进行单位换算,
应该直接这样写
(目前这里因为只做了iOS侧, 所以先写110 , 代表110 pt)
Positioned(
child: Image.asset(
ImagesPath.launch_icon,
width: 750.px,
height: 110,
// height: 220.px,
fit: BoxFit.fill,
),
bottom: 0.pxH,
这个110 和iPhone8 下的121.440000 仅相差10, 也符合我看到的,两个launch页面图片有细微的高度差的描述…
至于为什么不能进行单位换算?
因为在iOS 的LaunchScreen中, 我添加了这张375*110的图片,图片的高度是固定的, 就是110pt, 或者说220px ,
此时我无论是基于375 还是基于667 的基础进行单位换算, 其数值在8 / XR等机型上的高度被计算修改过了( 121.440000 等),
反而 在 iPhone se2 这样的机器上, 换算出来的高度正好就是110
那什么地方需要用到换算?
其他正常布局使用单位换算都可以, 但是遇到这种特殊的情况, 或者一些在各个机型上需要同样高度的, 就不推荐进行单位换算…
明显看到图片挤压了,有点变形, 是因为设置图片的填充模式
fit: BoxFit.cover,
就可以了
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。