想写这个很久了,每个人都是从萌新来的,在一些国内Flutter群里(482462250,422833104)呆着, 经常有很多重复的问题在群里反复出现,导致群里大佬都不爱搭理了。
下面的目录会不断更新,如果内容太多,我会拆分掉。
FlutterCandies QQ群:181398081
image
目录
以下集合由 什么都懂一些的财经龙 big nao 授权
image
大佬有很多有用插件Github
我是谁,我从哪里来,我要做什么
Flutter跟其他混合开发模式比怎么样?
安卓IOS原生是不是灭亡了?
有没有线上的Flutter产品?
这应该是每个程序猿选择新的领域的一种焦虑吧,其实我们可以根据自己的情况,以及该领域的发展前景来进行自己的判断。答案肯定不是唯一的。在塞班灭亡之前,没人可以那么肯定它就这样亡了。一个程序猿当然也不可能一辈子只是接触一个技术一个领域,学习难道不是作为程序猿来说的一种乐趣吗。对于前2个问题,我没法说出标准答案,第三个,有,咸鱼,爱奇艺,东方财富都在原生的基础上嵌入了Flutter。
萌新入门看啥
萌新的自己解决问题的能力
每个人都从萌新而来,如果你想开森的写代码,自己解决问题是必须的
状态栏怎么透明
还是原生大法好,已经有插件支持,安心食用
flutter_statusbarcolor
怎么去掉列表上拉或者下拉时候的波纹
该组件在插件loading_more_list当中
下拉刷新
上拉加载更多
NestedScrollView的使用
官方的NestedScrollView是有一些缺陷的,在使用这个组件之前,强烈建议食用,里面的Demo也有NestedScrollView的用法。
我的列表怎么了
列表或者说ScrollView其实有一个可视区域的概念(Viewport),就是滚动时候的可见的部分,这个区域的大小往往需要你自己告诉他。
- 列表放在Column里面
错误示例
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'测试',
),
ListView.builder(itemBuilder: (context,index){})
],
),
你想在列表上面加个Text,当然可能是别的。你把2个组件放到了Column里面,但是注意,Column里面的元素,默认是自动大小的,就autosize.这就会造成ListView认为外面的区域是无限大的,它会构建出全部的Items,超出的部分会被截掉,列表也会失去滚动的效果。
正确示例
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'测试',
),
Expanded(
child: ListView.builder(itemBuilder: (context, index) {}),
)
],
),
将列表放进一个Expanded,表示列表的可视区域是除去Text之后的剩下的区域,这样列表就有了它确定的可视区域
- List里面可以放List吗?
大部分人有这种想法。其实是想水平和垂直区域都要有对应的滚动。
代码示例
CustomScrollView(
slivers: <Widget>[
//水平
SliverToBoxAdapter(
child: Container(
height: 40.0,
child: ListView.builder(
itemBuilder: (context, index) {
return Text("测试${index}");
},
itemCount: 50,
scrollDirection: Axis.horizontal,
),
),
),
//垂直
SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return Text("测试${index}");
}, childCount: 50),
)
],
),
注意你要给水平的列表增加指定的高度,因为对于垂直方向来说。。这个水平列表如果没有固定高度,那么垂直方法的viewport将没法进行计算
- 使用ListView还是SliverList?
这2者的区别在于
1.SliverList必须放在Sliver系列里面,常见的是CustomScrollView,NestedScrollView的header里面。
请牢牢记住,Sliver系列只能放Sliver系列,别直接把其他widget比如Container/ListView直接放里面。
2.ListView内部其实也是包裹了ScrollView,而SliverList依靠的是外部的CustomScrollView或者NestedScrollView的header 里面的ScrollView 来进行控制的。
这里我们提一下常用的Sliver组件
是Sliver组件的老祖宗,全部的Sliver都放在这个里面。
SliverList, which is a sliver that displays linear list of children.
SliverFixedExtentList, which is a more efficient sliver that displays linear list of children that have the same extent along the scroll axis.
比SliverList多一个就是相同的行高。这样性能会更好
SliverGrid, which is a sliver that displays a 2D array of children.
可以设置每行的个数的Grid
SliverPersistentHeader A sliver whose size varies when the sliver is scrolled to the leading edge of the viewport.
This is the layout primitive that SliverAppBar uses for its shrinking/growing effect.
非常好用的组件,SliverAppBar就是用这个实现的。这个组件的特点是可以创建出随着滑动变化的可以Pinned的元素,大家经常用的什么吸顶组件可以用这个很方便的构建
SliverToBoxAdapter
当你想把一个非Sliver的Widget放在CustomScrollview里面的时候,你需要用这个包裹一下。千万别把非Sliver widget直接放在Sliver里面,记得用这个
SliverFillRemaining sizes its child to fill the viewport in the cross axis and to fill the remaining space in the viewport in the main axis. 使用这个它会填充完剩余viewport里面的全部空间
SliverPadding, which is a sliver that adds blank space around another sliver.
你可以把不是Sliver系列的widget放这个里面,跟SliverToBoxAdapter效果差不多,其实你也可以用SliverToBoxAdapter 里面放个Padding来实现
SliverAppBar, which is a sliver that displays a header that can expand and float as the scroll view scrolls.
SliverSafeArea A sliver that insets another sliver by sufficient padding to avoid intrusions by the operating system.
For example, this will indent the sliver by enough to avoid the status bar at the top of the screen.为了防止各种边界的越界,比如说越过顶部的状态栏,跟SafeArea效果一样。只是这个是放Sliver里面的
除了Sliver列表之外,SliverToBoxAdapter,SliverFillRemaining是Sliver系列里面高频使用的组件。
圆角
ClipRRect(
borderRadius: new BorderRadius.circular(radius),child:child)
点击水波纹
return InkWell(
child: Text("测试${index}"),
onTap: () {},
);
点击空白透明区域没事件响应
return GestureDetector(
behavior: HitTestBehavior.translucent,
child: Text("测试${index}"),
onTap: () {},
);
设置HitTestBehavior
enum HitTestBehavior {
/// Targets that defer to their children receive events within their bounds
/// only if one of their children is hit by the hit test.
deferToChild, //只生效在child的区域比如文字
/// Opaque targets can be hit by hit tests, causing them to both receive
/// events within their bounds and prevent targets visually behind them from
/// also receiving events.
opaque,//GestureDetector的整个区域,不包括它下面的区域
/// Translucent targets both receive events within their bounds and permit
/// targets visually behind them to also receive events.
translucent,// GestureDetector的整个区域以及它下面的区域
}
Flutter错误提示
Flutter中如果有错误,将会在控制台当中显示出错误信息(虽然有时候信息不能反映出准确的位置),你可以根据这个信息来了解错误的原因和地方
I/flutter ( 9746): The following assertion was thrown building NotificationListener<ScrollNotification>: I/flutter ( 9746): A RenderViewport expected a child of type RenderSliver but received a child of type I/flutter ( 9746): RenderRepaintBoundary. I/flutter ( 9746): RenderObjects expect specific types of children because they coordinate with their children during I/flutter ( 9746): layout and paint. For example, a RenderSliver cannot be the child of a RenderBox because a I/flutter ( 9746): RenderSliver does not understand the RenderBox layout protocol.
E/flutter ( 9746): #6 runApp (package:flutter/src/widgets/binding.dart:756:7) E/flutter ( 9746): #7 main (package:flutter_app123123213/main.dart:3:16)
上面错误是我尝试将ListView(非Sliver组件)放进CustomScrollView中,上面是错误信息,下面的是错误发生在我写的代码的哪里。
这个东西没别的方法,多被坑几次就会好了。。
image键盘挡住页面了
请使用一些能滚动的组件包住你的页面。比如SingleChildScrolView,
Appbar/Tabbar/StatusBar的高度
Appbar kToolbarHeight 这个是一个系统的Const可以直接获得
imageTabbar 可以用tabbar.preferredSize获取 如果你看源码。其实它也还是一个Const
多看源码吧。。
StatusBar
final double statusBarHeight = MediaQuery.of(context).padding.top;
处理安卓/IOS系统中文本缩放对Flutter文字的影响以及根据App的文字大小设置某个页面的文字大小
获取MediaQuery并且对它的textScaleFactor进行重定义
下面是实现
import 'dart:math' as math;
import 'package:flutter/material.dart';
class NoScaleTextWidget extends StatelessWidget {
final Widget child;
const NoScaleTextWidget({
Key key,
@required this.child,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaxScaleTextWidget(
max: 1.0,
child: child,
);
}
}
class MaxScaleTextWidget extends StatelessWidget {
final double max;
final Widget child;
const MaxScaleTextWidget({
Key key,
this.max = 1.2,
@required this.child,
}) : super(key: key);
@override
Widget build(BuildContext context) {
var data = MediaQuery.of(context);
var scale = math.min(max, data.textScaleFactor);
return MediaQuery(
data: data.copyWith(textScaleFactor: scale),
child: child,
);
}
}
class ScaleTextWidget extends StatelessWidget {
final double scale;
final Widget child;
const ScaleTextWidget({
Key key,
@required this.scale,
@required this.child,
}) : super(key: key);
@override
Widget build(BuildContext context) {
var data = MediaQuery.of(context);
var scale = this.scale ?? data.textScaleFactor;
return MediaQuery(
data: data.copyWith(textScaleFactor: scale),
child: child,
);
}
}
使用方式如下,当然你也使用这个来实现对某个页面字体大小缩放的功能(比如app里面的有调整字体大小)
return MaterialApp(
builder: (c, w) {
//不应用系统的字体缩放
return NoScaleTextWidget(
child: w,
);
},
home: child,
);
最后放上 Flutter_Candies,如果你觉得有什么问题也是常常被萌新问到的,请告诉我,我会增加到汇总当中.
网友评论