likes
comments
collection
share

Flutter 在不同屏幕上尺寸适配

作者站长头像
站长
· 阅读数 3

Flutter屏幕尺寸适配

前言

现代手机屏幕尺寸各不相同,导致我们平时写布局的时候会在个不同的移动设备上显示的效果不同。为了达到一套代码所有手机体验一致效果,需要做尺寸上的适配。

本文将花费你3分钟时间,快速讲解如何适配

近期iphone的尺寸表

设备名称操作系统尺寸 inPPI纵横比宽 x 高 dp宽 x 高 px密度 dpi
iPhone 13 Pro MaxiOS6.745819 : 9428 x 9261284 x 27783.0 xxhdpi
iPhone 13 ProiOS6.146019 : 9390 x 8441170 x 25323.0 xxhdpi
iPhone 13iOS6.146019 : 9390 x 8441170 x 25323.0 xxhdpi
iPhone 13 miniiOS5.447619 : 9360 x 7801080 x 23403.0 xxhdpi
iPhone 12 Pro MaxiOS6.745819 : 9428 x 9261284 x 27783.0 xxhdpi
iPhone 12 ProiOS6.146019 : 9390 x 8441170 x 25323.0 xxhdpi
iPhone 12 MiniiOS5.447619 : 9360 x 7801080 x 23403.0 xxhdpi
iPhone 11 ProiOS5.845819 : 9375 x 8121125 x 24363.0 xxhdpi
iPhone 11 Pro MaxiOS6.545819 : 9414 x 8961242 x 26883.0 xxhdpi
iPhone 11 (11,XR)iOS6.132619 : 9414 x 896828 x 17922.0 xhdpi

实现方法

如何实现在不同屏幕上展示相同比例大小?

举例,设计师给了一个iphone13作为标准尺寸的设计图,此时有一个logo是50*50的正方形,在iphone11的屏幕上我们应该变成多少尺寸才能保持比例相同?

50/390=x/375

x=50/390*375=48.076923...

x=50*(375/390)

在求值时,375/390往往时固定的,于是我们讲375/390也就当前屏幕宽度/设计稿屏幕宽度 记做横向ratio。每次我们想知道设计图上一个值在用户设备上的值为多少,只需乘以这个ratio。

计算公式:实际尺寸 = UI尺寸 * 设备宽度/设计图宽度

import 'dart:math';

import 'package:flutter/material.dart';
// import 'package:flutter_screenutil/flutter_screenutil.dart';

class SizeConfig {
  static MediaQueryData _mediaQueryData;
  /// 设备宽度
  static double screenWidth = 0;
  /// 设备高度
  static double screenHeight = 0;
  /// 方向
  static Orientation orientation;
  /// 设计图宽度
  static double inputHeight = 390;
  /// 设计图宽度
  static double inputWidth = 844;
  static EdgeInsets padding;

  /// The ratio of actual height to UI design
  static double get scaleWidth => screenWidth / inputWidth;

  static double get scaleHeight => screenHeight / inputHeight;

  static double get scaleText => min(scaleWidth, scaleHeight);
	
  /// 在使用前应当初始化他,
  static void init(BuildContext context, double w, double h) {
    inputWidth = w;
    inputHeight = h;
    _mediaQueryData = MediaQuery.of(context);
    screenWidth = _mediaQueryData.size.width;
    screenHeight = _mediaQueryData.size.height;
    orientation = _mediaQueryData.orientation;
    padding = _mediaQueryData.padding;
  }
}

// Get the proportionate height as per screen size
double getProportionateScreenWidth(num inputWidth) {
  return inputWidth * SizeConfig.scaleWidth;
}

// Get the proportionate height as per screen size
double getProportionateScreenHeight(num inputHeight) {
  return inputHeight * SizeConfig.scaleHeight;
}


扩展

参考flutter_screenutil对num进行扩展,可以不用写一长串方法名,直接使用1.2.w,1.h,1.r这样的形式 无需引入这个库,你只需复制这两段代码,在你的utils目录下建个文件,引用即可


/// 对num进行扩展,可直接使用1.2.w的形式代替getProportionateScreenWidth(1.2)
extension SizeExtension on num {
  ///[ScreenUtil.setWidth]
  double get w => getProportionateScreenWidth(this);

  ///[ScreenUtil.setHeight]
  double get h => getProportionateScreenHeight(this);

  ///[ScreenUtil.radius]
  double get r => this * SizeConfig.scaleText;

  ///屏幕宽度的倍数
  ///Multiple of screen width
  double get sw => SizeConfig.screenWidth * this;

  ///屏幕高度的倍数
  ///Multiple of screen height
  double get sh => SizeConfig.screenHeight * this;
}

知识点

屏幕尺寸

严格来说,屏幕尺寸实际被物理尺寸和显示分辨率两个部分定义。而我们今天对各类手机、Pad 设备所说的屏幕尺寸,只指物理尺寸。如果一块手机屏幕的物理尺寸是 5.0 英寸,即是指该手机屏幕对角线的长度。

屏幕分辨率

屏幕分辨率是指屏幕图像的精密度,是显示器所能显示的像素的具体数值。 如一个手机标称分辨率是 400 x 800,即表示屏幕横向由 400 个像素点组成,纵向由 800 个像素点组成。由于屏幕上的点、线和面都是由像素组成的,屏幕具备的像素点越多,画面就越精细。分辨率越高,单位面积内显示的信息就越多,我们能看到的内容就越多。

屏幕比例

屏幕比例是指屏幕的宽度与高度的比例,今天更多指分辨率的比例,即 屏幕比例 = 屏幕横向分辨率 / 屏幕纵向分辨率 此外,在各类设备、平台之间也有一些比较常用的比例,同时也推荐大家在开发对应设置或平台的应用时使用推荐比例。 使用推荐比例可以让用户在使用我们的 App 时更舒适,带来更好的使用体验。

DPI

DPI(Dots Per Inch),每英寸所拥有的点数,原用于打印机、鼠标的精确度指标。 在屏幕方面一般使用 PPI 来表示精度。

PPI

PPI(Pixels Per Inch),每英寸所拥有的像素数,屏幕的 PPI 越高,表示屏幕中的每个像素点之间的距离越接近,像素的密度越高,这样屏幕内容看起来就更加细腻、真实。 而当 PPI 超过 300 时,屏幕被认为达到了视网膜级别,一般情况下人眼已经较难察觉 300 以上 PPI 之间的差别。

Flutter 在不同屏幕上尺寸适配

屏幕密度(Density)

Density 由 Android 1.6 版本(Android API Level 4)为了适配不同大小的屏幕而提出,表示每英寸有多少个显示点(逻辑值),它的单位是 DPI。 在 Android 原生开发中,常常使用 dp/dip/sp 等单位来定义视图、文字的宽高 理论上当 Density 的值为 160 DPI 时,1px = 1dp,当前屏幕的 Density 为 320 DPI 时,2px = 1dp

倍率DPR(devicePixelRatio)

有的地方也叫设备像素比,是设备像素dp和设备独立像素dips的比例, 也就是dpr = dp / dips

逻辑分辨率

逻辑分辨率在 APICloud 应用中也可以被当做显示分辨率使用。 逻辑分辨率与屏幕分辨率在当今的主流设备中是不相同的,公式为: 逻辑分辨率 = 屏幕分辨率 / 屏幕倍率 在 Android 系统中,根据 DP 的定义 1dp = 1px 时, Density 为 160,可知公式为: Android 屏幕倍率 = Density / 160 如 iPhone 4 的屏幕分辨率为 640 x 960,逻辑分辨率为: 640 / 2 x 960 / 2 = 320 x 480 而小米 2 的屏幕分辨率为 720 x 1280,Density 为 320,逻辑分辨率为: 720 / (320 / 160) x 1280 / (320 / 160) = 360 x 640