Flutter应用框架搭建实现屏幕适配方案详解
晨晨dyj 人气:0原理
UI设计的时候一般会按照一个固定的尺寸进行设计,如 360 x 690
,实际设备分辨率可能是 Google Pixel: 1080 x 1920
、Google Pixel XL: 1440 x 2560
、iPhone 12 Pro Max: 1284 x 2778
等等。开发时如果直接按照设计图写死数值则会出现最后实现的效果跟设计效果不一致的情况。这个时候就可以用比例的方式来进行适配。
将设计图分为固定单位并给这个单位定义一个标识,例如就叫 w
,然后通过获取设备分辨率,使用设备真实宽度除以设计图宽度 ,就得到了 1w
代表的真实宽度:
1w = 设备真实宽度 / 设计图宽度
如设计图尺寸是 360 x 690
,则宽度为 360w
,真实设备宽度为 1080 则 1w = 1080 / 360 = 3
。
根据上面的算法,得到对应设备的 1w
的真实宽度:
Google Pixel: 1w = 1080 / 360 = 3
Google Pixel XL: 1w = 1440 / 360 = 4
iPhone 12 Pro Max: 1w = 1284 / 360 = 3.57
按照同样的算法,可以给高度定义一个单位为 h
, 得出对应设备的高度单位的真实值,如下:
Google Pixel: 1h = 1920 / 690 = 2.78
Google Pixel XL: 1h = 2560 / 690 = 3.71
iPhone 12 Pro Max: 1h = 2778 / 690 = 4.03
得到换算以后 w
、h
的真实值以后,开发过程中就可以使用其来设置 UI 控件的高、宽、间距等,使其最终呈现的效果无限接近设计图的效果。
开发过程中一般采用宽度来进行适配,控件高度要么自适应,要么也设置宽度的单位,然后整体高度根据内容自适应。但是如果有特殊需求也可以使用高度来进行适配,比如需求要求是 banner 占屏幕的 1/4 ,或者要求内容刚好一屏显示,这个时候设置控件的高度时就可以采用高度单位来进行适配。
基于上面的算法,在项目中就可以实现对应的适配方案了,但本着不重复造轮子的思想,项目开发中可以直接使用 flutter_screenutil 这个适配库。
推荐方法
直接使用ScreenUtil.init方法,传入屏幕尺寸、设计图尺寸和屏幕方向可以对flutter_screenutil进行初始化,代码如下:
ScreenUtil.init( BoxConstraints( maxWidth: MediaQuery.of(context).size.width, //屏幕宽度 maxHeight: MediaQuery.of(context).size.height, //屏幕高度 ), designSize: const Size(360, 690), // 设计图尺寸 orientation: Orientation.portrait); // 屏幕方向 )
使用这种方式只需要在使用flutter_screenutil前进行初始化即可,一般放在根路由即第一个页面加载的时候进行初始化。
注意:ScreenUtil.init不能够在MyApp中进行初始化,此时还没有加载MaterialApp无法使用MediaQuery.of(context)获取到屏幕的宽高。
初始化以后就可以使用flutter_screenutil提供的方法获取到适配后的数值进行使用了。
可以通过如下的api获取宽高以及字体的适配数值。
ScreenUtil().setWidth(540) //根据屏幕宽度适配尺寸 ScreenUtil().setHeight(200) //根据屏幕高度适配尺寸(一般根据宽度适配即可) ScreenUtil().radius(200) //根据宽度或高度中的较小者进行调整 ScreenUtil().setSp(24) //字体大小适配
传入的参数即为设计图上的大小。在实际使用中的示例如下:
Container( width: ScreenUtil().setWidth(200), height: ScreenUtil().setHeight(540), child: Text("Hello", style: TextStyle(fontSize: ScreenUtil().setSp(24)),), );
flutter_screenutil更简单的写法,使用dart扩展的num类型:
上面的每一个方法和下面的相对应:
ScreenUtil().setWidth(540) => 540.h ScreenUtil().setHeight(200) => 200.w ScreenUtil().radius(200) => 200.r ScreenUtil().setSp(24) => 24.sp
相应的修改之后的使用示例:
Container( width: 200.w, height: 540.h, child: Text("Hello", style: TextStyle(fontSize: 24.sp),), );
注意:1.w!=1.h除非屏幕的分辨率比例和设计图的比例一致,所以要设置正方形,切记使用相同的单位,如果设置相同的w和h,可能是长方形。
除了上面的4钟扩展属性以外,还提供了sm以及sw和sh
sm:取数值本身和sp的值较小的值,如:12.sm则取12和12.sp的值进行比较,取较小的值。
sw:screen width的缩写,表示的是屏幕宽度,作用是按照屏幕宽度比例返回值。如0.2sw则返回屏幕宽度的20%,1.sw则是整个屏幕宽度
sh:screen height的缩写,即屏幕高度,作用于sw类似,返回指定比例的屏幕高度值。如1.sh为整个屏幕的高度。
使用sp作为字体单位,默认是会随着系统字体缩放进行变化的,如果不想让字体随着系统的缩放进行变化,可以设置textScaleFactor为1.0来实现。项目中可对MaterialApp进行全局设置,或者对Text进行单独的设置。
全局设置:
MaterialApp( debugShowCheckedModeBanner: false, title: 'Flutter_ScreenUtil', theme: ThemeData( primarySwatch: Colors.blue, ), builder: (context, widget) { return MediaQuery( ///设置文字大小不随系统设置改变 data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), child: widget, ); }, home: HomePage(title: 'FlutterScreenUtil Demo'), ),
单独设置:
Text("text", textScaleFactor: 1.0)
加载全部内容