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

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

文章汇总地址:

Flutter 完整实战实战系列文章专栏

Flutter 番外的世界系列文章专栏

1、Text 的 TextOverflow.ellipsis 不生效

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

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

所以你需要给 Text 设置一个 Container 之类的去约束它的大小,或者是 Row 中通过 Expanded + Container 去约束你的 Text,如果不知道于应该多大,可以通过 LayoutBuilder 设置。

请无视图片

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

看过第六篇的同学应该知道, 我们可以用 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));
  }

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

如果你看过 MaterialApp 的源码,你应该会看到它的内部是一个 WidgetsApp ,而 WidgetsApp 内有一个 MediaQuery,熟悉它的朋友知道我们可以通过 MediaQuery.of(context).size 去获取屏幕大小。

其实 MediaQuery 是一个 InheritedWidget ,它有一个叫 MediaQueryData 的参数,这个参数是通过如下图设置的,再通过源码我们知道,一般情况下 MediaQueryDatapaddingtop 就是状态栏的高度。

所以我们可以通过 MediaQueryData.fromWindow(WidgetsBinding.instance.window).padding.top 获取到状态栏高度,当然有时候可能需要考虑 viewInsets 参数。

image

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

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

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

简单的可以通过 AppBarbrightness 或者 ThemeData 去设置状态栏颜色。

但是如果你不想用 AppBar ,那么你可以嵌套 AnnotatedRegion<SystemUiOverlayStyle> 去设置状态栏样式,通过 SystemUiOverlayStyle 就可以快速设置状态栏和底部导航栏的样式。

同时你还可以通过 SystemChrome.setSystemUIOverlayStyle 去设置,前提是你没有使用 AppBar需要注意的是,所有状态栏设置是全局的, 如果你在 A 页面设置后,B 页面没有手动设置或者使用 AppBar ,那么这个设置将直接呈现在 B 页面。

5、系统字体缩放

现在的手机一般都提供字体缩放,这给应用开发的适配上带来一定工作量,所以大多数时候我们会选择禁止应用跟随系统字体缩放。

在 Flutter 中字体缩放也是和 MediaQueryDatatextScaleFactor 有关。所以我们可以在需要的页面,通过最外层嵌套如下代码设置,将字体设置为默认不允许缩放。

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

6、Margin 和 Padding

在使用 Container 的时候我们经常会使用到 marginpadding 参数,其实在上一篇我们已经说过, Container 其实只是对各种布局的封装,内部的 marginpadding 其实是通过 Padding 实现的,而 Padding 不支持负数,所以如果你需要用到负数的情况下,推荐使用 Transform

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

7、控件圆角裁剪

日常开发中我们大致上会使用两种圆角方案:

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

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

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

image

8、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)
    )

9、懒加载

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

10、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);

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

资源推荐

完整开源项目推荐:
我们还会再见吗?
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容