Flutter小技巧總結之flutter 適配寬高,字體


一,前言:

  現在的手機品牌和型號越來越多,導致我們平時寫布局的時候會在個不同的移動設備上顯示的效果不同,比如我們的設計稿一個View的大小是300px,如果直接寫300px,可能在當前設備顯示正常,但到了其他設備可能就會偏小或者偏大,這就需要我們對屏幕進行適配。

  安卓原生的話有自己的適配規則,可以根據不同的尺寸建立不同的文件夾,系統會根據當前的設備尺寸取對應的大小的布局。而flutter本身並沒有適配規則,而原生的又比較繁瑣,這就需要我們自己去對屏幕進行適配。

二,flutter_ScreenUtil

  • flutter 屏幕適配方案
    github: https://github.com/OpenFlutter/flutter_ScreenUtil
  • 使用方法:
    • 安裝依賴:
      安裝之前請查看最新版本
      dependencies:
        flutter:
          sdk: flutter
        # 添加依賴
        flutter_screenutil: ^0.4.2
    • 在每個使用的地方導入包:
      import 'package:flutter_screenutil/flutter_screenutil.dart';
    • 初始化設置尺寸

       在使用之前請設置好設計稿的寬度和高度,傳入設計稿的寬度和高度(單位px)

      一定在MaterialApp的home中的頁面設置(即入口文件,只需設置一次),以保證在每次使用之前設置好了適配尺寸:

      //設置適配尺寸 (填入設計稿中設備的屏幕尺寸) 假如設計稿是按iPhone6的尺寸設計的(iPhone6 750*1334)

      ScreenUtil.instance = ScreenUtil(width: 750, height: 1334)..init(context);
  • 使用:
    • 適配尺寸:

      傳入設計稿的px尺寸:

      根據屏幕寬度適配 width: ScreenUtil().setWidth(540),

      根據屏幕高度適配 height: ScreenUtil().setHeight(200),

      • 注意

        高度也根據setWidth來做適配可以保證不變形(當你想要一個正方形的時候)

        setHeight方法主要是在高度上進行適配, 在你想控制UI上一屏的高度與實際中顯示一樣時使用.

      • 例如:

        //長方形:
        Container(
        width: ScreenUtil().setWidth(375),
        height: ScreenUtil().setHeight(200),
        ),
        
        //如果你想顯示一個正方形:
        Container(
        width: ScreenUtil().setWidth(300),
        height: ScreenUtil().setWidth(300),
        ),
    • 適配字體

       ScreenUtil().setSp(28)         //傳入字體大小,根據系統的“字體大小”輔助選項來進行縮放
       ScreenUtil().setSp(28false)  //傳入字體大小,不會根據系統的“字體大小”輔助選項來進行縮放
      
      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) 
                       )
                ),
    • 其他相關api:
      ScreenUtil.pixelRatio //設備的像素密度
      ScreenUtil.screenWidth //設備寬度
      ScreenUtil.screenHeight //設備高度
      ScreenUtil.bottomBarHeight //底部安全區距離,適用於全面屏下面有按鍵的
      ScreenUtil.statusBarHeight //狀態欄高度 劉海屏會更高 單位px
      ScreenUtil.textScaleFactory //系統字體縮放比例
      
      ScreenUtil().scaleWidth // 實際寬度的dp與設計稿px的比例
      ScreenUtil().scaleHeight // 實際高度的dp與設計稿px的比例
      //導入
      import 'package:flutter_screenutil/flutter_screenutil.dart';
      
      ...
      
        @override
        Widget build(BuildContext context) {
          //設置適配尺寸 (填入設計稿中設備的屏幕尺寸) 假如設計稿是按iPhone6的尺寸設計的(iPhone6 750*1334)
          ScreenUtil.instance = ScreenUtil(width: 750, height: 1334)..init(context);
          print('設備寬度:${ScreenUtil.screenWidth}'); //Device width
          print('設備高度:${ScreenUtil.screenHeight}'); //Device height
          print('設備的像素密度:${ScreenUtil.pixelRatio}'); //Device pixel density
          print(
              '底部安全區距離:${ScreenUtil.bottomBarHeight}'); //Bottom safe zone distance,suitable for buttons with full screen
          print(
              '狀態欄高度:${ScreenUtil.statusBarHeight}px'); //Status bar height , Notch will be higher Unit px
      
          print('實際寬度的dp與設計稿px的比例:${ScreenUtil().scaleWidth}');
          print('實際高度的dp與設計稿px的比例:${ScreenUtil().scaleHeight}');
      
          print(
              '寬度和字體相對於設計稿放大的比例:${ScreenUtil().scaleWidth * ScreenUtil.pixelRatio}'); 
          print(
              '高度相對於設計稿放大的比例:${ScreenUtil().scaleHeight * ScreenUtil.pixelRatio}'); 
          print('系統的字體縮放比例:${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('設備寬度:${ScreenUtil.screenWidth}px'),
                  Text('設備高度:${ScreenUtil.screenHeight}px'),
                  Text('設備的像素密度:${ScreenUtil.pixelRatio}'),
                  Text('底部安全區距離:${ScreenUtil.bottomBarHeight}px'),
                  Text('狀態欄高度:${ScreenUtil.statusBarHeight}px'),
                  Text(
                    '實際高度的dp與設計稿px的比例:${ScreenUtil().scaleHeight}',
                    textAlign: TextAlign.center,
                  ),
                  Text(
                    '實際高度的dp與設計稿px的比例:${ScreenUtil().scaleHeight}',
                    textAlign: TextAlign.center,
                  ),
                  Text(
                    '寬度和字體相對於設計稿放大的比例:${ScreenUtil().scaleWidth * ScreenUtil.pixelRatio}',
                    textAlign: TextAlign.center,
                  ),
                  Text(
                    '高度相對於設計稿放大的比例:${ScreenUtil().scaleHeight * ScreenUtil.pixelRatio}',
                    textAlign: TextAlign.center,
                  ),
                  SizedBox(
                    height: ScreenUtil().setHeight(100),
                  ),
                  Text('系統的字體縮放比例:${ScreenUtil.textScaleFactory}'),
                  Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      Text('我的文字大小在設計稿上是14px,不會隨着系統的文字縮放比例變化',
                          style: TextStyle(
                              color: Colors.black,
                              fontSize: ScreenUtil().setSp(14, false))),
                      Text('我的文字大小在設計稿上是14px,會隨着系統的文字縮放比例變化',
                          style: TextStyle(
                              color: Colors.black, fontSize: ScreenUtil().setSp(14))),
                    ],
                  )
                ],
              ),
            ),
          );
        }
    • 使用示例:
      example demo
    • 適配原理:
      • 說一下適配方案, 比如我們設計師設計的UI是根據Iphone6來做的,我們知道 iPhone6的分辨率是750*1334(px),
        又或者是根據hdpi的設備來設計的UI,我們知道hdpi的 Android設備是 (240 dpi),像素密度是1.5,即hdpi設備的分辨率寬度是320px, 總之,無論設計稿的單位是px,或者是dp,我們都能夠轉換成px.
        那么我們如果根據px來適配,ios和 android 就都可以兼容了.

      • 假設,我們的設計稿手機是10801920 px.
        設計稿上有一個540960 的組件, 即寬度和寬度是手機的一半. 如果我們直接寫的時候組件的尺寸這么定義,在其他尺寸的設備上未必是一半,或多,或少. 但是我們可以按比例來看,即我們要實現的寬度是實際設備的一半.
        那么假設我們設備的寬度是deviceWidth和deviceHeight , 我們要寫的組件大小為: 寬:(540/1080)*deviceWidth,高度: (960/1920)*deviceHeight.

      • 通過這個公式我們可以發現,我們要寫的組件寬度就是設計稿上的尺寸width*(deviceWdith/原型設備寬度).那么每次我們寫ui的時候,只要直接哪來設計稿的尺寸*(deviceWdith/設備原型)寬度即可.

      • 原理就是先獲取,實際設備與原型設備的尺寸比例.
        首先flutter獲取設備的尺寸的代碼是:

        以下數據為我的手機數據:

        以下數據為我的手機數據:
        
        import 'dart:ui';
        //因為window是dart:ui中提供的,所以需要引入這個包.
        window.physicalSize  //Size(1080.0, 1794.0)  單位px
        width =  window.physicalSize.width  //寬度
        height =  window.physicalSize.height  //高度
        
        //使用這個方法則無需引入包
        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

        設計稿單位是px,且尺寸為1080*1920 px 時:

        scaleWidth = width  / 1080;
        scaleHeight = height / 1920;

        那么我們要寫尺寸為500100控件的寬度就是 500scaleWidth .100*scaleHeigh ,注意這時單位是px,flutter中默認組件尺寸單位都是dp,我們還要進行px->dp的操作.除以像素密度就好了.
        flutter獲取像素密度的方法:

        MediaQuery.of(context).devicePixelRatio
        window.physicalSize     

        上面兩種方法得到的是一樣的結果,但是window對象來自dart:ui,所以我們引入這個包:

        import ‘dart:ui’;

        設計稿單位是dp,且尺寸為360*640 dp 時:

        scaleWidth = widhtDp / 360;
        scaleHeight = heightDp / 640;
        //那么我們要寫尺寸為500*100控件的寬度就是 500*scaleWidth .100*scaleHeigh 

         








 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM