Flutter学习笔记第二课-基础组件及布局

Flutter一切皆组件!

Dart基础语法可以参看这个网址: https://juejin.im/post/5dac7b93e51d45248c7b5182
组件详细的属性资料可以参看这个网址: https://book.flutterchina.club/

用Android布局的角度来看Flutter

Flutter控件 Android控件
AppBar ActionBar/ToolBar
ListView,GridView ListView/RecyclerView
Text TextView
Center ViewGroup
Container RelativeLayout
FloatingActionButton FloatingActionButton(design库里面的)
BottomNavigationBar BottomNavigation(design库里面的)
RaisedButton/Button Button
Column LinearLayout的android:orientation="vertical"
Row android:orientation="horizontal"
DecorationImage ImageView
Image ImageView
Stack FrameLayout/RelativeLayout
Algin alginParentXXX属性
resizeToAvoidBottomPadding android:windowSoftInputMode=”adjustResize属性
SingleChildScrollView ScrollView
Stack FrameLayout
SizeBox Layout固定宽高
Alignment 对齐方式
CustomScrollerView,slivers 复杂的滑动嵌套布局
SliverAppBar CollapsingToolbarLayout,实现AppBar展开/收起的功能, 相对于 AppBar 位置的固定的应用最上面的;而 SliverAppBar 是可以跟随内容滚动的。
Positioned 确定某一个View的具体坐标
Expanded Row、Column、Flex会被Expanded撑开,充满主轴可用空间。
Clip 小碎片,类似流式布局里面的Item
Warp 包裹的小部件超过屏幕宽度后换行
Step 步骤,类似快递物流效果
Card 类似CardView效果
ClipRRect 给图片加圆角
ListTile 固定样式的view 左边图片 右边可设置标题 副标题
DataTable 表格 参考
PaginatedDataTable 分页表格参考

Flutter控件本身通常由许多小型、单用途的控件组成,结合起来产生强大的效果,例如,Container是一种常用的控件,由负责布局、绘画、定位和大小调整的几个控件组成,具体来说,Container是由LimitedBox、ConstrainedBox、 Align、Padding、DecoratedBox和Transform控件组成,而不是将Container子类化来产生自定义效果,您可以用这种新颖的方式组合这些以及其他简单的控件。

在写应用程序时,经常会使用StatelessWidget和StatefulWidget编写新控件,两者的差别在于你是否要管理控件的状态。一个控件的主要任务是实现build函数,定义控件中其他较低层次的控件。build函数将依次构建这些控件,直到底层渲染对象。

  • Scaffold

Scaffold 实现了基本的Material Design布局结构。也就是说, MaterialApp 的 child 是 Scaffold Widget。
在Material设计中定义的单个界面上的各种布局元素,在 Scaffold 中都有支持,比如 左边栏(Drawers)、snack bars、以及 bottom sheets。
Scaffold 有下面几个主要属性:

1、appBar:显示在界面顶部的一个 AppBar,也就是 Android 中的 ActionBar 、Toolbar。
2、body:当前界面所显示的主要内容 Widget。
3、floatingActionButton:Material设计中所定义的 FAB,界面的主要功能按钮。
4、persistentFooterButtons:固定在下方显示的按钮,比如对话框下方的确定、取消按钮。
5、drawer:侧边栏控件。
6、backgroundColor: 内容的背景颜色,默认使用的是 ThemeData.scaffoldBackgroundColor 的值。
7、bottomNavigationBar: 显示在页面底部的导航栏。
8、resizeToAvoidBottomPadding:类似于 Android 中的
9、android:windowSoftInputMode=”adjustResize”,控制界面内容 body 是否重新布局来避免底部被覆盖了,比如当键盘显示的时候,重新布局避免被键盘盖住内容。默认值为 true。

  • Appbar

AppBar 和 SliverAppBar 是Material Design中的 App Bar,也就是 Android 中的 Toolbar,关于 Toolbar 的设计指南请参考Material Design中 Toolbar 的内容。
AppBar 和 SliverAppBar 都是继承StatefulWidget 类,都代表 Toobar,二者的区别在于 AppBar 位置的固定的应用最上面的;而 SliverAppBar 是可以跟随内容滚动的。

他们的主要属性如下:
1、 leading:在标题前面显示的一个控件,在首页通常显示应用的 logo;在其他界面通常显示为返回按钮
2、 title: Toolbar 中主要内容,通常显示为当前界面的标题文字。
3、actions:一个 Widget 列表,代表 Toolbar 中所显示的菜单,对于常用的菜单,通常使用。4、IconButton 来表示;对于不常用的菜单通常使用 PopupMenuButton 来显示为三个点,点击后弹出二级菜单。
5、 bottom:一个 AppBarBottomWidget 对象,通常是 TabBar。用来在 Toolbar 标题下面显示一个 Tab 导航栏。
6、elevation:纸墨设计中控件的 z 坐标顺序,默认值为 4,对于可滚动的 SliverAppBar,当 SliverAppBar 和内容同级的时候,该值为 0, 当内容滚动 SliverAppBar 变为 Toolbar 的时候,修改 elevation 的值 flexibleSpace:一个显示在 AppBar 下方的控件,高度和 AppBar 高度一样,可以实现一些特殊的效果,该属性通常在 SliverAppBar 中使用
7、backgroundColor:APP bar 的颜色,默认值为 ThemeData.primaryColor。改值通常和下面的三个属性一起使用
8、 brightness:App bar 的亮度,有白色和黑色两种主题,默认值为 ThemeData.primaryColorBrightness
9、 iconTheme:App bar 上图标的颜色、透明度、和尺寸信息。默认值为 ThemeData.primaryIconTheme
10、 textTheme: App bar 上的文字样式。默认值为 ThemeData.primaryTextTheme
11、 centerTitle: 标题是否居中显示,默认值根据不同的操作系统,显示方式不一样

基本组件

ClipRRect 给图片加圆角


 child: ClipRRect(
                      borderRadius: BorderRadius.only(
                        topLeft: Radius.circular(4.0),
                        topRight: Radius.circular(4.0),
                      ),
                      child: Image.network(
                        'http://img3.3lian.com/2013/c4/95/d/18.jpg',
                        fit: BoxFit.cover,
                      ),
                    ),

  • Container
    容器,一个常用的控件,由基本的绘制、位置和大小控件组成。负责创建矩形的可视元素,可以用BoxDecoration来设计样式,比如背景、边框和阴影,Container也有边距、填充和大小限制,另外,还可以在三维空间利用矩阵进行变换。

没有子控件的容器尽可能大,除非传入的大小约束是无限的,在这种情况下,它们尽可能小。有子控件的容器将自己的尺寸给他们的孩子。我们可以通过width、height和 constraints属性控制size。

  • BoxDecoration
    装饰器,可以用来修饰其他的组件,和Android里面的shape很相似
    const BoxDecoration({
    this.color,//背景色
    this.image,//图片
    this.border,//描边
    this.borderRadius,//圆角大小
    this.boxShadow,//阴影
    this.gradient,//过度效果
    this.backgroundBlendMode,
    this.shape = BoxShape.rectangle,//形状,BoxShape.circle和borderRadius不能同时使用
    })

  • SizedBox
    SizedBox控件能强制子控件具有特定宽度、高度或两者都有
    类似线性布局制定高宽
 body: new SizedBox(
        width: 250.0,
        height: 250.0,
        child: new Container(
          decoration: new BoxDecoration(
            backgroundColor: Colors.lightBlueAccent[100],
          ),
        ),
      ),
    );

  • AspectRatio
    AspectRatio控件能强制子小部件的宽度和高度具有给定的宽高比,以宽度与高度的比例表示。
 body: new AspectRatio(
        aspectRatio: 3.0 / 2.0,
        child: new Container(
          decoration: new BoxDecoration(
            backgroundColor: Colors.lightBlueAccent[100],
          ),
        ),
      ),
    );

  • Row
    flex水平布局控件,能够将子控件水平排列,是基于Web的flexbox的布局模式设计的。
    Row子控件有灵活与不灵活的两种,Row首先列出不灵活的子控件,减去它们的总宽度,计算还有多少可用的空间。然后Row按照Flexible.flex属性确定的比例在可用空间中列出灵活的子控件。要控制灵活子控件,需要使用Expanded控件。
    注意该控件不支持滑动,如果子控件超过剩余空间,会报错,如果想支持水平滑动,考虑使用ListView。
    如果只有一个子控件,可以使用 Align or Center控件定义该子控件位置。
new Row(
  children: [
    new Expanded(
      child: new Text('Deliver features faster', textAlign: TextAlign.center),
    ),
    new Expanded(
      child: new Text('Craft beautiful UIs', textAlign: TextAlign.center),
    ),
    new Expanded(
      child: new FittedBox(
        fit: BoxFit.contain, // otherwise the logo will be tiny
        child: const FlutterLogo(),
      ),
    ),
  ],
)

  • Column
    flex垂直布局控件,能够将子控件垂直排列。
    用法与Row控件一样。

  • Image
    显示图像的控件,Image控件有多种构造函数:
    new Image,用于从ImageProvider获取图像。
    new Image.asset,用于使用key从AssetBundle获取图像。
    new Image.network,用于从URL地址获取图像。
    new Image.file,用于从File获取图像。

Image里面的BoxFit参数介绍:(相当于Android的ImageView的scaleType参数)

fill 通过篡改原始宽高比来填充目标box
contain 在尽可能大的情况下,仍然将源完全包含在目标框中。
cover 尽可能小,同时仍然覆盖整个目标框。
fitWidth 确保显示源的全部宽度,而不管这是否意味着源垂直溢出目标框。
fitHeight 确保显示源的全部高度,而不管这是否意味着源水平地溢出目标框。
none 在目标框中对齐源(默认为居中),并放弃位于框外的源的任何部分。源图像未调整大小。
scaleDown 在目标框中对齐源(默认为居中),如果需要,将源缩小以确保源适合该框。这与contain的内容相同,如果该内容会收缩图像,那么它就是none。

-MainAxisAlignment和CrossAxisAlignment简介
MainAxisAlignment(主轴)和CrossAxisAlignment(交叉轴)常用于Row和Column控件中,主要是用来控制子控件排列的位置,并可以配合textDirection和verticalDirection属性来控制子控件排列的方向及改变MainAxisAlignment和CrossAxisAlignment的起始位置。

enum MainAxisAlignment {
 //将子控件放在主轴的开始位置
  start,  
   //将子控件放在主轴的结束位置
  end,
  //将子控件放在主轴的中间位置
  center,
  //将主轴空白位置进行均分,排列子元素,手尾没有空隙
  spaceBetween,
  //将主轴空白区域均分,使中间各个子控件间距相等,首尾子控件间距为中间子控件间距的一半
  spaceAround,
  //将主轴空白区域均分,使各个子控件间距相等
  spaceEvenly,
}

  • Expanded组件可以使Row、Column、Flex等子组件在其主轴方向上展开并填充可用空间(例如,Row在水平方向,Column在垂直方向)。如果多个子组件展开,可用空间会被其flex factor(表示扩展的速度、比例)分割
  • Text
    用来显示文本的控件,当然还有很多样式,具体请看源码
      new Text("hello_word",
            textDirection: TextDirection.ltr,
            style: TextStyle(
              decoration: TextDecoration.overline,
              fontSize: 40.0,
              fontWeight: FontWeight.bold,
              color: Colors.black87,
            ))

  • Icon
    图标控件,按照IconData中所描述的规则绘制,显示Material中预定义的IconDatas。
 new Icon(Icons.pool, size: 32.0, color: Colors.white),

最基础的HelloWold代码。

import 'package:flutter/material.dart';
void main () => runApp(MyApp());

class MyApp extends StatelessWidget{
  @override
  Widget build(BuildContext context ){
      return MaterialApp(
        title:'Text widget',
        home:Scaffold(
          body:Center(
          child:Text(
           'HelloWold',
           textAlign:TextAlign.left,
           overflow:TextOverflow.ellipsis,
           maxLines: 1,
           style: TextStyle(
               fontSize:25.0,
               color:Color.fromARGB(255, 255, 150, 150),
               decoration:TextDecoration.underline,
               decorationStyle:TextDecorationStyle.solid,
            ),
           )
          ),
        ),
      );
  }
}

Container(容器控件)在Flutter是经常使用的控件,它就相当于我们HTML里的

标签
bottomCenter:下部居中对齐。
botomLeft: 下部左对齐。
bottomRight:下部右对齐。
center:纵横双向居中对齐。
centerLeft:纵向居中横向居左对齐。
centerRight:纵向居中横向居右对齐。
topLeft:顶部左侧对齐。
topCenter:顶部居中对齐。
topRight: 顶部居左对齐

TextAlign属性就是文本的对齐方式,它的属性值有如下几个
center: 文本以居中形式对齐。
left:左对齐,经常使用,让文本居左进行对齐。
right :右对齐。
start:以开始位置进行对齐,类似于左对齐。
end: 以为本结尾处进行对齐,不常用。类似右对齐.

overflow属性是用来设置文本溢出时,它有几个常用的值供我们选择。
clip:直接切断,剩下的文字就没有了,感觉不太友好,体验性不好。
ellipsis: 在后边显示省略号。
fade: 溢出的部分会进行一个渐变消失的效果,当然是上线的渐变,不是左右的。

Image图片组件的使用

Image.asset: 加载资源图片,就是加载项目资源目录中的图片,加入图片后会增大打包的包体体积,用的是相对路径。
Image.network: 网络资源图片,意思就是你需要加入一段http://xxxx.xxx的这样的网络路径地址。
Image.file: 加载本地图片,就是加载本地文件中的图片,这个是一个绝对路径,跟包体无关。
Image.memory: 加载Uint8List资源图片,这个我目前用的不是很多,所以没什么发言权。

import 'package:flutter/material.dart';
void main () => runApp(MyApp());

class MyApp extends StatelessWidget{
  @override
  Widget build(BuildContext context ){
      return MaterialApp(
        title:'Text widget',
        home:Scaffold(
          body:Center(
          child:Container(
            child:new Image.network(
              'https://file.40017.cn/groundtraffic/ticketmachine/img/apple_index_01.png',
              scale:1.0,
            ),
            width:300.0,
            height:200.0,
            color: Colors.lightBlue,
          ),
          ),
        ),
      );
  }
}

fit属性的设置

fit属性可以控制图片的拉伸和挤压,这些都是根据图片的父级容器的。

  • BoxFit.fill:全图显示,图片会被拉伸,并充满父容器。

  • BoxFit.contain:全图显示,显示原比例,可能会有空隙。

  • BoxFit.cover:显示可能拉伸,可能裁切,充满(图片要充满整个容器,还不变形)。

  • BoxFit.fitWidth:宽度充满(横向充满),显示可能拉伸,可能裁切。

  • BoxFit.fitHeight :高度充满(竖向充满),显示可能拉伸,可能裁切。

  • BoxFit.scaleDown:效果和contain差不多,但是此属性不允许显示超过源图片大小,可小不可大。

ListView 列表组件

final List products = List.generate(
    20, (i) => Product('商品 ${i+1}','这是一个商品详情,编号为:${i+1}')
  );

class Product{
  final String title;  //商品标题
  final String description;  //商品描述
  Product(this.title, this.description);
}

class ProductList extends StatelessWidget{
  final List products;
  ProductList({Key key,@required this.products}):super(key:key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title:Text('商品列表')),
      body:ListView.builder(
        itemCount:products.length,
        itemBuilder: (context,index){
          return ListTile(
            title:Text(products[index].title),
            onTap:(){
              Navigator.push(context, MaterialPageRoute(
                  builder: (context) => ProductDetail(product: products[index])
                )
              );
            }
          );
        },
      )
    );
  }
}

感谢王伟desire ,技术胖的分享学习了flutter的基础组件和布局

你可能感兴趣的:(Flutter学习笔记第二课-基础组件及布局)