flutter 屏幕适配

本文最后更新于:2022年4月22日 上午

flutter 屏幕适配

屏幕适配

flutter中编写的像素单位是固定的,如果要做在不同设备上的屏幕适配,需要开发者手动适配(类似小程序中的 rpx适配,会将手机屏幕以750宽度作为基准,开发者通过做好该宽度的适配即可在不同屏幕上自动拥有不同的大小效果)

适配方式

  1. 通过设备的 物理宽高 除以 dpr得到 逻辑宽高
  2. 逻辑宽高 除以 设计稿宽度(一般以6/6s750 做基准) 得到 dpr
  3. 设置像素的时候通过 像素 乘以 dpr得到 可以自适应的宽高

例如 设备逻辑宽度是 750dpr2,那么得到逻辑宽是 750/2 = 375,那么就会把 375当做设备的宽度。

再用 逻辑宽度 / 设计稿宽度 得到 rpx 375/750 = 0.5

设置像素的时候 都用 像素 乘以 刚刚算出的 rpx,如 100 * 0.5 = 50,那么这个像素在当前设备上就是 50

假如换到 iphone xrrpx就是 414/750 = 0.552,再用像素乘以rpx 100*0.552 = 55.2,那么在 xr 上就是宽度就是 55.2

封装获取 rpx

class HotSize {
  static double standardSize = 750; // 设计稿尺寸

  static double physicalWidth = 0; // 物理宽度
  static double physicalHeight = 0; // 物理高度
  static double dpr = 2; // 缩放比例

  static double width = 0; // 逻辑宽度
  static double height = 0; // 逻辑高度

  static double tabHeight = 0; // 头部状态栏高度

  static double rpx = 0; // rpx
  static double px = 0; // px

  static init() {
    // 获取物理宽高
    physicalWidth = window.physicalGeometry.width;
    physicalHeight = window.physicalGeometry.height;

    // 获取 dpr
    dpr = window.devicePixelRatio;

    // 计算逻辑宽高
    width = physicalWidth / dpr;
    height = physicalHeight / dpr;

    tabHeight = window.padding.top;

    rpx = width / standardSize;
    px = width / standardSize * 2;
  }

  // 设置 rpx
  double setRpx(double size) => size * rpx;
  double setRx(double size) => size * px;
}

使用

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('屏幕')),
      body: Center(
        child: Container(
          width: HotSize().setRpx(750),
          height: HotSize().setRpx(300),
          color: Colors.green,
        ),
      ),
      // body: Text('home'),
    );
  }
}

优化写法

上述写法每次都需要调用 setRpx()来设置 rpx,会较为繁琐,我们可以通过扩展的方式来简化写法

import '../utils/hot_size.dart';

// 扩展 int
extension intHotSize on int {
  double get rpx => HotSize.setRpx(this.toDouble());
  double get px => HotSize.setPx(this.toDouble());
}
import '../utils/hot_size.dart';

// 扩展 double
extension doubleHotSize on double {
  double get rpx => HotSize.setRpx(this.toDouble());
  double get px => HotSize.setPx(this.toDouble());
}

使用

需要先进行导入

import 'package:learn_fluuter_00/cookbook/extensions/int.dart';

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: Text('美食广场')),
    body: Container(width: 200https://api.flutter-io.cn/flutter/static-assets/favicon.png?v1.rpx, child: Text('首页')),
  );
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议,转载请注明出处。