前言

我去终于学到组件了,赶紧把这些玩意都掌握然后开始实操了
官方组件教程

1.Widget

Flutter中的Widget概念更加广泛,不仅可以表示UI元素,也可以表示一些功能性的组件
但是由于Flutter主要就是用于构建用户界面的,所以在大多数时候读者可以认为widget就是一个控件

  • 实际上Flutter中真正代表屏幕上显示元素的类是Element,也就是Widget只是藐视`Element的配置数据
  • 一个Widget对象可以对应多个Element对象
  • Widget类继承自DiagnosticableTree诊断树
  • Widget包含一个Key属性主要的作用是否在下一次build时复用旧的widget

StatelessWidget

用于不需要维护的场景,通常在build方法中通过嵌套其他Widget来构建UI,在构建过程中会递归的构建其嵌套的Widget

@required

命名参数中的必要参数要添加@required标注,这样有利于静态代码分析其进行检查
个人理解就是在调用的时候必须添加的参数

child或者children

倘若Widget要接收子Widget那么child或者children参数通常应当被放在参数列表的最后

Context

build方法有一个context参数,是BuildContext类的一个实例,表示当前widget在widget树中的上下文
每一个widget都会对应一个context对象

  • 实际上context是当前widget在widget树中位置中执行“相关操作”的一个句柄

可通过某种方法来寻找当前widget的父级widget
以下代码直接CV自教程

class ContextRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Context测试"),
      ),
      body: Container(
        child: Builder(builder: (context) {
          // 在Widget树中向上查找最近的父级`Scaffold` widget
          Scaffold scaffold = context.findAncestorWidgetOfExactType<Scaffold>();
          // 直接返回 AppBar的title, 此处实际上是Text("Context测试")
          return (scaffold.appBar as AppBar).title;
        }),
      ),
    );
  }
}

通过方法context.findAncestorWidgetOfExactType<Scaffold>(),子widget可以获取到上一级widget,从而获取父widget的title,也就是Text("Context测试")

StatefulWidget

  • StatefulWidget继承自Widget类,并且重写了createElement()方法

State

一个StatefulWidget类会对应一个State

  • State表示与其对应的StatefulWidget要维护的状态

在Widget树中获取State对象

由于StateWidget的具体逻辑都在其State中,所以很多时候需要获取StatefulWidget对应的State对象来调用一些方法

①通过Context获取

findAncestorStateOfType()
通过context的该方法,该方法可以从当前节点沿着widget树向上查找指定类型的StatefulWidget对应的State对象

  • 一般来说如果StatefulWidget的状态是私有的,那么代码中就不应该去直接获取State对象
  • 如果状态是希望暴露出的,则可以去直接获取其State对象
  • 但是findAncestorStateOfType()方法获取其StatefulWidget的状态是通用的
  • 如果State不希望暴露,则不提供of方法,否则会在StatefulWidget中提供一个of静态方法

②通过GlobalKey

1.首先给目标StatefulWidget添加GlobalKey

/定义一个globalKey, 由于GlobalKey要保持全局唯一性,我们使用静态变量存储
static GlobalKey<ScaffoldState> _globalKey= GlobalKey();
...
Scaffold(
    key: _globalKey , //设置key
    ...  
)
  1. 通过GlobalKey来获取State`对象
_globalKey.currentState.openDrawer()

使用GlobalKey的开销较大,如果有其它方法,不应该用GlobalKey

2.Material组件

Material应用程序以MaterialApp组件开始
引入需要在开头import
import 'package:flutter/material.dart';

3.Cupertino组件

import 'package:flutter/cupertino.dart';

4.状态管理

状态管理是响应式编程框架中永恒的主题
StatefulWidget的状态管理应该取决于实际情况来决定

  • 如果状态是用户数据,比如复选框的选中状态,滑块位置,应该由父Widget管理自己的状态
  • 如果状态是有关界面外观效果的,比如颜色,动画,那么由父Widget管理子Widget状态
  • 如果某个状态是不同Widget共享的,则采用混合管理

这里通过教程所给的一个范例来实操
第一个范例是父Widget管理自己的状态(通过触碰屏幕是否激活)
这里的状态是一个名叫_active的状态,然后通过触碰屏幕调用handleTap()函数来对该状态进行取反,然后再通过三元运算符?:来根据状态实时更新页面状态

class TapboxA extends StatefulWidget{
  TapboxA({Key key}) : super(key:key);
  @override
  _TapboxAState createState() => new _TapboxAState();
}

class _TapboxAState extends State<TapboxA>{
  bool _active = false;
  void _handleTap(){
    setState(() {
      _active = !_active;
    });
  }

  Widget build(BuildContext context){
    return new GestureDetector(
      onTap: _handleTap,
      child: new Container(
        child: new Center(
          child: new Text(
            _active ? "Active" : "Inactive",
            style: new TextStyle(fontSize: 32.0,color: Colors.white),
          ),
        ),
        width: 200.0,
        height: 200.0,
        decoration: new BoxDecoration(
          color: _active? Colors.green : Colors.red,
        ),
      ),
    );
  }
}

41.PNG
触碰屏幕后
42.PNG

5. Text组件

Text用于显示简单的文本,包含一些控制文本显示样式的一些属性

范例1(textAlign)

Text('A man without a man is a man man man man man man and a man men man man hahahahahahahaha',
 textAlign: TextAlign.left,
);

44.PNG

范例2(textAlign)

Text('A man without a man is a man man man man man man and a man men man man hahahahahahahaha',
 textAlign: TextAlign.right,
);

45.PNG

范例3(textAlign)

Text('A man without a man is a man man man man man man and a man men man man hahahahahahahaha',
 textAlign: TextAlign.center,
);

47.PNG

注意,对其的参考系是Text Widget本身,如果文本内容宽度不足一行,此时指定对齐是没有意义的

范例4(maxline处理方法)

Text('A man without a man is a man man man man man man and a man men man man hahahahahahahaha',
      maxLines: 1,
        overflow: TextOverflow.ellipsis,
      ),

48.PNG

TextStyle

用于指定文本显示的样式比如颜色,字体,粗细等
范例CV自范例

Text("Hello world",
  style: TextStyle(
    color: Colors.blue,
    fontSize: 18.0,
    height: 1.2,  
    fontFamily: "Courier",
    background: new Paint()..color=Colors.yellow,
    decoration:TextDecoration.underline,
    decorationStyle: TextDecorationStyle.dashed
  ),
);
  • fontFamily 为字体
  • fontSize 可以精确指定字体大小

6.TextSpan

Text组件中所有文本只能有一种样式,而TextSpan中可以不同部分按照不同的样式

范例

Text.rich(TextSpan(
        children: [
          TextSpan(
            text: "点击右侧链接进入合作伙伴 : "
          ),
          TextSpan(
            text:"https://www.google.com",
            style: TextStyle(
              color: Colors.blueAccent
            )
          )
        ]
      )),

410.PNG

Q.E.D.

知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议