美文网首页Flutter学习Flutter开发圈Flutter
Flutter flutter_screenutil 实现屏幕适

Flutter flutter_screenutil 实现屏幕适

作者: StevenHu_Sir | 来源:发表于2019-08-25 22:18 被阅读0次

    初始化配置

    // 设置屏幕宽高比
    //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<MemberPage> {
      @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: <Widget>[
                  Text("顶部"),
                  Text("底部"),
                ],
              ),
            ),
          ),
        );
      }
    }
    
    效果图

    ②借助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<Offset>(
                      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的插件在填写版本号时不要使用^符号。

    依赖版本问题

    ^符号意味着你可以使用此插件的最新版本(大于等于当前版本)。这会导致什么问题呢?可能你前一天代码还能跑起来,今天就编译出错了。因为这些插件中包括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 实现屏幕适

        本文链接:https://www.haomeiwen.com/subject/vizkectx.html