Flutter完整开发实战详解(8、 实用技巧与填坑)

做为系列文章的第八篇,本篇是主要讲述 Flutter 开发过程当中的实用技巧,让你少走弯路少掉坑,全篇属于很干的干货总结,以实用为主,算是在深刻原理过程当中穿插的实用篇章。android

前文:git

一、Text 的 TextOverflow.ellipsis 不生效

有时候咱们为 Text 设置 ellipsis ,却发现并无生效,而是出现以下图左边提示 overflowed 的警告。github

其实大部分时候,这是 Text 内部的 RenderParagraph 在判断 final bool didOverflowWidth = size.width < textSize.width; 时, size.widthtextSize.width 是相等致使的。安全

因此你须要给 Text 设置一个 Container 之类的去约束它的大小,或者是 Row 中经过 Expanded + Container 去约束你的 Textbash

请无视图片

二、获取控件的大小和位置

看过第六篇的同窗应该知道, 咱们能够用 GlobalKey ,经过 key 去获取到控件对象的 BuildContext,而前面咱们也说过 BuildContext 的实现实际上是 Element ,而 Element 持有 RenderObject 。So,咱们知道的 RenderObject ,实际上获取到的就是 RenderBox ,那么经过 RenderBox 咱们就只大小和位置了:异步

showSizes() {
    RenderBox renderBoxRed = fileListKey.currentContext.findRenderObject();
    print(renderBoxRed.size);
  }

  showPositions() {
    RenderBox renderBoxRed = fileListKey.currentContext.findRenderObject();
    print(renderBoxRed.localToGlobal(Offset.zero));
  }
复制代码

三、获取状态栏高度和安全布局

若是你看过 MaterialApp 的源码,你应该会看到它的内部是一个 WidgetsApp ,而 WidgetsApp 内有一个 MediaQuery,熟悉它的朋友知道咱们能够经过 MediaQuery.of(context).size 去获取屏幕大小。async

其实 MediaQuery 是一个 InheritedWidget ,它有一个叫 MediaQueryData 的参数,这个参数是经过以下图设置的,再经过源码咱们知道,通常状况下 MediaQueryDatapaddingtop 就是状态栏的高度。布局

因此咱们能够经过 MediaQueryData.fromWindow(WidgetsBinding.instance.window).padding.top 获取到状态栏高度,固然有时候可能须要考虑 viewInsets 参数。post

至于 AppBar 的高度,默认是 Size.fromHeight(kToolbarHeight + (bottom?.preferredSize?.height ?? 0.0)),kToolbarHeight 是一个固定数据,固然你能够经过实现 PreferredSizeWidget 去自定义 AppBar字体

同时你可能会发现,有时候在布局时发现布局位置不正常,竟然是从状态栏开始计算,这时候你须要用 SafeArea 嵌套下,至于为何,看源码你就会发现 MediaQueryData 的存在。

四、设置状态栏颜色和图标颜色

简单的能够经过 AppBarbrightness 或者 ThemeData 去设置状态栏颜色。

可是若是你不想用 AppBar ,那么你能够嵌套 AnnotatedRegion<SystemUiOverlayStyle> 去设置状态栏样式,经过 SystemUiOverlayStyle 就能够快速设置状态栏和底部导航栏的样式。

同时你还能够经过 SystemChrome.setSystemUIOverlayStyle 去设置,前提是你没有使用 AppBar须要注意的是,全部状态栏设置是全局的, 若是你在 A 页面设置后,B 页面没有手动设置或者使用 AppBar ,那么这个设置将直接呈如今 B 页面。

五、系统字体缩放

如今的手机通常都提供字体缩放,这给应用开发的适配上带来必定工做量,因此大多数时候咱们会选择禁止应用跟随系统字体缩放。

在 Flutter 中字体缩放也是和 MediaQueryDatatextScaleFactor 有关。因此咱们能够在须要的页面,经过最外层嵌套以下代码设置,将字体设置为默认不容许缩放。

MediaQuery(
      data: MediaQueryData.fromWindow(WidgetsBinding.instance.window).copyWith(textScaleFactor: 1),
      child: new Container(),
    );
复制代码

六、Margin 和 Padding

在使用 Container 的时候咱们常常会使用到 marginpadding 参数,其实在上一篇咱们已经说过, Container 其实只是对各类布局的封装,内部的 marginpadding 实际上是经过 Padding 实现的,而 Padding 不支持负数,因此若是你须要用到负数的状况下,推荐使用 Transform

Transform(
      transform: Matrix4.translationValues(10, -10, 0),
      child: new Container(),
    );
复制代码

七、控件圆角裁剪

平常开发中咱们大体上会使用两种圆角方案:

  • 一种是经过 Decoration 的实现类 BoxDecoration 去实现。
  • 一种是经过 ClipRRect 去实现。

其中 BoxDecoration 通常应用在 DecoratedBoxContainer 等控件,这种实现通常都是直接 Canvas 绘制时,针对当前控件的进行背景圆角化,并不会影响其 child 。这意味着若是你的 child 是图片或者也有背景色,那么极可能圆角效果就消失了。

ClipRRect 的效果就是会影响 child 的,具体看看其以下的 RenderObject 源码可知。

八、PageView

若是你在使用 TarBarView ,而且使用了 KeepAlive 的话,那么我推荐你直接使用 PageView 。由于目前到 1.2 的版本,在 KeepAlive 的 状态下,跨两个页面以上的 Tab 直接切换, TarBarView 会致使页面的 dispose 再从新 initState。尽管 TarBarView 内也是封装了 PageView + TabBar

你能够直接使用 PageView + TabBar 去实现,而后 tab 切换时使用 _pageController.jumpTo(MediaQuery.of(context).size.width * index); 能够避免一些问题。固然,这时候损失的就是动画效果了。事实上 TarBarView 也只是针对 PageView + TabBar 作了一层封装。

除了这个,其实还有第二种作法,使用以下方 PageStorageKey 保持页面数状态,可是由于它是 save and restore values ,因此的页面的 dispose 再从新 initState 方法,每次都会被调用。

return new Scaffold(
      key: new PageStorageKey<your value type>(your value)
    )
复制代码

九、懒加载

Flutter 中经过 FutureBuilder 或者 StreamBuilder 能够和简单的实现懒加载,经过 future 或者 stream “异步” 获取数据,以后经过 AsyncSnapshot 的 data 再去加载数据,至于流和异步的概念,之后再展开吧。

十、Android 返回键回到桌面

Flutter 官方已经为你提供了 android_intent 插件了,这种状况下,实现回到桌面能够以下简单实现:

Future<bool> _dialogExitApp(BuildContext context) async {
    if (Platform.isAndroid) {
      AndroidIntent intent = AndroidIntent(
        action: 'android.intent.action.MAIN',
        category: "android.intent.category.HOME",
      );
      await intent.launch();
    }

    return Future.value(false);
  }
·····
 return WillPopScope(
      onWillPop: () {
        return _dialogExitApp(context);
      },
      child:xxx);
复制代码

自此,第八篇终于结束了!(///▽///)

资源推荐

完整开源项目推荐:
文章

《Flutter完整开发实战详解(1、Dart语言和Flutter基础)》

《Flutter完整开发实战详解(2、 快速开发实战篇)》

《Flutter完整开发实战详解(3、 打包与填坑篇)》

《Flutter完整开发实战详解(4、Redux、主题、国际化)》

《Flutter完整开发实战详解(5、 深刻探索)》

《Flutter完整开发实战详解(6、 深刻Widget原理)》

《Flutter完整开发实战详解(7、 深刻布局原理)》

《Flutter完整开发实战详解(8、 实用技巧与填坑)》

《Flutter完整开发实战详解(9、 深刻绘制原理)》

《Flutter完整开发实战详解(10、 深刻图片加载流程)》

《Flutter完整开发实战详解(11、全面深刻理解Stream)》

《跨平台项目开源项目推荐》

《移动端跨平台开发的深度解析》

《React Native 的将来与React Hooks》

咱们还会再见吗?
相关文章
相关标签/搜索