做移动应用开发,各个系统都自己的适配方案,比如Android可以用dp、sp来描述大小,IOS使用pt来描述。但是入手Flutter后,却发现我们要描述的widget的大小没有单位,比如
Container( width: 40, height: 40, ),
那么这个40到底是什么意思呢?px、dp或者dp,其实都不是。
二、了解的Flutter的尺寸测试手机信息:720 * 1080 320dpi。
运行以下测试代码
void main(){ runApp(MaterialApp( theme: ThemeData( primarySwatch: Colors.blue, ), home: Scaffold( appBar: AppBar( title: const Text('适配测试'), ), body: const Text('Hello world'), ), )); }
通过Flutter的DevTool查看:
可以看到这里的尺寸显示的是 w = 360.0,h = 540.0
下面修改我们的代码,水平添加6个 width为60的Contaniner:
void main(){ runApp(MaterialApp( theme: ThemeData( primarySwatch: Colors.blue, ), home: Scaffold( appBar: AppBar( title: const Text('适配测试'), ), body: Row( children: List.generate(6, (index) => Container( width: 60, height: 60, color: Color.fromARGB(255,Random().nextInt(255), Random().nextInt(255), Random().nextInt(255)), )) ), ), )); }
运行效果图:
刚好占据整个屏幕,下面哦我们通过DevTools看一下内部的布局情况:
通过这个图,我们能明确的看到每个Container的w = 60,h = 60;6个Container刚好占据360的宽度。
所以Flutter中的大小是逻辑像素,与设备的分辨率和密度相关。
比如720 * 1080 dpi为320的设备,与大小为360 * 540;在比如Iphone6,750 * 1334,大小为375 * 667;因此我们设置的大小实际上为独立的值。
了解Flutter的尺寸的意义后,在开中我们应该注意什么呢? 那就是适配问题;比如上面的代码在720 * 1080 dpi为320的设备上运行没有问题,那么换到 480 * 800 dpi为240设备上会出现什么情况呢?
提示已经超过了最大宽度。接下里通过DevTools都看一下内部的布局呢:
可以看出这里宽度变为了320,而我们每个Container的宽度是60,6个的总宽度360 > 320。
从上面的描述,我们可以看出Flutter的尺寸单位:是逻辑像素,和设备的 devicePixelRatio和分辨率相关
显然,若果我们不对某些widget的大小做适配,就可能达不到我们预期设计的效果,因此接下里我们要处理的就是适配问题了。
三、Flutter在移动端的适配方案适配和我们的设计稿相关,比如375 * 667的设计稿,上面一个图片大小为100 * 100,那么320 * 453的设备上,大小该是多少呢?这里做一个比例缩放就行了,320/375 ≈ 0.85 ,因此在320 * 453的设备上图片大小是85 * 85。这样就能够适配我们的屏幕了。如下图:
根据上面的原理描述,下面我们实现Flutter在移动端的适配:
新建一个size_fit.dart
class WTSizeFit { //物理尺寸宽度 static late double physicalWidth; //物理尺寸高度 static late double physicalHeight; //像素密度 static late double devicePixelRatio; /// ///屏幕像素相对宽度- ///比如:物理像素750*1334的iphone6 screenWidth则为375 ///720 * 1080的android设备,screenWidth为 360 /// static late double screenWidth; /// /// screenHeight和screenWidth对应 /// static late double screenHeight; static late double statusBarHeight; // static late double bottomBarHeight; /// /// 宽度缩放比 /// static late double widthScaleRatio; /// /// 设计稿宽度-使用像素 /// static late double _designWidth; static void initialize({double designWidth = 375}) { _designWidth = designWidth; physicalWidth = window.physicalSize.width; physicalHeight = window.physicalSize.height; devicePixelRatio = window.devicePixelRatio; screenWidth = physicalWidth / devicePixelRatio; screenHeight = physicalHeight / devicePixelRatio; statusBarHeight = window.padding.top / devicePixelRatio; bottomBarHeight = window.padding.bottom / devicePixelRatio; widthScaleRatio = screenWidth / _designWidth; } /// /// pt或者dp都可以使用该方法 /// static double dpToSize(num dp) => dp * widthScaleRatio; /// /// sp也使用dp的方式进行视适配 /// static double spToSize(num sp) => sp * widthScaleRatio;
这里根据平时移动端的开发经验,做宽度的适配就可以,高度可以不用考虑,其他场景可以根据该原理进行修改。
在开发中我们可以这样使用:
第一步:
MyApp的build方法中进行初始化:SizeFit.initialize();
第二步:
设置大小的地方按以下方式进行使用:
Container( width: SizeFit.dpToSize(60), height: SizeFit.dpToSize(60), )
总参考如下:
void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { SizeFit.initialize(); return MaterialApp( theme: ThemeData( primarySwatch: Colors.blue, ), home: const MainPage(), ); } } class MainPage extends StatelessWidget { const MainPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( body: Row( children: List.generate( 6, (index) => Container( width: SizeFit.dpToSize(60), height: SizeFit.dpToSize(60), color: Color.fromARGB(255, Random().nextInt(255), Random().nextInt(255), Random().nextInt(255)), ))), ); } }
这样做以后满足了我们的屏幕的适配,但是每次都调用SizeFit.dpToSize()有点麻烦,这里我们可以使用扩展方法:
extension SizeExtension on num{ double get dp => WTSizeFit.dpToSize(this); double get sp => WTSizeFit.spToSize(this); }
接下来按以下方式进行调用:
Container( width: 60.dp, height: 60.dp, )最后:
- 通过上面的描述,我们了解的flutter的尺寸的含义
- 如果不做适配,在不同的机型上,可能达不到预期的设计效果
- 了解适配的实现原理,提供适配方案
- 在pub.dev上面有其他的适配库,但是我们应该要了解适配问题以及适配方案的原理,这样后期可以根据需求随时定制。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)