目前移动端设备非常多,并且不同的设备手机屏幕也不相同。
目前做移动端开发都要针对不同的设备进行一定的匹配,无论是移动原生开发、小程序、H5页面
那么下面我们来学习下,Flutter中如何针对不同的手机屏幕来进行适配
在进行Flutter开发时,我们通常不需要传入尺寸的单位,那么Flutter使用的是什么单位呢?
在Flutter开发中我们使用的是对应的逻辑分辨率
获取屏幕上的一些信息,可以通过MediaQuery
//获取媒体查询信息对象
final mediaQueryData = MediaQuery.of(context);
//获取屏幕的宽度和高度
final kScreenWidth = mediaQueryData.size.width;
final kScreenHeight = mediaQueryData.size.height;
final phySicalWidth = window.physicalSize.width;
final phySicalHeight = window.physicalSize.height;
final dpr = window.devicePixelRatio;
print("屏幕的宽度===$kScreenWidth, 屏幕的高度===$kScreenHeight");
print("分辨率: phySicalWidth==$phySicalWidth, phySicalHeight===$phySicalHeight");
print("dpr=======$dpr");
// 3.状态栏的高度
// 有刘海的屏幕:44 没有刘海的屏幕为20
final statusBarHeight = mediaQueryData.padding.top;
// 有刘海的屏幕:34 没有刘海的屏幕0
final bottomHeight = mediaQueryData.padding.bottom;
print("状态栏height: $statusBarHeight 底部高度:$bottomHeight");
假如我们希望程序运行起来的开始就拿到这些屏幕的信息,我们在MyApp的build方法中写这样一段代码:
是说MediaQuery这个对象不存在,为什么会不存在了 我们可以去查看源码:
当我们在MyApp中的build方法获取MediaQuery
对象时, runApp方法还没有走完,MediaQuery
还没有创建
其实我们仔细的产看MediaQuery
的fromWindow
初始化方法,我们可以发现size对象是通过Window对象的某些属性计算来赋值,那我们完全可以绕过MediaQuery
对象直接使用window对象来获取我们需要的屏幕信息
如果还需要获取一些其它信息,我们可以参考上述源码,直接通过window来获取信息
获取一些设备相关信息,可以使用官方提供的一个库:
dependencies:
device_info: ^2.0.2
加入我们有下面这样一段代码
class GYHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Center(
child: Container(
width: 200,
height: 200,
color: Colors.red,
alignment: Alignment.center,
child: Text("Hello World", style: TextStyle(fontSize: 30, color: Colors.white),),
)
);
}
}
上面的代码在不同屏幕上会有不同的表现:
在前端开发中,针对不同的屏幕常见的适配方案有下面几种:
这里我采用小程序的rpx
来完成Flutter
的适配
最终我们把这个写代码封装成一个工具类(extension(扩展) + 单利 )来实现的
import 'dart:ui';
class GYSizeFit {
double phySicalWidth = 0;
double phySicalHeight = 0;
double screenWidth = 0;
double screenHeight = 0;
double dpr = 0;
double px = 0;
double statusBarHeight = 0;
double bottomHeight = 0;
//初始化
static void initialize() {
}
//工厂方法构造函数
factory GYSizeFit() => _getInstance();
//instance的getter方法
static GYSizeFit get instance => _getInstance();
//静态变量 _instace, 存储唯一对象
// 这里必须要使用? 声明可选值, 不然不可以赋值null
static GYSizeFit? _instance = null;
//获取对象
static GYSizeFit _getInstance() {
if (_instance == null) {
//使用私有构造方法来创建对象
_instance = GYSizeFit._internal();
}
return _instance!;
}
//私有的命名构造法方法 ,默认的构造方法将失效, 这样就隐藏了构造方法
//子类不能继承internal
//不是关键字,可定义其它名字
GYSizeFit._internal() {
// 初始化
//分辨率
phySicalWidth = window.physicalSize.width;
phySicalHeight = window.physicalSize.height;
// 屏幕宽高
screenWidth = window.physicalSize.width / window.devicePixelRatio;
screenHeight = window.physicalSize.height / window.devicePixelRatio;
//这里是以iphone6 为模板来适配的
dpr = screenWidth/750 ; // 像素点适配
px = screenWidth/750 * 2; // 物理宽度适配
//导航栏和底部工具栏的高度
statusBarHeight = window.padding.top;
bottomHeight = window.padding.bottom;
}
}
//给double写一个分类
extension sizeFit on double {
//使用像素适配大小
double dpx() {
return this * GYSizeFit.instance.dpr;
}
// 使用px(物理宽度适配)
double px() {
return this * GYSizeFit.instance.px;
}
}
所有设计到尺寸的都可以调用这个方法来适配