flutter 屏幕尺寸適配和字體大小適配的實(shí)現(xiàn)
前言:
現(xiàn)在的手機(jī)品牌和型號(hào)越來(lái)越多,導(dǎo)致我們平時(shí)寫布局的時(shí)候會(huì)在個(gè)不同的移動(dòng)設(shè)備上顯示的效果不同,
比如我們的設(shè)計(jì)稿一個(gè)View的大小是300px,如果直接寫300px,可能在當(dāng)前設(shè)備顯示正常,但到了其他設(shè)備可能就會(huì)偏小或者偏大,這就需要我們對(duì)屏幕進(jìn)行適配。
安卓原生的話有自己的適配規(guī)則,可以根據(jù)不同的尺寸建立不同的文件夾,系統(tǒng)會(huì)根據(jù)當(dāng)前的設(shè)備尺寸取對(duì)應(yīng)的大小的布局。而flutter本身并沒(méi)有適配規(guī)則,而原生的又比較繁瑣,這就需要我們自己去對(duì)屏幕進(jìn)行適配。
如果有幫助,請(qǐng)給我個(gè)star
flutter_ScreenUtil
flutter 屏幕適配方案
github: https://github.com/OpenFlutter/flutter_ScreenUtil
使用方法:
安裝依賴:
安裝之前請(qǐng)查看最新版本
dependencies: flutter: sdk: flutter # 添加依賴 flutter_screenutil: ^0.4.2
在每個(gè)使用的地方導(dǎo)入包:
import 'package:flutter_screenutil/flutter_screenutil.dart';
初始化設(shè)置尺寸
在使用之前請(qǐng)?jiān)O(shè)置好設(shè)計(jì)稿的寬度和高度,傳入設(shè)計(jì)稿的寬度和高度(單位px)
一定在MaterialApp的home中的頁(yè)面設(shè)置(即入口文件,只需設(shè)置一次),以保證在每次使用之前設(shè)置好了適配尺寸:
//設(shè)置適配尺寸 (填入設(shè)計(jì)稿中設(shè)備的屏幕尺寸) 假如設(shè)計(jì)稿是按iPhone6的尺寸設(shè)計(jì)的(iPhone6 750*1334) ScreenUtil.instance = ScreenUtil(width: 750, height: 1334)..init(context);
使用:
適配尺寸:
傳入設(shè)計(jì)稿的px尺寸:
根據(jù)屏幕寬度適配 width: ScreenUtil().setWidth(540),
根據(jù)屏幕高度適配 height: ScreenUtil().setHeight(200),
注意
高度也根據(jù)setWidth來(lái)做適配可以保證不變形(當(dāng)你想要一個(gè)正方形的時(shí)候)
setHeight方法主要是在高度上進(jìn)行適配, 在你想控制UI上一屏的高度與實(shí)際中顯示一樣時(shí)使用.
例如:
//長(zhǎng)方形: Container( width: ScreenUtil().setWidth(375), height: ScreenUtil().setHeight(200), ), //如果你想顯示一個(gè)正方形: Container( width: ScreenUtil().setWidth(300), height: ScreenUtil().setWidth(300), ),
適配字體:
ScreenUtil().setSp(28) //傳入字體大小,根據(jù)系統(tǒng)的“字體大小”輔助選項(xiàng)來(lái)進(jìn)行縮放 ScreenUtil().setSp(28,false) //傳入字體大小,不會(huì)根據(jù)系統(tǒng)的“字體大小”輔助選項(xiàng)來(lái)進(jìn)行縮放 for example: Text( 'My font size is 28px and will not change with the system.', style: TextStyle( color: Colors.black, fontSize: ScreenUtil().setSp(28, false) ) ),
其他相關(guān)api:
ScreenUtil.pixelRatio //設(shè)備的像素密度 ScreenUtil.screenWidth //設(shè)備寬度 ScreenUtil.screenHeight //設(shè)備高度 ScreenUtil.bottomBarHeight //底部安全區(qū)距離,適用于全面屏下面有按鍵的 ScreenUtil.statusBarHeight //狀態(tài)欄高度 劉海屏?xí)?單位px ScreenUtil.textScaleFactory //系統(tǒng)字體縮放比例 ScreenUtil().scaleWidth // 實(shí)際寬度的dp與設(shè)計(jì)稿px的比例 ScreenUtil().scaleHeight // 實(shí)際高度的dp與設(shè)計(jì)稿px的比例
//導(dǎo)入 import 'package:flutter_screenutil/flutter_screenutil.dart'; ... @override Widget build(BuildContext context) { //設(shè)置適配尺寸 (填入設(shè)計(jì)稿中設(shè)備的屏幕尺寸) 假如設(shè)計(jì)稿是按iPhone6的尺寸設(shè)計(jì)的(iPhone6 750*1334) ScreenUtil.instance = ScreenUtil(width: 750, height: 1334)..init(context); print('設(shè)備寬度:${ScreenUtil.screenWidth}'); //Device width print('設(shè)備高度:${ScreenUtil.screenHeight}'); //Device height print('設(shè)備的像素密度:${ScreenUtil.pixelRatio}'); //Device pixel density print( '底部安全區(qū)距離:${ScreenUtil.bottomBarHeight}'); //Bottom safe zone distance,suitable for buttons with full screen print( '狀態(tài)欄高度:${ScreenUtil.statusBarHeight}px'); //Status bar height , Notch will be higher Unit px print('實(shí)際寬度的dp與設(shè)計(jì)稿px的比例:${ScreenUtil().scaleWidth}'); print('實(shí)際高度的dp與設(shè)計(jì)稿px的比例:${ScreenUtil().scaleHeight}'); print( '寬度和字體相對(duì)于設(shè)計(jì)稿放大的比例:${ScreenUtil().scaleWidth * ScreenUtil.pixelRatio}'); print( '高度相對(duì)于設(shè)計(jì)稿放大的比例:${ScreenUtil().scaleHeight * ScreenUtil.pixelRatio}'); print('系統(tǒng)的字體縮放比例:${ScreenUtil.textScaleFactory}'); return new Scaffold( appBar: new AppBar( title: new Text(widget.title), ), body: new Center( child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[ Row( children: <Widget>[ Container( width: ScreenUtil().setWidth(375), height: ScreenUtil().setHeight(200), color: Colors.red, child: Text( '我的寬度:${ScreenUtil().setWidth(375)}dp', style: TextStyle( color: Colors.white, fontSize: ScreenUtil().setSp(12, false), ), ), ), Container( width: ScreenUtil().setWidth(375), height: ScreenUtil().setHeight(200), color: Colors.blue, child: Text('我的寬度:${ScreenUtil().setWidth(375)}dp', style: TextStyle( color: Colors.white, fontSize: ScreenUtil().setSp(12, false), )), ), ], ), Text('設(shè)備寬度:${ScreenUtil.screenWidth}px'), Text('設(shè)備高度:${ScreenUtil.screenHeight}px'), Text('設(shè)備的像素密度:${ScreenUtil.pixelRatio}'), Text('底部安全區(qū)距離:${ScreenUtil.bottomBarHeight}px'), Text('狀態(tài)欄高度:${ScreenUtil.statusBarHeight}px'), Text( '實(shí)際高度的dp與設(shè)計(jì)稿px的比例:${ScreenUtil().scaleHeight}', textAlign: TextAlign.center, ), Text( '實(shí)際高度的dp與設(shè)計(jì)稿px的比例:${ScreenUtil().scaleHeight}', textAlign: TextAlign.center, ), Text( '寬度和字體相對(duì)于設(shè)計(jì)稿放大的比例:${ScreenUtil().scaleWidth * ScreenUtil.pixelRatio}', textAlign: TextAlign.center, ), Text( '高度相對(duì)于設(shè)計(jì)稿放大的比例:${ScreenUtil().scaleHeight * ScreenUtil.pixelRatio}', textAlign: TextAlign.center, ), SizedBox( height: ScreenUtil().setHeight(100), ), Text('系統(tǒng)的字體縮放比例:${ScreenUtil.textScaleFactory}'), Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text('我的文字大小在設(shè)計(jì)稿上是14px,不會(huì)隨著系統(tǒng)的文字縮放比例變化', style: TextStyle( color: Colors.black, fontSize: ScreenUtil().setSp(14, false))), Text('我的文字大小在設(shè)計(jì)稿上是14px,會(huì)隨著系統(tǒng)的文字縮放比例變化', style: TextStyle( color: Colors.black, fontSize: ScreenUtil().setSp(14))), ], ) ], ), ), ); }
使用示例:
適配原理
說(shuō)一下適配方案, 比如我們?cè)O(shè)計(jì)師設(shè)計(jì)的UI是根據(jù)Iphone6來(lái)做的,我們知道 iPhone6的分辨率是750*1334(px),
又或者是根據(jù)hdpi的設(shè)備來(lái)設(shè)計(jì)的UI,我們知道hdpi的 Android設(shè)備是 (240 dpi),像素密度是1.5,即hdpi設(shè)備的分辨率寬度是320px, 總之,無(wú)論設(shè)計(jì)稿的單位是px,或者是dp,我們都能夠轉(zhuǎn)換成px.
那么我們?nèi)绻鶕?jù)px來(lái)適配,ios和 android 就都可以兼容了.
假設(shè),我們的設(shè)計(jì)稿手機(jī)是10801920 px.
設(shè)計(jì)稿上有一個(gè)540960 的組件, 即寬度和寬度是手機(jī)的一半. 如果我們直接寫的時(shí)候組件的尺寸這么定義,在其他尺寸的設(shè)備上未必是一半,或多,或少. 但是我們可以按比例來(lái)看,即我們要實(shí)現(xiàn)的寬度是實(shí)際設(shè)備的一半.
那么假設(shè)我們?cè)O(shè)備的寬度是deviceWidth和deviceHeight , 我們要寫的組件大小為: 寬:(540/1080)*deviceWidth,高度: (960/1920)*deviceHeight.
通過(guò)這個(gè)公式我們可以發(fā)現(xiàn),我們要寫的組件寬度就是設(shè)計(jì)稿上的尺寸width*(deviceWdith/原型設(shè)備寬度).那么每次我們寫ui的時(shí)候,只要直接哪來(lái)設(shè)計(jì)稿的尺寸*(deviceWdith/設(shè)備原型)寬度即可.
原理就是先獲取,實(shí)際設(shè)備與原型設(shè)備的尺寸比例.
首先f(wàn)lutter獲取設(shè)備的尺寸的代碼是:
以下數(shù)據(jù)為我的手機(jī)數(shù)據(jù):
import 'dart:ui'; //因?yàn)閣indow是dart:ui中提供的,所以需要引入這個(gè)包. window.physicalSize //Size(1080.0, 1794.0) 單位px width = window.physicalSize.width //寬度 height = window.physicalSize.height //高度 //使用這個(gè)方法則無(wú)需引入包 MediaQuery.of(context).size //Size(411.4, 683.4) 單位:dp widhtDp = MediaQuery.of(context).size.width //寬度 411.4 heightDp = MediaQuery.of(context).size.height //高度 683.4
設(shè)計(jì)稿單位是px,且尺寸為1080*1920 px 時(shí):
scaleWidth = width / 1080; scaleHeight = height / 1920;
那么我們要寫尺寸為500100控件的寬度就是 500scaleWidth .100*scaleHeigh ,注意這時(shí)單位是px,flutter中默認(rèn)組件尺寸單位都是dp,我們還要進(jìn)行px->dp的操作.除以像素密度就好了.
flutter獲取像素密度的方法:
MediaQuery.of(context).devicePixelRatio window.physicalSize
上面兩種方法得到的是一樣的結(jié)果,但是window對(duì)象來(lái)自dart:ui,所以我們引入這個(gè)包:
import ‘dart:ui';
設(shè)計(jì)稿單位是dp,且尺寸為360*640 dp 時(shí):
scaleWidth = widhtDp / 360; scaleHeight = heightDp / 640;
那么我們要寫尺寸為500*100控件的寬度就是 500*scaleWidth .100*scaleHeigh
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android中wifi與數(shù)據(jù)流量的切換監(jiān)聽詳解
本文主要介紹了Android中wifi與數(shù)據(jù)流量的切換監(jiān)聽的方法步驟。具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-01-01Android動(dòng)態(tài)表格的實(shí)現(xiàn)代碼(內(nèi)容、樣式可擴(kuò)縮)
這篇文章主要介紹了Android動(dòng)態(tài)表格的實(shí)現(xiàn)代碼(內(nèi)容、樣式可擴(kuò)縮),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09Android實(shí)現(xiàn)多線程下載圖片的方法
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)多線程下載圖片的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09Android開發(fā)之彈出軟鍵盤工具類簡(jiǎn)單示例
這篇文章主要介紹了Android開發(fā)之彈出軟鍵盤工具類,結(jié)合實(shí)例形式分析了Android彈出軟鍵盤及獲取焦點(diǎn)的簡(jiǎn)單操作技巧,需要的朋友可以參考下2018-01-01Flutter?頁(yè)面跳轉(zhuǎn)和傳值的實(shí)現(xiàn)
跳轉(zhuǎn)傳值是再普通不過(guò)的小功能了,在開發(fā)中會(huì)經(jīng)常用到,比如列表進(jìn)入詳情,本文主要介紹了Flutter?頁(yè)面跳轉(zhuǎn)和傳值的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-04-04dialog dismiss時(shí)鍵盤不消失的問(wèn)題淺析及解決辦法
這篇文章主要介紹了dialog dismiss時(shí)鍵盤不消失的問(wèn)題淺析及兩種解決方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下2017-01-01android studio 一直卡在Gradle:Build Running的幾種解決辦法
這篇文章主要介紹了android studio 一直卡在Gradle:Build Running的解決辦法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-10-10Android Jetpack組件庫(kù)LiveData源碼深入探究
LiveData是Jetpack組件的一部分,更多的時(shí)候是搭配ViewModel來(lái)使用,相對(duì)于Observable,LiveData的最大優(yōu)勢(shì)是其具有生命感知的,換句話說(shuō),LiveData可以保證只有在組件( Activity、Fragment、Service)處于活動(dòng)生命周期狀態(tài)的時(shí)候才會(huì)更新數(shù)據(jù)2022-09-09談?wù)凙ndroid Fragments 詳細(xì)使用
本篇文章主要介紹了Android Fragments 詳細(xì)使用,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12XrecyclerView實(shí)現(xiàn)加載數(shù)據(jù)和切換不同布局
這篇文章主要為大家詳細(xì)介紹了XrecyclerView實(shí)現(xiàn)加載數(shù)據(jù)、切換不同布局功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12