做为系列文章的第八篇,本篇是主要讲述 Flutter 开发过程当中的实用技巧,让你少走弯路少掉坑,全篇属于很干的干货总结,以实用为主,算是在深刻原理过程当中穿插的实用篇章。android
前文:git
有时候咱们为 Text
设置 ellipsis ,却发现并无生效,而是出现以下图左边提示 overflowed
的警告。github
其实大部分时候,这是 Text
内部的 RenderParagraph
在判断 final bool didOverflowWidth = size.width < textSize.width;
时, size.width 和 textSize.width 是相等致使的。安全
因此你须要给 Text
设置一个 Container
之类的去约束它的大小,或者是 Row
中经过 Expanded
+ Container
去约束你的 Text
。bash
看过第六篇的同窗应该知道, 咱们能够用 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
的参数,这个参数是经过以下图设置的,再经过源码咱们知道,通常状况下 MediaQueryData
的 padding
的 top
就是状态栏的高度。布局
因此咱们能够经过 MediaQueryData.fromWindow(WidgetsBinding.instance.window).padding.top
获取到状态栏高度,固然有时候可能须要考虑 viewInsets
参数。post
至于 AppBar
的高度,默认是 Size.fromHeight(kToolbarHeight + (bottom?.preferredSize?.height ?? 0.0)),
,kToolbarHeight 是一个固定数据,固然你能够经过实现 PreferredSizeWidget
去自定义 AppBar
。字体
同时你可能会发现,有时候在布局时发现布局位置不正常,竟然是从状态栏开始计算,这时候你须要用 SafeArea
嵌套下,至于为何,看源码你就会发现 MediaQueryData
的存在。
简单的能够经过 AppBar
的 brightness 或者 ThemeData
去设置状态栏颜色。
可是若是你不想用 AppBar
,那么你能够嵌套 AnnotatedRegion<SystemUiOverlayStyle>
去设置状态栏样式,经过 SystemUiOverlayStyle
就能够快速设置状态栏和底部导航栏的样式。
同时你还能够经过 SystemChrome.setSystemUIOverlayStyle
去设置,前提是你没有使用 AppBar
。须要注意的是,全部状态栏设置是全局的, 若是你在 A 页面设置后,B 页面没有手动设置或者使用 AppBar ,那么这个设置将直接呈如今 B 页面。
如今的手机通常都提供字体缩放,这给应用开发的适配上带来必定工做量,因此大多数时候咱们会选择禁止应用跟随系统字体缩放。
在 Flutter 中字体缩放也是和 MediaQueryData
的 textScaleFactor
有关。因此咱们能够在须要的页面,经过最外层嵌套以下代码设置,将字体设置为默认不容许缩放。
MediaQuery(
data: MediaQueryData.fromWindow(WidgetsBinding.instance.window).copyWith(textScaleFactor: 1),
child: new Container(),
);
复制代码
在使用 Container
的时候咱们常常会使用到 margin 和 padding 参数,其实在上一篇咱们已经说过, Container
其实只是对各类布局的封装,内部的 margin 和 padding 实际上是经过 Padding
实现的,而 Padding
不支持负数,因此若是你须要用到负数的状况下,推荐使用 Transform
。
Transform(
transform: Matrix4.translationValues(10, -10, 0),
child: new Container(),
);
复制代码
平常开发中咱们大体上会使用两种圆角方案:
Decoration
的实现类 BoxDecoration
去实现。ClipRRect
去实现。其中 BoxDecoration
通常应用在 DecoratedBox
、 Container
等控件,这种实现通常都是直接 Canvas 绘制时,针对当前控件的进行背景圆角化,并不会影响其 child 。这意味着若是你的 child 是图片或者也有背景色,那么极可能圆角效果就消失了。
而 ClipRRect
的效果就是会影响 child 的,具体看看其以下的 RenderObject 源码可知。
若是你在使用 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 再去加载数据,至于流和异步的概念,之后再展开吧。
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完整开发实战详解(4、Redux、主题、国际化)》
《Flutter完整开发实战详解(6、 深刻Widget原理)》
《Flutter完整开发实战详解(10、 深刻图片加载流程)》
《Flutter完整开发实战详解(11、全面深刻理解Stream)》
《React Native 的将来与React Hooks》