flutter 屏幕适配方案自定义单位 rpx px

屏幕适配

现在我们来搞几个模拟器 iphone 5 6 6+ 其他的东西来使用这个

class HYHomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("物理宽度高度 ${HYSizeFit.physicalWidth} * ${HYSizeFit.physicalHeight}");
    return Scaffold(
      appBar: AppBar(
        title: Text("title")
      ),
      body: Center(
        child: Container(
          width: 200,
          height: 200,
          color: Colors.red,
          child: Text("hello world", style: TextStyle(fontSize: 20)),
        )
      ),
    );
  }
}

image

但是我们这只是在小屏幕的iphone上面可以放下

如果我们到 iphone5上面说不定就不行了 他是比较小的

如果我们这里也给他搞一个200 * 200 说不定就不行了 这个时候 如果站的比较多了 这个时候 可能就会报一些错了

所以我们希望你在iphone5 上面 放的小一点 然后再iphone 6 + 上面放的大一点

但是现在如果跑在这些机器上面那他们的距离因该都是200 * 200 这个大小现在是写死的

其实在前端里面对这个东西的适配已经有很多的经验了 所以我们这里借助前端的方案来适配

前端的方案有三种

  • rem

    • 这个东西的方式是 给更标签设置一个字体大小
    • 其他的设置一个字体大小 其他的标签在设置的时候 它就会根据这个字体大小作为单位
  • vw vh

    • 将屏幕分成100 等分 一个vw就是屏幕宽度的1%
    • 其他的所有的单位都使用 vw或者vh
  • rpx

    • 这个是小程序的适配方案 这个东西就是一个可相应的东西
    • 这个东西是 以iphone 6为设计稿
      • 如果我们使用 400 * 400 的时候在iphone 6 上面就是一个200 * 200
      • 如果我们变到到比较的小的上面 这里我们用 400 * 400 它就是 400 * 0.42 作为它的宽度来使用的 这个.42怎么算出来的 是可以 168 这里它就会对这个做一个拉伸
      • 这里我们不管你什么屏幕 我都把你分成 750等份 这个时候iphone 6 就是 0.5 375 / 750
      • iphone 5是 320 / 750 iphone 6+ 414 / 750 0.552
      • 所以这个小程序就和 vw vh差不多 但是它是将屏幕分的更多

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DOFF10Wx-1588730835300)(7D1F9CFD54744C1D8B7B264C101E5861)]
    那我们怎么做这个适配呢 我们来到size_fit 里面 新建一个属性rpx 然后通过这些东西计算出 rpx

import 'dart:ui';

class HYSizeFit {
  static double physicalWidth;
  static double physicalHeight;
  static double screenWidth;
  static double screenHeight;
  static double dpr;
  static double statusHeight;

  static double rpx;

  static void initialize() {
//    1. 手机的物理分辨率
    physicalWidth = window.physicalSize.width; // 拿到物理的宽度
    physicalHeight = window.physicalSize.height;

//    2. 求出dpr
    dpr = window.devicePixelRatio;
//    3. 求出逻辑的宽高
    screenWidth = physicalWidth / dpr;
    screenHeight = physicalHeight /dpr;

//    4. 状态栏高度
    statusHeight = window.padding.top / dpr;

//    5. 计算rpx
    rpx = screenWidth / 750;
  }
}

其实就是 逻辑宽度和750 的商

然后再其他的地方使用

class HYHomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("物理宽度高度 ${HYSizeFit.physicalWidth} * ${HYSizeFit.physicalHeight}");
    return Scaffold(
      appBar: AppBar(
        title: Text("title")
      ),
      body: Center(
        child: Container(
          width: 200 * HYSizeFit.rpx,
          height: 200 * HYSizeFit.rpx,
          color: Colors.red,
          child: Center(
              child: Text("hello world", style: TextStyle(fontSize: 20))
          ),
        )
      ),
    );
  }
}

当然后面我们有更好的适配的写法

但是你注意一个问题就是 小程序里面 我们的是除以 750 不是375 所以我们的所有的东西 都要翻倍

class HYHomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("物理宽度高度 ${HYSizeFit.physicalWidth} * ${HYSizeFit.physicalHeight}");
    return Scaffold(
      appBar: AppBar(
        title: Text("title")
      ),
      body: Center(
        child: Container(
          width: 400 * HYSizeFit.rpx,
          height: 400 * HYSizeFit.rpx,
          color: Colors.red,
          child: Center(
              child: Text("hello world", style: TextStyle(fontSize: 40 * HYSizeFit.rpx))
          ),
        )
      ),
    );
  }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kli4OFy1-1588730835288)(1DD8B4AEFDFC4AFDB4C5D072423877E7)]

这样我们的大小就不一样了

但是 这个地方 * 单位的方式不是特别好些 所以我们这里搞了一个其他的东西

我们给它搞了一个静态方法来实现这个东西



import 'dart:ui';

class HYSizeFit {
  static double physicalWidth;
  static double physicalHeight;
  static double screenWidth;
  static double screenHeight;
  static double dpr;
  static double statusHeight;

  static double rpx;

  static void initialize() {
//    1. 手机的物理分辨率
    physicalWidth = window.physicalSize.width; // 拿到物理的宽度
    physicalHeight = window.physicalSize.height;

//    2. 求出dpr
    dpr = window.devicePixelRatio;

//    3. 求出逻辑的宽高
    screenWidth = physicalWidth / dpr;
    screenHeight = physicalHeight /dpr;

//    4. 状态栏高度
    statusHeight = window.padding.top / dpr;

//    5. 计算rpx
    rpx = screenWidth / 750;
  }

  static double setRpx(double size) {
    return size * rpx;
  }
}

使用

class HYHomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("物理宽度高度 ${HYSizeFit.physicalWidth} * ${HYSizeFit.physicalHeight}");
    return Scaffold(
      appBar: AppBar(
        title: Text("title")
      ),
      body: Center(
        child: Container(
          width: HYSizeFit.setRpx(400),
          height: HYSizeFit.setRpx(400),
          color: Colors.red,
          child: Center(
              child: Text("hello world", style: TextStyle(fontSize: HYSizeFit.setRpx(40)))
          ),
        )
      ),
    );
  }
}

但是如果我们这里还是使用这个rpx不是要翻倍吗 不是很好用 所以我们可以再搞一个单位

import 'dart:ui';

class HYSizeFit {
  static double physicalWidth;
  static double physicalHeight;
  static double screenWidth;
  static double screenHeight;
  static double dpr;
  static double statusHeight;

  static double rpx;
  static double px;

  static void initialize() {
//    1. 手机的物理分辨率
    physicalWidth = window.physicalSize.width; // 拿到物理的宽度
    physicalHeight = window.physicalSize.height;

//    2. 求出dpr
    dpr = window.devicePixelRatio;

//    3. 求出逻辑的宽高
    screenWidth = physicalWidth / dpr;
    screenHeight = physicalHeight /dpr;

//    4. 状态栏高度
    statusHeight = window.padding.top / dpr;

//    5. 计算rpx
    rpx = screenWidth / 750;
    px = rpx * 2;
  }

  static double setRpx(double size) {
    return size * rpx;
  }

  static double setPx(double size) {
    return size * px;
  }
}

这样如果ui给的是一个px 就用px 如果用的是一个rpx那就可以用 rpx

有些时候 公司不是以750 为设计稿 所以我们可以封装更加好一点

这里我们可以给这个initialize 传递一个参数 standardSize 还给他整了一个默认参数

import 'dart:ui';

class HYSizeFit {
  static double physicalWidth;
  static double physicalHeight;
  static double screenWidth;
  static double screenHeight;
  static double dpr;
  static double statusHeight;

  static double rpx;
  static double px;

  static void initialize({standardSize = 750}) {
//    1. 手机的物理分辨率
    physicalWidth = window.physicalSize.width; // 拿到物理的宽度
    physicalHeight = window.physicalSize.height;

//    2. 求出dpr
    dpr = window.devicePixelRatio;

//    3. 求出逻辑的宽高
    screenWidth = physicalWidth / dpr;
    screenHeight = physicalHeight /dpr;

//    4. 状态栏高度
    statusHeight = window.padding.top / dpr;

//    5. 计算rpx
    rpx = screenWidth / standardSize;
    px = screenWidth / standardSize * 2;
  }

  static double setRpx(double size) {
    return size * rpx;
  }

  static double setPx(double size) {
    return size * px;
  }
}

还有 一种方案是使用extension 用这个数值参数的 扩展类 然后将 这个写法继续优化

我们新建一个extensio int 这样就相当于在 int类中写东西

但是注意我们的dart是没有 隐式转换的

import "size_fit.dart";

extension IntFit on int {
  double get px {
    return HYSizeFit.setPx(this.toDouble());
  }

  double get rpx {
    return HYSizeFit.setRpx(this.toDouble());
  }
}
import 'package:learn_flutter02/day14_screenfit/shared/size_fit.dart';

extension DoubleFit on double {
//  double px() {
//    return HYSizeFit.setPx(this);
//  }
//
//  double rpx() {
//    return HYSizeFit.setRpx(this);
//  }

  double get px {
    return HYSizeFit.setPx(this);
  }

  double get rpx {
    return HYSizeFit.setRpx(this);
}
}

我梦给他增加一个 方法 来获得对应的 rpx px值

导入对应的文件使用


import "package:flutter/material.dart";
import "shared/size_fit.dart";

import "extension/double_extension.dart";
import "extension/int_extension.dart";

main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
//    导入文件 然后初始化
    HYSizeFit.initialize();
    return MaterialApp(
      title: "Flutter Demo",
      theme: ThemeData(
        primarySwatch: Colors.blue,
        splashColor: Colors.transparent
      ),
      home: HYHomeScreen(),
    );
  }
}

class HYHomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("物理宽度高度 ${HYSizeFit.physicalWidth} * ${HYSizeFit.physicalHeight}");
    return Scaffold(
      appBar: AppBar(
        title: Text("title")
      ),
      body: Center(
        child: Container(
          width: 400.rpx,
          height: 200.px,
          color: Colors.red,
          child: Center(
              child: Text("hello world", style: TextStyle(fontSize: 40.rpx))
          ),
        )
      ),
    );
  }
}

这种方式更加简洁

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值