flutter 屏幕适配分析
算出一个rpx后,再将自己的size和rpx单位相乘即可: 比如100px的宽度:100 * 2 * rpx 在iPhone5上计算出的结果是84px 在iPhone6上计算出的结果是100px 在iPhone6plus上计算出的结果是110.4px。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。:物理像素与逻辑像素的比例,当像素比为
一、移动端屏幕适配概念
在flutter 应用中一般来说我们是没有用单位的,不像传统的开发用了px,rpx,pt,vw等等,但是在实际的开发过程中移动端不同的屏幕我们都需要做适配。在此,就引出三个概念:逻辑分辨率、物理分辨率与像素比。
物理分辨率:硬件所支持的,即设备分辨率,常常听到的1920,2k屏,物理像素固定,出厂设置好了。
逻辑分辨率(手机屏幕大小):软件通过算法达到的,flutter开发中我们用的就是这个逻辑分辨率。
像素比(dpr):物理像素与逻辑像素的比例,当像素比为1:1时,使用1个物理像素显示1个逻辑像素;当像素比为2:1时,使用4个物理像素(长2倍,宽2倍,乘起来就是4倍)显示1个逻辑像素
获取设备信息(通过MediaQuery)
- 报错分析:首先点击of方法进去
MediaQueryData必须要初始化好,不然你拿到的就是null
- 查看MediaQueryData具体是啥
初始化MediaQueryData实际上不是用的构造器函数,而是用的MediaQueryData.formWindow方法
- 具体看看怎么初始化的
只有等这个方法初始化完后,才能调用MediaQuery.of(context),所以要求执行顺序必须是:图五→图一才行,而按照现在的代码顺序却是图一到图五了,所以报错。可以打断点验证整个过程
import 'dart:ui';
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
//一般希望在应用程序启动就拿到手机的物理分辨率
final physicalWidth=window.physicalSize.width;
final physicalHeight=window.physicalSize.height;
print("手机物理分辨率:$physicalWidth*$physicalHeight");
//在这里通过媒体查询获取手机屏幕宽高(逻辑分辨率)会报错
// final screenWidth=MediaQuery.of(context).size.width;
// final screenHeight=MediaQuery.of(context).size.height;
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: "/",
routes: {
"/": (context) => MyHomePage(title: 'Flutter Demo Home Page'), //注册首页路由
},
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override
Widget build(BuildContext context) {
//放这里不会报错,因为已经初始化完成
final mediaQueryData=MediaQuery.of(context);
print(mediaQueryData);
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Column(
children: <Widget>[
Text('测试'),
]
),
));
}
}
如果要强行在刚刚报错的地方拿到屏幕宽高怎么办?
回头看源码,发现有这个代码:
size = window.physicalSize / window.devicePixelRatio
那么我们可以在报错的地方直接按照这个写法,跳过初始化的过程(此过程实际上就是用的也是window方法)。
解决方案:
// 获取dpr
final dpr=window.devicePixelRatio;
// 通过仿照源码方式获取手机屏幕宽高(逻辑分辨率)
final screenWidth= physicalWidth/dpr;
final screenHeight= physicalHeight/dpr;
// 同理也可以获取状态栏高度等其它参数
final statusHeight=window.padding.top/dpr;
二、Flutter屏幕适配可以采用小程序的rpx适配
rpx适配原理:
- 不管是什么屏幕,统一分成750份
- 在iPhone5上:1rpx = 320/750 = 0.4266 ≈ 0.42px
- 在iPhone6上:1rpx = 375/750 = 0.5px
- 在iPhone6plus上:1rpx = 414/750 = 0.552px
算出一个rpx后,再将自己的size和rpx单位相乘即可: 比如100px的宽度:100 * 2 * rpx 在iPhone5上计算出的结果是84px 在iPhone6上计算出的结果是100px 在iPhone6plus上计算出的结果是110.4px
封装一个适配的工具类
import 'dart:ui';
class ScreenUtil {
static double physicalWidth;
static double physicalHeight;
static double screenWidth;
static double screenHeight;
static double dpr;
static double statusHeight;
static double rpx;
static void initialize({double standardSize = 750}) {
// 1.手机的物理分辨率
physicalWidth = window.physicalSize.width;
physicalHeight = window.physicalSize.height;
print("宽高==$physicalWidth --- $physicalHeight");
// 2.获取dpr
dpr = window.devicePixelRatio;
// 3.宽度和高度
screenWidth = physicalWidth / dpr;
screenHeight = physicalHeight / dpr;
// 4.状态栏高度
statusHeight = window.padding.top / dpr;
// 5.计算rpx的大小
rpx = screenWidth / standardSize;
}
static px(int size) {
return rpx *2 * size;
}
}
工具类的使用
首先需要在入口main.dart初始化
import 'package:flutter/material.dart';
import 'package:flutter_learn/blog/utils/screen_fit.dart';
import 'home/home_page.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
ScreenUtil.initialize();
return MaterialApp(
title: 'Flutter widget',
debugShowCheckedModeBanner:false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
然后直接使用工具类
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("首页"),
),
body: Stack(
children: <Widget>[
Container(
width: ScreenUtil.px(200),
height: ScreenUtil.px(200),
color: Colors.red,
),
HomePageContent(),
],
));
}
}
文末福利
如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。
如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。
全套视频资料:
一、面试合集
二、源码解析合集
三、开源框架合集
欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓
更多推荐
所有评论(0)