Flutter flutter_screenutil 实现屏幕适配

初始化配置

// 设置屏幕宽高比
//If the design is based on the size of the iPhone6 ​​(iPhone6 ​​750*1334)
ScreenUtil.instance = ScreenUtil(width: 750, height: 1334)..init(context);
print('设置像素密度:${ScreenUtil.pixelRatio}');
print('设置的高度:${ScreenUtil.screenHeight}');
print('设置的宽度:${ScreenUtil.screenWidth}');

使用

1.设置字体大小

fontSize: ScreenUtil().setSp(26)

2.设置宽高

width: ScreenUtil.setWidth(750),
height: ScreenUtil.setHeight(333),

依赖下载

# 屏幕适配 https://github.com/OpenFlutter/flutter_screenutil
flutter_screenutil: ^0.6.0

适配要点

  • 顶部NavigationBar 上部预留安全区域
  • 底部NavigationBar 底部预留安全区域

对于安全区域的适配有两种方案

  • 1.采用SafeArea 来包裹页面,SafeArea是Flutter中一个用于适配全面屏的组件,它类似于RN中的SafeAreaView 主要是用于解决适配全屏手机的安全区域问题
  • 2.借助MediaQuery.of(context).padding 获取屏幕四周的padding,然后根据padding自己手动实现对安全区域的控制
  • 方案一:相对简单,只需要引入SafeArea,但不够灵活
  • 方案二:需要借助MediaQuery.of(context).padding 自己实现对安全区域的控制,相对复杂些,但灵活度高;

①采用SafeArea 适应全面屏

import 'package:flutter/material.dart';

class MemberPage extends StatefulWidget {
  @override
  _MemberPageState createState() => _MemberPageState();
}

class _MemberPageState extends State {
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '全面屏适配',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Container(
        decoration: BoxDecoration(color: Colors.white),
        child: SafeArea(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Text("顶部"),
              Text("底部"),
            ],
          ),
        ),
      ),
    );
  }
}
Flutter flutter_screenutil 实现屏幕适配_第1张图片
效果图

②借助MediaQuery.of(context).padding 自己实现对安全区域的控制

补充常见问题

1.部件溢出

A RenderFlex overflowed by 22 pixels on the bottom.
//原因:在水平或者垂直方向上的内容超过了父部件的大小

//解决办法
包一层SingleChildScrollView,让你的页面可以滑动起来。
在Scaffold中设置resizeToAvoidBottomInset为false。默认为ture,防止部件被遮挡。如果使用了这个方法,如果底部有输入框,则会造成遮挡。

2.输入框遮挡

Column配合Expanded来实现

3.SafeArea

一旦有部件固定在顶部或者底部(严谨点的话可以说是在屏幕的四边)。那我我们最好使用SafeArea来包一下。因为Android 和 IOS都有状态栏,甚至IOS还有叫做“HomeIndicator”的横条。所以一不留神就会出现适配问题
使用方法为


Material( // 需要颜色填充到边界区域可以使用
  color: Colors.white,
  child: SafeArea(
    child: Container(),
  ),
)

4.注意平台差异

注意部分组件在Android与IOS平台之间的差异。
ScaffoldAppBarAppBar中默认的title在Android中靠左显示,IOS中居中显示。如果需要两个平台效果统一,需要设置在AppBar中主动设置centerTitle属性。同时AppBar的返回箭头图标也不相同,统一的话需要自定义leading

页面跳转如果使用MaterialPageRoute来做过渡效果,注意Android中新的页面会从屏幕底部滑动到屏幕顶部,IOS中新的页面会从屏幕右侧滑动到屏幕左侧。

如果需要两个平台效果统一,我们不使用自带效果,可以自定义一个

①.SlideTransition
///自定义跳转
        Navigator.push(context, PageRouteBuilder(transitionDuration: Duration(milliseconds: 300),
            pageBuilder: (context, animation, secondaryAnimation){
              return new SlideTransition( //实现相对自身的位移
                position: Tween(
                  begin: const Offset(0.0, 0.02),
                  end: Offset.zero,
                ).animate(animation),
                child: DiscoverChildPage(title: widget.title,),
              );
            })
        );
②2.FadeTransition
///自定义跳转
Navigator.push(context, PageRouteBuilder(transitionDuration: Duration(milliseconds: 300),
    pageBuilder: (context, animation, secondaryAnimation){
      return new FadeTransition( //使用渐隐渐入过渡,
        opacity: animation,
        child: DiscoverChildPage(title: widget.title,),
      );
    })
);

5.依赖版本设置

首先这里建议凡是Flutter的插件在填写版本号时不要使用^符号。

Flutter flutter_screenutil 实现屏幕适配_第2张图片
依赖版本问题

^符号意味着你可以使用此插件的最新版本(大于等于当前版本)。这会导致什么问题呢?可能你前一天代码还能跑起来,今天就编译出错了。因为这些插件中包括Android、IOS的所用依赖环境配置,常见的就是新版本使用了AndroidX的依赖,但是还有些插件并没有使用AndroidX,导致了两者的冲突。

6.Flutter iOS 和 Android 统一左上角返回按钮

思路:自定义leading

appBar: AppBar(
  leading: IconButton(
    icon: Icon(Icons.arrow_back),
    onPressed: () {
      print('返回上一页');
      Navigator.pop(context);
    },
  ),
  title: Text('商品详细页'),
),

自定义leading

static Widget leading (BuildContext context, {Color color}) {
    return GestureDetector(
        onTap: () {
            Navigator.of(context).maybePop();
        },
        child: Icon(
            Icons.arrow_back_ios,
            size: 20,
            color: color ?? Colors.white
        ),
    );
}

屏幕相关

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:ui' as ui show window;

class Screen {
  static double get width {
    MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window);
    return mediaQuery.size.width;
  }
  
  static double get height {
    MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window);
    return mediaQuery.size.height;
  }

  static double get scale {
    MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window);
    return mediaQuery.devicePixelRatio;
  }

  static double get textScaleFactor {
    MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window);
    return mediaQuery.textScaleFactor;
  }

  static double get navigationBarHeight {
    MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window);
    return mediaQuery.padding.top + kToolbarHeight;
  }

  static double get topSafeHeight {
    MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window);
    return mediaQuery.padding.top;
  }

  static double get bottomSafeHeight {
    MediaQueryData mediaQuery = MediaQueryData.fromWindow(ui.window);
    return mediaQuery.padding.bottom;
  }

  static updateStatusBarStyle(SystemUiOverlayStyle style) {
    SystemChrome.setSystemUIOverlayStyle(style);
  }
}

你可能感兴趣的:(Flutter flutter_screenutil 实现屏幕适配)