Flutter常用组件

工程中遇到的部分常用的或者必要组件记录

  • WillPopScope

class WillPopScope extends StatefulWidget {
  const WillPopScope({
    Key key,
    @required this.child,
    @required this.onWillPop,
  }) : assert(child != null),
       super(key: key);

参数onWillPop用来监听当用户按下返回键时child是否关闭,类型:typedef WillPopCallback = Future<bool> Function();限定返回值的方法,可用来实现类似双击返

  • BottomNavigationBar

底部导航栏,类似TabBar

  • PageView

类ViewPage
PageView+CustomScrollView时,翻页rebuild的问题可以通过给CustomScrollView设置不同的Key来解决
其他ScrollableView应该也可以(待测试)

  • Theme常用属性

 theme: new ThemeData(
          primarySwatch: Colors.blue,//主色板:不需要指定颜色的空间大多使用该值,如ListView等的下拉弧线。
          primaryColor: Colors.red,//原色:
          primaryIconTheme: IconThemeData(color: Colors.black),//Icon的颜色,仅限自带Icons中图标
          primaryTextTheme: TextTheme(title: TextStyle(color: Colors.black, fontFamily: "Aveny")),
          textTheme: TextTheme(title: TextStyle(color: Colors.black))),
      home: new InstaHome(),
  • Flexible

在行和列中使用该控件包裹,可以设置行和列子组件的大小比例,类似权重表示行或者列所占的比例,利用flex属性控制行或者列中内容的收缩或者扩展模式。

  • MainAxisAlignment

如何在弹性布局中沿主轴放置子项,通常默认为MainAxisAlignment.start则通常从主轴的开始位置开始放置子组件(若为行则水平方向,列则竖直方向)。该属性不仅于Row和Column,部分其他组件亦可用。

  • CrossAxisAlignment

类MainAxisAlignment,如何在弹性布局中沿横轴放置子项。

  • MainAxisSize

主轴尺寸如min、max,常与MainAxisAlignment搭配使用

  • MediaQuery

要了解当前媒体的大小(例如,包含您应用程序的窗口),可以从MediaQuery.of:MediaQuery.of(context).size返回的MediaQueryData中读取MediaQueryData.size属性。文档入口
MediaQuery.of(context).padding.top//顶部statusBar高度

SizedBox(child: XXX(),height: deviceSize.height * 0.15, )依据屏幕比例设置组件高度
  • BoxDecoration

绘制边框。BoxDecoration类提供了多种绘制框的方法。该框具有边框,主体,并可以投射boxShadow。
BoxDecoration的形状可以是圆形或矩形。如果是矩形,则borderRadius属性控制角的圆度。
BoxDecoration的主体是分层绘制的。最底层是颜色,它填充了该框。在此之上的是渐变,渐变也填充了该框。最后是图像,其精确对齐由DecorationImage类控制。
shape或borderRadius不会修剪装饰的Container的子级。如果需要剪辑,请插入剪辑小部件(例如ClipRect,ClipRRect,ClipPath)作为Container的子级。请注意,裁剪可能会导致性能损失。也可以看看:
DecoratedBox和Container,可以使用BoxDecoration对象配置的小部件。
CustomPaint,一个小部件,可让您绘制任意图形。
Decoration,可让您定义其他装饰的基类。

  • FractionallySizedBox

child按给的比例显示大小,若给定的宽高比不一致,则依据两者中小者显示

 FractionallySizedBox(
                  heightFactor: 0.5,
                  widthFactor: 0.5,
                  child: FlutterLogo(),
                )
  • RandomContainer

背景色自由变更的Container

  • DragTarget&Draggable

拖动目标控件&拖动控件

Draggable(
          child: Container(//可拖动控件原型
            decoration: BoxDecoration(
              shape: BoxShape.rectangle,
              color: Colors.blue,
            ),
            height: 100,
            width: 100,
          ),
          childWhenDragging: Container(//拖动时显示的Widget
            decoration: BoxDecoration(
              shape: BoxShape.rectangle,
              borderRadius: BorderRadius.circular(30),
              color: Colors.green,
            ),
            height: 100,
            width: 100,
//          color: Colors.red,
          ),
          feedback: Container(//原控件移动之后原地丢下的Widget
            decoration: BoxDecoration(
              shape: BoxShape.rectangle,
              color: Colors.red,
              borderRadius: BorderRadius.circular(30),
            ),
            height: 100,
            width: 100,
          ),
        )

DragTarget

DragTarget(
              builder: (BuildContext context, List<dynamic> accepted, List<dynamic> rejected) => Container(
                height: 200.0,
                width: 200.0,
                decoration: BoxDecoration(color: Colors.cyan),
                child: Center(//
                  child: Column(children: <Widget>[Text(accpeptedData.toString()),Text(rejectData.toString())],),
                ),
              ),
              onAccept: (int data) {//拖动到指定位置,且接收数据
                accpeptedData = data;
              },
              onLeave: (int data){//拖动到指定位置之后取消
                rejectData=data;
              },
            )
  • CircleAvatar

类似脚注或者其他注释,消息提示红点,登陆头像等。

  • Placeholder

组件占位符

  • Spacer

使用flex属性控制大小
Spacer小部件将占用任何可用空间,因此将包含Spacer的Flex容器上的Flex.mainAxisAlignment设置为MainAxisAlignment.spaceAround,MainAxisAlignment.spaceBetween或MainAxisAlignment.spaceEvenly不会产生任何可见效果:Spacer占用了所有空间 的额外空间,因此没有剩余可重新分配。
可用来调节Row、Colmun、Flex等组件

  • Visibility

visible: false控制组件是否可见

  • SearchDelegate

Scaffold中方法showSearch(),系统自带的辅助搜索功能,showSearch(context: context, delegate: DataSearch());需要自定义Delegate继承父Delegate且实现其中的方法如下

  @override
  List<Widget> buildActions(BuildContext context) {
    return [...];//类AppBar的Actions
  }

  @override
  Widget buildLeading(BuildContext context) {
    return ...;//头部类AppBar头部
  }

  @override
  Widget buildResults(BuildContext context) {
    return ..;//搜索结果
  }

  @override
  Widget buildSuggestions(BuildContext context) {
      return ...;//搜索提示,配合富文本之类的已输入的黑体未输入的灰体
  }

  • AnimatedIcons

已实现的动画转场效果如视频播放时暂停到播放的转换,menu到arrow的转换等

_controller = AnimationController(
      duration: const Duration(milliseconds: 300),
      value: 1.0,
      vsync: this,
    );
....
AnimatedIcon(
              icon: AnimatedIcons.close_menu,
              semanticLabel: 'close',
              progress: _controller.view,
            )

progress用来控制进度,

  • RichText&TextSpan

富文本

RichText(
              text: TextSpan(
                  text: suggestionList[index].substring(0, query.length),
                  style: TextStyle(
                      color: Colors.black, fontWeight: FontWeight.bold),//已输入的搜索部分
                  children: [
                    TextSpan(//未输入的部分
                        text: suggestionList[index].substring(query.length),
                        style: TextStyle(color: Colors.grey))
                  ]),
            )
  • Hero

直接使用该组件包裹希望制作动画的图片或者组件(两个页面都需要),再在两个Hero组件中添加tag标签,以便Flutter规划动画的路径。

  • Align

设置相对位置

alignment: Alignment.lerp(Alignment.centerRight, Alignment.bottomRight, 0.5),)

除已经预设好的位置还可以使用上面参数自定义位置,前两参数可理解为参数,最后一个为偏移量

CachedNetworkImage(
       imageUrl: url,
       placeholder: (context,url) => CircularProgressIndicator(),//加载中View
       errorWidget: (context,url,error) => new Icon(Icons.error),//加载失败的View
     ),

相较与Image.Network(),直接提供了加载结果的处理入口,ImageNetwork如下,跟自由度更高

Image.network(
                  '${Api.imgHeadHorizon}${model.backdropPath}',
                  height: imgHeight,
                  width: size.width,
                  fit: BoxFit.fill,
                  loadingBuilder: (context, widget, loadingProgress) {
                    if (loadingProgress != null) {//开始时为空需判断
                      //下面表达式中前者为当前已经下载的字节数,后者为字节总数,可通过除法获取百分比
                      if(loadingProgress.cumulativeBytesLoaded == loadingProgress.expectedTotalBytes){
                        print('(*^__^*) ');
                      }
                    }
                    return Container(color: Colors.cyan,);//如果没特殊要求直接返回widget就好。
                  },
  • Divider

分割线,对象

  • AnimatedCrossFade

AnimatedCrossFade(
      firstChild: first,
      secondChild: second,
      firstCurve: const Interval(0.0, 0.6, curve: Curves.fastOutSlowIn),
      secondCurve: const Interval(0.4, 1.0, curve: Curves.fastOutSlowIn),
      sizeCurve: Curves.fastOutSlowIn,
      crossFadeState: isExpanded ? CrossFadeState.showSecond : CrossFadeState.showFirst,
      duration: const Duration(milliseconds: 200),
    );

两个界面的过渡,比如加载图片时默认和加载完成的过渡,或者其他叠加布局时布局切换的过渡

扩展收缩的ListView或者Panel,若不是LIst可以考虑使用ExpansionTile

  • ListView&GridView滑动监听

          if (controller.position.extentAfter == 0) {
                        
          }

方法二
...

  • IgnorePointer

  • IgnorePointer会拦截将要进入自己内部的触摸事情,并向后传递

  • Matrix4

属性如下

//scale:缩放比例
Matrix4.diagonal3Values(2, 1, 1)
Matrix4.diagonal3(v.Vector3(2, 1, 1))
Matrix4.diagonal3(v.Vector3.array([2, 1, 1]))
//transform: 移动
Matrix4.translationValues(30, 0, 0)
Matrix4.translation(v.Vector3(30, 0, 0))
Matrix4.translation(v.Vector3.array([0, -30, 0]))
//rotationZ:绕Z轴旋转
//rotationX:绕X轴旋转
//rotationY:绕Y轴旋转
Matrix4.rotationZ(pi / 6)
Matrix4(cos(pi / 6), sin(pi / 6), 0, 0,-sin(pi / 6), cos(pi / 6), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)
//columns:设置一个新的矩阵
//compose:复合平移、旋转、缩放,形成新的状态
Matrix4.columns( Vector3 translation, Quaternion rotation, Vector3 scale) 
//copy:复制一个4*4的张量(矩阵)
//identity:恢复初始状态,也就是4*4的单位矩阵
//inverted:取相反的矩阵,就是反着来
//outer(合并)、skew(扭曲)、skewX(x轴扭曲)、skewY(y轴扭曲)、zero(置零矩阵)、fromList(将一个16位的一维数组转换成4*4的矩阵)
  • NotificationListener(widget) 监听其子View滑动状态。子View的滚动事件并发送通知

NotificationListener<ScrollNotification>(//只接受某个子类型的通知
          child: SingleChildScrollView(
            child: Column(
              children: <Widget>[
                Container(
                  height: 900,
                  width: double.infinity,
                  color: Colors.red,
                )
              ],
            ),
          ),
          onNotification: (_){print('1111111');},//返回true则事件不在传递,false则继续往父控件传递
        ),

child通常为scrollableView

  • ScrollStartNotification,它指示小部件已开始滚动。通常为最先接收到的Notification

  • 零个或多个ScrollUpdateNotifications(指示小部件已更改其滚动位置)

  • 零个或多个ScrollUpdateNotifications与零个或多个OverscrollNotifications混合,指示小部件未更改其滚动位置,因为更改会导致其滚动位置超出其滚动范围。如滚动到最顶部或者最底部

  • 与ScrollUpdateNotifications和OverscrollNotifications穿插的是零个或多个UserScrollNotifications,它们表示用户已更改其滚动方向。如水平滑动之后直接竖直滑动会调用UserScrollNotifications

  • ScrollEndNotification,它指示小部件已停止滚动。标志滚动事件结束
    一个UserScrollNotification,其ScrollDirection.idle的UserScrollNotification.direction。
    滑动事件从开始到结束 ScrollStartNotification--->UserScrollNotification(从无到有和从有到无都算变化)--->OverscrollNotification/ScrollUpdateNotifications--->ScrollEndNotification--->UserScrollNotification

  • notification.depth=0/1/...表示监听的深度,通常处理深度为0的及多层可滚动只处理当前子控件的滚动

  • CustomScrollView

结合了ScrollView和SliverAppBar(基于SliverPersistentHeader实现)的控件

 Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(//折叠头部
            title: Text('SliverDemoPage'),
            centerTitle: true,
            expandedHeight: 300,
            forceElevated: true,
             pinned: true,//折叠后不消失
            floating: true,// 当有下滑手势的时候,就会显示 AppBar
            snap: true,// 当下滑到一定比例,会自动把 AppBar 展开
            flexibleSpace: FlexibleSpaceBar(
              collapseMode: CollapseMode.parallax,
              background: Image.asset(
                'images/joker.jpg',
                fit: BoxFit.fill,
              ),
            ),
          ),
          SliverFillRemaining(child: Center(child: Text('填充剩余空间'),),)//填充剩余空间
        ],
      ),
    );

Slivers相关

  • SliverFillViewport
  • SliverFillRemaining
  • SliverFixedExtentList
  • SliverToBoxAdapter
  • SliverPadding
  • SliverPersistentHeader&SliverPersistentHeaderDelegate(SliverAppBar的内部实现)

若CustomScrollView底部横向和纵向滚动的冲突目前没有解决办法

  • NestedScrollView

  • SliverOverlapAbsorber
  • SliverOverlapInjector

Scrollbar


AnimationController

动画的控制器。
此类可让您执行以下任务:
向前或向后播放动画,或停止动画。
将动画设置为特定值。
定义动画的upperBound和LowerBound值。
使用物理模拟创建猛冲动画效果。
默认情况下,AnimationController在给定的持续时间内线性生成的值介于0.0到1.0之间。 每当运行您的应用的设备准备显示新帧时,动画控制器都会生成一个新值(通常,此速率约为每秒60个值)。

Listenable

维护侦听器列表的对象。
侦听器通常用于通知客户端对象已更新。
此接口有两种变体:
ValueListenable,一个使用当前值的概念扩展Listenable接口的接口。
动画,一个扩展ValueListenable接口以添加方向(正向或反向)概念的接口。
Flutter API中的许多类都使用或实现这些接口。 以下子类特别相关:
ChangeNotifier,可以将其子类化或混入以创建实现Listenable接口的对象。
ValueNotifier,它使用可变值实现ValueListenable接口,该可变值在修改后会触发通知。

CurvedAnimation

将曲线应用于另一个动画的动画。
当您想对动画对象应用非线性曲线时,特别是在动画前进和后退时想要不同的曲线时,CurvedAnimation很有用。
根据给定的曲线,CurvedAnimation的输出范围可能比其输入范围大。 例如,诸如Curves.elasticIn之类的弹性曲线将大大超出或低于默认范围0.0到1.0。

Interval

直到开始时为0.0的曲线,然后从开始处的0.0弯曲到结束处的弯曲(根据曲线),然后在结束处保持1.0。
间隔可用于延迟动画。 例如,使用Interval(开始时间设置为0.5,结束时间设置为1.0)的Interval的六秒钟动画实际上将变成三秒钟的动画,该动画在三秒钟后开始。

          Opacity(
            opacity: CurvedAnimation(
              parent: ReverseAnimation(animation),
              curve: const Interval(0.5, 1.0),// Curves.***(easeInOut)
            ).value,
            child: const Text('Select a Category'),
          ),

AnimatedWidget

当给定的Listenable更改值时重建的小部件。
AnimatedWidget最常与可收听的Animation对象一起使用,但可与任何Listenable(包括ChangeNotifier和ValueNotifier)一起使用。
AnimatedWidget对于否则为无状态的小部件最有用。 要使用AnimatedWidget,只需将其子类化并实现build函数。

  BackDropTitle({Key key, Listenable listenable}) : super(key: key, listenable: listenable);

  @override
  Widget build(BuildContext context) {
    //animation extends Listenable
    final Animation<double> animation = listenable;
    return DefaultTextStyle(
      style: Theme.of(context).textTheme.title,
      softWrap: false,
      overflow: TextOverflow.ellipsis,
      child: Stack(
        children: <Widget>[
          Opacity(opacity: CurvedAnimation(parent: ReverseAnimation(animation), curve: Curves.easeInOut).value)
        ],
      ),
    );
  }

RotatedBox

 RotatedBox(
                  quarterTurns: 1, //1顺时针90度,2顺时针180度,3 顺时针270度 ,4顺时针360度
                  child: Text("Hello world")
              ),

LayoutBuilder

大小不确定的布局,绘制时返回大小,可以根据大小返回不同布局

Material

 const Material({
    Key key,
    this.type = MaterialType.canvas,
    this.elevation = 0.0,
    this.color,
    this.shadowColor = const Color(0xFF000000),
    this.textStyle,
    this.borderRadius,
    this.shape,
    this.borderOnForeground = true,
    this.clipBehavior = Clip.none,
    this.animationDuration = kThemeChangeDuration,
    this.child,
  })

一个属性比较全的小控件,形状,圆角,裁剪等

ListTileTheme

一个继承的窗口小部件,它为该窗口小部件的子树中的ListTiles定义颜色和样式参数。
此处指定的值用于没有指定显式非null值的ListTile属性。
Drawer小部件为其子级指定一个tile主题,该主题将样式设置为ListTileStyle.drawer。
*了狗了 一万个小部件

PositionedTransition

Positioned的动画版本,采用特定的Animation <RelativeRect>在动画的整个生命周期中将孩子的位置从开始位置转换到结束位置。
仅当它是Stack的子代时才有效。
这是PositionedTransition小部件的图示,其由设置为Curves.elasticInOut的CurvedAnimation进行矩形动画处理:

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

推荐阅读更多精彩内容