likes
comments
collection
share

flutter-UI百分比适配

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

基础知识与适配方案

flutter屏幕适配过程中难免会碰到尺寸问题,也就是说不是设计给多少就能写多少的,flutter默认的尺寸为:dp(android)pt(ios),可以理解为1倍像素下的标准尺寸,具体表现为 像素/倍率(1、2、3)

我们开发过程中,以蓝湖为例,设计一般会以 375750 屏幕宽为模板进行开发,实际上就是以 iphone6为标准开发,分别表示的是 ptpxiphone62倍像素屏,所以屏幕基本宽度 375, 宽度占用像素为 750,到这里相信都理解了这两者的关系

目前主流适配方案大致有两种(都是以宽度为参考):

  1. 按照设计稿等比适配
  2. 间距固定,内容根据剩余宽度等比放大或者缩小(毕竟横向也放不了多少东西)

dp、pt适配方案(间距固定、内容填充适配)

这种方案一般都是使用 dp、pt 方案来适配的,一般适用于横向内容比较少的页面,一般应用在带图片的内容浏览,越是大屏,内容区域会越大,观看体验越佳,这也是以前比较主流的适配方案,现在也同样适用,相比与下面的百分比,有时候有些布局需要略微多动一点脑子罢了(而不是特殊布局直接按宽为750来布局),不过没事僵尸还没吃掉我的脑子,还勉强够用😂

百分比适配方案

根据设计稿宽度,等比例适配到真机上,两者只需要相除便可以得出比例,适用设计稿像素*基本百分比即可,这样可以保证宽度上在不同宽度的手机上表现得大致相同(会有一个像素左右误差,毕竟像素不会出现0.1、0.9之类的)

这也是目前跨平台应用普遍采用的适配方案(既然跨平台了,那么都一样吧😂)

混合适配

混合适配就是根据内容和平台的展示,选择使用百分比还是dp、pt方案

例如根据内容分割:朋友圈分享页面选择dp、pt方案,购物导航页选择百分比

实际上一般应用都只会使用 百分比 方案适配更加方便,如果想在大屏平台上让体验更佳一些,且同时应用到 ipad 上面的应用较多采用 dp、pt方案,而仅仅手机端则采用 百分比的更多一点

百分比适配方案代码准备

以 dart 为例(可转化为适合自己的编程语言),生成下面代码,以便使用

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

class AdaptUtil {
  //设备基本信息对象
  static final MediaQueryData mediaQuery = MediaQueryData.fromWindow(window);
  //屏幕宽度dp
  static final double width = mediaQuery.size.width;
  //屏幕高度dp
  static final double height = mediaQuery.size.height;
  //屏幕像素倍率
  static final double ratio = mediaQuery.devicePixelRatio;
  static final double dp2pxRatio = width / 750;
  //传入设计稿 750 像素宽度为参考的尺寸 dp2px
  static double dp2px(double dp2px) {
    return dp2px * dp2pxRatio;
  }
  //传入px转化成dp
  static double px(double px) {
    return px / ratio;
  }
}

由于都是静态方法,直接通过类名调用即可

//根据750像素宽的设计稿,传入尺寸
Container(
  width: AdaptUtil.dp2px(750),
),
//必要时传入像素
Container(
  width: AdaptUtil.px(120),
),

应用到flutter的案例改进

实际使用过程中,由于数字都是num对象,因此可以直接对num进行扩展即可,给转化逻辑包装成属性的样子,方便调用

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

final MediaQueryData mediaQuery = MediaQueryData.fromWindow(window);
//屏幕像素倍率
final double ratio = mediaQuery.devicePixelRatio;

//屏幕宽度dp
final double width = mediaQuery.size.width;
//屏幕高度dp
final double height = mediaQuery.size.height;
final double dp2pxRatio = width / 750;

//方便外边调用,不用模块化导出了,打出类名就能拿出变量了
class AdaptUtil {
  //屏幕宽度dp
  static final double width = width;
  //屏幕高度dp
  static final double height = height;
  //padding,例如:x 以及以上底部是 34 (.bottom),使用其可以避免底部按钮点不到的问题
  static final EdgeInsets padding = mediaQuery.padding;
}

//为了方便使用,我们伪装成属性调用(实际应该是伪属性,不存在该字段)
extension Adapt on num {
  //使用扩展方便调用,以边距750为例
  double get sp => this * dp2pxRatio;
  //将dp、pt转化为px
  double get px => this / ratio;
}

调用的时候只需要.sp即可

//如下所示调用即可,由于直接调用了方法, 因此不能使用 const,需要注意了
width: 10.sp

最后

你可能会觉得,百分比适配过程中每个都要走转化的方法,那么性能不就变低了么?

这是肯定会有一点影响的,但这类纯计算的一般影响不大,优先从别的地方进行性能优化,如果该优化的都优化了还是存在性能问题,那么要不就放弃跨平台使用原生,要不就产品选择更新内容来进行优化(不过只要功能合理一般应当以产品为主,毕竟产品竞争力很关键,他们负责将产品设计好,我们负责将技术瓶颈解决,以提升项目整体竞争力,毕竟合作共赢)

PS: 实在搞不定的实现和优化点,找产品砍需求,有时间条件的可以纳入原生尝试混编开发😂,当然如果你觉得百分比的这个拖累了速度,可以仅仅采用 dp、pt适配方案,也是完全ok,不过这种方案有时需要自己额外估算间距