flutter屏幕适配

现在的手机品牌和型号越来越多,导致我们平时写布局的时候会在个不同的移动设备上显示的效果不同,

比如我们的设计稿一个View的大小是300px,如果直接写300px,可能在当前设备显示正常,但到了其他设备可能就会偏小或者偏大,这就需要我们对屏幕进行适配。

安卓原生的话有自己的适配规则,可以根据不同的尺寸建立不同的文件夹,系统会根据当前的设备尺寸取对应的大小的布局。而flutter本身并没有适配规则,而原生的又比较繁琐,这就需要我们自己去对屏幕进行适配。

点击直达github地址 如果有帮助,请给我个star

flutter_ScreenUtil

flutter 屏幕适配方案

github: github.com/OpenFlutter…

csdn博客 工具 介绍: blog.csdn.net/u011272795/…

使用方法:

安装依赖:

安装之前请查看最新版本

dependencies:
  flutter:
    sdk: flutter
  # 添加依赖
  flutter_screenutil: ^0.3.0
复制代码

在每个使用的地方导入包:

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来做适配可以保证不变形

例如:
Container(
           width: ScreenUtil().setWidth(375),
           height: ScreenUtil().setHeight(200),
            ),
复制代码

适配字体:

ScreenUtil().setSp(28)         //传入字体大小,根据系统的“字体大小”辅助选项来进行缩放
      ScreenUtil().setSp(28,false)  //传入字体大小,不会根据系统的“字体大小”辅助选项来进行缩放

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  //宽度相对于设计稿放大的倍数
    ScreenUtil().scaleHeight //高度相对于设计稿放大的倍数
    
复制代码
//导入
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(
         '宽度相对于设计稿放大的倍数:${ScreenUtil().scaleWidth}'); //The width is enlarged relative to the design draft
     print(
         '高度相对于设计稿放大的倍数:${ScreenUtil().scaleHeight}'); //The height is enlarged relative to the design draft
     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(
                     'My width:${ScreenUtil().setWidth(375)}dp',
                     style: TextStyle(
                         color: Colors.white,
                         fontSize: ScreenUtil().setSp(28, false)),
                   ),
                 ),
                 Container(
                   width: ScreenUtil().setWidth(375),
                   height: ScreenUtil().setHeight(200),
                   color: Colors.blue,
                   child: Text('My width:${ScreenUtil().setWidth(375)}dp',
                       style: TextStyle(
                           color: Colors.white,
                           fontSize: ScreenUtil().setSp(28, false))),
                 ),
               ],
             ),
             Text('Device width:${ScreenUtil.screenWidth}px'),
             Text('Device height:${ScreenUtil.screenHeight}px'),
             Text('Device pixel density:${ScreenUtil.pixelRatio}'),
             Text('Bottom safe zone distance:${ScreenUtil.bottomBarHeight}px'),
             Text('Status bar height:${ScreenUtil.statusBarHeight}px'),
             Text(
               'Width is enlarged relative to the design draft:${ScreenUtil().scaleWidth}',
               textAlign: TextAlign.center,
             ),
             Text(
               'Height is enlarged relative to the design draft:${ScreenUtil().scaleHeight}',
               textAlign: TextAlign.center,
             ),
             SizedBox(
               height: ScreenUtil().setHeight(200),
             ),
             Text('System font scaling:${ScreenUtil.textScaleFactory}'),
             Column(
               crossAxisAlignment: CrossAxisAlignment.start,
               children: <Widget>[
                 Text(
                     '我的文字大小是28px,不会随着系统的文字大小变化',
                     style: TextStyle(
                         color: Colors.black,
                         fontSize: ScreenUtil().setSp(28, false))),
                 Text('我的文字大小是28px,会随着系统的文字大小变化',
                     style: TextStyle(
                         color: Colors.black, fontSize: ScreenUtil().setSp(28))),
               ],
             )
           ],
         ),
       ),
     );
   }
复制代码

使用示例:

example demo

效果:

适配原理

说一下适配方案, 比如我们设计师设计的UI是根据Iphone6来做的,我们知道 iPhone6的分辨率是750*1334(px), 又或者是根据hdpi的设备来设计的UI,我们知道hdpi的 Android 设备是 (240 dpi),像素密度是1.5,即hdpi设备的分辨率宽度是320px, 总之,无论设计稿的单位是px,或者是dp,我们都能够转换成px. 那么我们如果根据px来适配,ios和 android 就都可以兼容了.

假设,我们的设计稿手机是1080 1920 px. 设计稿上有一个540 960 的组件, 即宽度和宽度是手机的一半. 如果我们直接写的时候组件的尺寸这么定义,在其他尺寸的设备上未必是一半,或多,或少. 但是我们可以按比例来看,即我们要实现的宽度是实际设备的一半. 那么假设我们设备的宽度是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;
复制代码

那么我们要写尺寸为500 100控件的宽度就是 500 scaleWidth .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 
复制代码

字体大小适配

setSp(int fontSize, [allowFontScaling = true]) => allowFontScaling
      ? setWidth(fontSize) * _textScaleFactor
      : setWidth(fontSize);
复制代码

第一个参数为设计稿中字体的大小,单位px, 第二个参数可选,为控制字体是否要根据系统的“字体大小”辅助选项来进行缩放。默认值为true。

原文地址:https://www.cnblogs.com/pythonClub/p/10599340.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


这篇文章主要讲解了“FlutterComponent动画的显和隐怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究...
这篇文章主要讲解了“flutter微信聊天输入框功能如何实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“f...
本篇内容介绍了“Flutter之Navigator的高级用法有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处...
这篇文章主要介绍“Flutter怎么使用Android原生播放器”,在日常操作中,相信很多人在Flutter怎么使用Android原生播放器问题上存在疑惑,小编查阅了各式资料,整...
Flutter开发的android端如何修改APP名称,logo,版本号,具体的操作步骤:修改APP名称找到文件:android\\app\\src\\main\\AndroidManifest.xml
Flutter路由管理初识路由概念一.路由管理1.1.Route1.2.MaterialPageRoute1.3.Navigator1.4.路由传值1.5 命名路由1.6.命名路由参数传递1.7.适配二、路由钩子三、onUnknownRoute四、结尾初识路由概念路由的概念由来已久,包括网络路由、后端路由,到现在广为流行的前端路由。无论路由的概念如何应用,它的核心是一个路由映射表。比如:名字 detail 映射到 DetailPage 页面等。有了这个映射表之后,我们就可以方便的根据名字来完成路由的转发
前提:针对Android开发者(windows系统下),已安装Git,AndroidStudio(建议4.0+版本)一.下载Flutter SDK地址:https://flutter.dev/docs/development/tools/sdk/releases,在 Stable channel (Windows)里面下最新版本即可。Flutter的渠道版本会不停变动,请以Flutter官网为准。在中国,要想正常获取安装包列表或下载安装包,可能需要翻墙,也可以去Flutter github项目下去下载安
一、变量变量是一个引用,根据Dart中“万物皆对象”原则,即变量存储的都是对象的引用,或者说它们都是指向对象。1.1.声明变量://1.不指定类型var name = 'aaa';//2.明确指定类型String name = 'aaa';因为有类型推导,所以两种实现效果一样,官方推荐在函数内的本地变量尽量使用var声明。在变量类型并不明确的情况下,可以使用dynamic关键字//3.使用dynamic关键字dynamic name = 'aaa';1.2.默认值未初始化的变量
前言Flutter2.0发布不久,对web的支持刚刚进入stable阶段。初学几天,构建web应用时候碰到一些问题,比如中文显示成乱码,然后加载图片出现图片跨域问题:Failed to load network image...Trying to load an image from another domain?1.开启web端构建:使用下面这个命令才可以开启Web端构建的支持flutter config --enable-web提示我们:重新启动编辑器,以便它们读取新设置。2.重
一.Flutter打Android release包的步骤:1.为项目创建一个.jks签名文件(很简单,跳过)2.创建一个文件key.properties,直接复制下面key.properties位置如图:在里面输入一下内容:storePassword=iflytekkeyPassword=iflytekkeyAlias=teachingmachinestoreFile=E:/teacher/app/keys/TeachingMachine.jks输入你自己的passwork以及
1 问题Android原生向js发消息,并且可以携带数据2 实现原理Android原生可以使用RCTEventEmitter来注册事件,然后这里需要指定事件的名字,然后在js那端进行监听同样事件的名字监听,就可以收到消息得到数据Android注册关键代码reactContext.getJSModule(DeviceEventManagerModule.RCT...
1 Flexbox布局1) flexDirection 可以决定布局的主轴,子元素是应该沿着水平轴(row)方向排列,还是沿着竖直轴(column)方向排列2) justifyContent 决定其子元素沿着次轴(与主轴垂直的轴,比如若主轴方向为row,则次轴方向为column)的排列方式 有flex-start、center、flex-end、space-around...
1 实现的功能在网上看React Native文档,我特码就想实现一个页面到另外一个页面的跳转,然后另外一个页面怎么获取参数,特么没找到一个说清楚的,要么太复杂,要么说了不理解,下面是我自己写的一个App.js文件,实现一个Home页面跳到另外Details页面,并且携带了参数怎么在Details页面获取,就是这么简单粗暴.2 测试DemoApp.js文件如下...
1 问题在一个文件构建一个对象,然后在另外一个文件里面new这个对象,通过构造方法传递参数,然后再获取这个参数2 测试代码Student.js文件如下'use strict';import React from 'react'import {NativeModules, NativeEventEmitter, DeviceEventEmitter,Ale...
1 简单部分代码export default class App extends Component&amp;lt;Props&amp;gt; { render() { return ( &amp;lt;View {styles.container}&amp;gt; &amp;lt;View {styles.welcome}&amp;gt; &amp;l...
1 怎么实现发送和接收事件理论上封装了Android原生广播的代码,需要注册和反注册,这里用DeviceEventEmitter实现//增加监听DeviceEventEmitter.addListener//取消监听//this.emitter.remove();这里可也可以通过安卓原生向页面js发送消息,可以参考我的这篇博客React Native之Android原生通过Dev...
1、Component介绍一般Component需要被其它类进行继承,Component和Android一样,也有生命周期英文图片如下2 具体说明1)、挂载阶段constructor()//构造函数,声明之前先调用super(props)componentWillMount()//因为它发生在render()方法前,因此在该方法内同步设置状态...
1 触摸事件普通点击我们可以使用onPress方法,我们可以使用Touchable 系列控件设计我们的按钮TouchableHighlight 背景会在用户手指按下时变暗TouchableNativeFeedback用户手指按下时形成类似墨水涟漪的视觉效果TouchableOpacity指按下时降低按钮的透明度,而不会改变背景的颜色TouchableWithoutFeedbac...
1 问题部分代码如下class HomeScreen extends React.Component { render() { return ( &amp;lt;View {{ flex: 1, alignItems: 'center', justifyContent: 'center' }}&amp;gt; &amp;lt;Text&amp;gt;Home Scre...
1 Props(属性)和State(状态)和简单样式简单使用App.js代码如下/** * Sample React Native App * https://github.com/facebook/react-native * * @format * @flow */import React, {Component} from 'react';import {Pla...