Flutter Candies 一桶天下,kotlin 编程软件
大家想使用 ScrollController 无非 3 点。
1.下拉刷新,已提供demo
2.加载更多,已提供demo
3.控制列表滚动,已将属性暴露出来
使用常见问题
组件名字跟官方相同,所以当你们使用的时候,记住屏蔽掉官方的(太大胆了)
import 'package:flutter/widgets.dart' hide NestedScrollView;
对 NestedScrollView 不熟悉 这个建议先百度下,熟悉了官方的使用方式之后,再来看这些官方未解决的问题。
extended_image
Flutter 上面最能打的图片库(这样说没人打我吧) 掘金文章地址
主要功能
缓存网络图片
加载状态(正在加载,完成,失败)
拖拽缩放图片
图片编辑(裁剪,旋转,翻转)
图片预览(跟微信掘金一样)
滑动退出效果(跟微信掘金一样)
设置圆角,边框
使用常见问题
加载状态如何重写
设计原则是,如果你需要重写一个状态,就返回你想要的效果,否则请返回 null。下面是一个重写“正在加载”的例子
ExtendedImage.network(
item.imageUrl,
loadStateChanged: (ExtendedImageState state) {
if (state.extendedImageLoadState == LoadState.loading) {
return Container();
}
return null;
},
);
很多人因为在重写了 completed 状态而丢失了手势和裁剪功能,为此我新增了 ExtendedImageState.completedWidget。下面是重写 completed 状态而不丢失裁剪手势功能的例子。
ExtendedImage.network(
item.imageUrl,
loadStateChanged: (ExtendedImageState state) {
if (state.extendedImageLoadState == LoadState.completed) {
return Padding(
padding: EdgeInsets.all(10.0),
child: state.completedWidget,
);
}
return null;
},
);
path_provider 插件混合开发问题
请自行查看issue
extended_image_library
extended_image 的基础库,如果你只需要网络图片缓存功能,你可以只引用这个库
Image(
image: ExtendedNetworkImageProvider("", cache: true),
);
extended_text
富有中国特色强大功能的富文本 掘金文章地址
主要功能
快速构建富文本
支持选择(包括 WidgetSpan)以及自定义菜单
支持溢出文字自定义
支持自定义背景
使用常见问题
SpecialTextSpanBuilder 的使用
为了快速构建富文本,比如把 ‘[love]’ 这种文字变成表情图片,提供了 SpecialTextSpanBuilder。其原理很简单,就是根据你自己的规则,将文字转换成各种 InlineSapn(TextSpan,ImageSpan,WidgetSpan).
这里 build 方法是用入栈的方式遍历文字,createSpecialText 方法是用来根据你自己的规则创建 SpecialText 的。有一些用户可能觉得太复杂了,但是我这样考虑就是为了大家能根据自己业务的需求来自定义自己的规则。耐心看懂 demo,你可以快速的自定义自己的富文本
abstract class SpecialTextSpanBuilder
{
TextSpan build(String data,
{TextStyle textStyle, SpecialTextGestureTapCallback onTap})
SpecialText createSpecialText(String flag,
{TextStyle textStyle, SpecialTextGestureTapCallback onTap, int index});
}
extended_text_field
Flutters 上面唯一能支持输入内容是 WidgetSpan 的输入框 掘金文章地址
主要功能
快速构建富文本
支持选择(包括 WidgetSpan)以及自定义菜单
仿掘金推特点赞按钮
仿掘金推特点赞按钮,带数量滚动动画掘金文章地址
下拉刷新
可以在任何滚动场景中使用(包括 NestedScrollView)的自定义下拉刷新组件, 只提供了下拉刷新的状态,你可以最大化的自定义自己的效果而不用拘泥于组件本身提供。你可以根据状态距离,构建出任何你想要的效果。demo 里面的 4 种效果只是例子,欢迎大家 pr 更多更有趣的效果。掘金文章地址
使用常见问题
不满一屏幕,无法下拉刷新
iOS Bouncing 效果影响下拉刷新
这 2 个问题都可以通过设置列表的 physics 来解决,我这里提供了 AlwaysScrollableClampingScrollPhysics。
///in case list is not full screen and remove ios Bouncing
class AlwaysScrollableClampingScrollPhysics extends ClampingScrollPhysics {
const AlwaysScrollableClampingScrollPhysics({ScrollPhysics parent})
: super(parent: parent);
@override
AlwaysScrollableClampingScrollPhysics applyTo(ScrollPhysics ancestor) {
return AlwaysScrollableClampingScrollPhysics(parent: buildParent(ancestor));
}
@override
bool shouldAcceptUserOffset(ScrollMetrics position) {
return true;
}
}
扩展列表
支持特殊布局,内存清除以及可视区域 Indexes 变化追踪。更多详情
回收图片缓存
collectGarbage: (List<int> indexes) {
///collectGarbage
indexes.forEach((index) {
final item = listSourceRepository[index];
if (item.hasImage) {
item.images.forEach((image) {
final provider = ExtendedNetworkImageProvider(
image.imageUrl,
);
provider.evict();
});
}
});
},
|
|
|
| |
| --- |
瀑布流
高性能的瀑布流布局,喜欢的瀑布流的小伙伴赶快收藏起来。
|
|
| |
| --- |
列表加载更多
继承了UWP的加载更多思想的作品,将 UI 跟数据源的契约完美打通,你只要写过一次,你就会爱上这种方式,新增支持瀑布流。掘金文章地址
extended_tabs
支持 TabBarView 的联动,就是说二级 TabBarView 不能滑动了,就看一级能不能滑动,能滑动就滑动一级的 掘金文章地址
路由注解
轻巧灵活的路由注解工具,一行命令完成路由映射. 掘金文章地址
Json转换Dart实体类工具
使用 C#以及 Flutter 构建的 json 转换 dart 实体类工具,提供超级多的平台选择,大气的 ui 界面(偷笑.gif) 掘金文章地址
| 平台 | 语言 | 描述 | 代码/安装包地址 |
| --- | --- | --- | --- |
| windows | C# | uwp 构建,运行环境 windows10,x86/x64 | windows-uwp.zip |
| windows | C# | wpf 构建,运行环境 windows10/windows8/widnows7,x86/x64 | windows-wpf.zip |
| windows | dart | flutter 构建, 使用官方方式编译,x64 ,debug 版本 | windows-x64-flutter.zip |
| windows | dart | flutter 构建, 使用go-flutter编译,x64 ,debug 版本 | windows-x64-go-flutter.zip |
| mac | dart | flutter 构建,使用go-flutter编译(官方方式,未找到产物) | mac-go-flutter.zip |
| web | C# | silverlight构建, 需要安装 silverlight 插件,有浏览器限制 | 网页地址和带字体文件网页地址 |
| web | dart | flutter-web构建 | 网页地址 |
| linux | dart | flutter 构建, 使用官方方式编译,(没有环境测试,假装可以用) | 代码地址 |
从哪里上手 Flutter
Flutter中国官方网站,Flutter 官方明媒正娶,从入门到深入,各种资源应有尽有。如果你准备入手 Flutter,这应该是你必看的网站。
萌新问问题
每个人都从萌新而来,如果你想开森的写代码,自己解决问题是必须的
如果实在无法自己解决,可以求助于大佬,但是请注意提问方式,毕竟好沟通能节约双方的时间,大佬也要工作也要吃饭。
怎么找插件
把你的想要效果的插件的名字或者其他平台的组件叫什么名字,转为为英文,到pub 上面搜索,分高的使用的人多,相对就比较稳定更好。
安卓下载各种东西慢
我们经常运行别人组件的时候,发现各种下载失败,各种下载缓慢 请使用国内镜像,飞一般的赶脚。
替换 google()和 jcenter()
google()
jcenter()
替换为下面
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/jcenter' }
maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
替换 grade 下载地址 将上面的替换成下面镜像
#distributionUrl=https://services.gradle.org/distributions/gradle-5.1.1-all.zip
#csdn 镜像
distributionUrl=https://downloads.gradle-dn.com/distributions/gradle-5.1.1-all.zip
为啥设置 Size 没有效果
在开发中,我们发现给组件设置了大小,但是却没有效果。举个栗子,在 Appbar 的 leading/actions 中,我们想直接设置宽高是不可能的。 我们需要使用 UnconstrainedBox 来移除父 widget 对子大小的限制,如下代码
AppBar(
title: Text(widget.title),
leading: UnconstrainedBox(
child: Container(
width: 50.0,
height: 10.0,
color: Colors.red,
),
),
),
键盘弹出的时候,怎么把布局顶上去,而不遮住布局
通过下面代码获取键盘高度(放心键盘弹出或者收起的时候都会触发 build)
double keyboardHeight = MediaQuery.of(context).viewInsets.bottom;
然后你的布局大概就是下面这样
Column(
children: <Widget>[
///你的布局
Expanded(
child: Container(),
),
///顶起你的布局
Container(
height: keyboardHeight,
)
],
);
其实这个我也是在源码里面scaffold.dart中看到的,抄作业很重要
关键代码
并且在_ScaffoldLayout 中增加了这个高度
pub.dev 慢,打不开?!
中国镜像你在等什么呢,学起来
国际化之后设置 hintText,光标位置不一致
issue地址 通过设置下面代码解决,全局设置文字主题
textTheme: theme.textTheme.copyWith(
subhead: theme.textTheme.subhead
.copyWith(textBaseline: TextBaseline.alphabetic)),
我的文本设置了溢出,为啥没有效果
我们经常听到的就是为什么我的文本设置了溢出显示,但是它却显示黄色溢出警告了? 对于文本 Text 来说,如果它的父 Widget 没有给它做大小限制,它默认是无限长的 我们解决的方法如下。
给它设置个大小,如果无效请参考 为啥设置 Size 没有效果 (特别注意,Row/Column 嵌套的时候。你需要从最外面一层就给内层限定大小,参考下面一条)
Row/Column 中,给它设置 Expaned/Flexible 这样告诉文本,你的大小是,其他 widget 剩下的那空间。 Expaned/Flexible 都有这个作用,但是它们的区别是什么呢。给你们看 2 张图你就明白了。
return Row(
children: <Widget>[
Flexible(
child: Text(
"我是一个很短的文本",
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 12),
),
),
Container(
color: Colors.red,
width: 100.0,
)
],
);
return Row(
children: <Widget>[
Expanded(
child: Text(
"我是一个很短的文本",
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 12),
),
),
Container(
color: Colors.red,
width: 100.0,
)
],
);
Expaned/Flexible 两者的区别就在于,Expanded 会强制占 100 剩余的空间,而 Flexible 可以自适应。当然他们最大也都是占 100 剩余的空间。
获取滚动组件中孩子的位置
更多的细节,你可以查看文章
官方的 Appbar 不好用
由于官方的 Appbar 增加了对 material 风格的设置,所以很多地方都有一些限制。其实也不能怪官方,这是一种设计规范。但是我们就是想自己骚怎么办呢?? 我之前写了个 my_app_bar.dart,之前一直放 gists 上面,不方便大家查看,现在也移入了??。这是一个简单的实现,看明白了代码原理之后,你可以扩展出更多适合自己的 appbar。
掘金斗鱼的那种首页滚动效果怎么做?
因为有好几个人问过,所以我写了个简单的demo。主要是靠 NotificationListener 来监听滚动来控制头部。
黄色警告 ? 一定要管吗?
不是每一种警告,都是一定要管的。警告只是官方告诉你需要注意这点,这就是为什么 Release 下面不会出现警告。警告不等于错误。
我这里举一个栗子。NestedScrollView 的 body 其实是 SliverFillRemaining 包住的,它会跟着一起滚动。但是我们这里布局里面是一个 Tabbar,它是一个有固定高度的组件,当它超出屏幕的时候就会出现警告。但是事实上,这种警告并不能影响我们的使用。
push/pop 的时候页面重新 build
如果你是因为页面重新 build 就影响你的业务,那应该好好检查下业务逻辑代码。build 的原因是 route 变化时候的动画,以及 NavigatorState 中 Overlay(实际就是 Stack),route 位置变化而引起的页面 build。
ListView 嵌套,shrinkWrap 的使用
Listview 里面嵌套 Listview,是我经常看到过的,会报错。然后就会有人说 把这个设置成 shrinkWrap 设置成 true。下面我们来看看这个属性的意思。
/// Whether the extent of the scroll view in the [scrollDirection] should be determined by the contents being viewed.
///
/// If the scroll view does not shrink wrap, then the scroll view will expand to the maximum allowed size in the [scrollDirection]. If the scroll view has unbounded constraints in the [scrollDirection], then [shrinkWrap] must be true.
///
/// Shrink wrapping the content of the scroll view is significantly more expensive than expanding to the maximum allowed size because the content can expand and contract during scrolling, which means the size of the scroll view needs to be recomputed whenever the scroll position changes.
///
/// Defaults to false.
final bool shrinkWrap;
设置 shrinkWrap 为 true,scrollview 的范围将是全部内容的高度,否则是为 viewport 的高度。列表或者说 ScrollView 其实有一个可视区域的概念(Viewport),就是滚动时候的可见的部分,这个区域的大小往往需要你自己告诉他或者它的父亲告诉它,超出这个范围的内容会根据情况进行回收。
我们这里看到为什么直接使用 Listview 嵌套 Listview 会报错了。因为 Listview 本身是无高度限制的,而你把一个 Listview 放在一个 Listview 里面,里面的 Listview 的 viewport 是无从得知的。那怎么办呢? 那只能使用设置 shrinkWrap 为 true,让里面的 Listview 的高度其实等于自己全部内容的高度。这样外面 Listview 就能知道这个孩子的高度了。
设置 shrinkWrap 为 true,更消耗性能。因为在滚动的时候都需要重新去计算高度是否变化。并且不会回收可视区域之外的内容。
使用 ListView 嵌套 Listview 的场景往往都能使用 Sliver 系列来解决,详情请看下一个问题
Sliver 一生之敌?一生之爱?
群里萌萌说的时候,我有点惊讶道,但是 Sliver 确实是经常有人问到的。
Sliver 系列的东东很多,我们下面来一一介绍一下。
CustomScrollView 是 Sliver 组件的老祖宗,全部的 Sliver 都放在这个里面,大家别看 ListView/GridView 跟他们不一样,其实里面还是 Sliver 系列,只是不能将他们直接放到 Sliver 里面,也不建议这样做。
NestedScrollView这个也是大家经常使用到的,其实里面是一个 CustomScrollView,它的 headers 是 Sliver 的数组,body 是被包裹在 SliverFillRemaining 中的
SliverList 列表跟 ListView 用法差不多,跟 CustomScrollView 一起使用
SliverFixedExtentList, 比 SliverList 多一个就是相同的 Extent,这样性能会更好,跟 CustomScrollView 一起使用
SliverPrototypeExtentList 主轴上面有相同的 Extent,跟 SliverFixedExtentList 灵活,不需要设置 Extend,而是根据 prototypeItem 来获取 Extent
SliverGrid, 可以设置每行的个数的 Grid,跟 CustomScrollView 一起使用
SliverPadding,跟 Padding 一样的使用,区别是 child 变成了 sliver
SliverPadding(
sliver: SliverList(),
padding: EdgeInsets.all(5.0),
);
SliverPersistentHeader 非常好用的组件,SliverAppBar 就是用这个实现的。这个组件的特点是可以创建出随着滑动变化的可以 Pinned 的元素,大家经常用的什么吸顶组件可以用这个很方便的构建,前面讲到的自定义 SliverAppbar(my_app_bar.dart)就是利用它实现的。
SliverAppBar 跟 Appbar 的最大区别就可以根据滚动状态来折叠内容,主要是由状态栏高度+导航栏高度+折叠高度组成
SliverToBoxAdapter 当你想把一个非 Sliver 的 Widget 放在 CustomScrollview 里面的时候,你需要用这个包裹一下。
SliverSafeArea 为了防止各种边界的越界,比如说越过顶部的状态栏
评论