前言
我去终于学到组件了,赶紧把这些玩意都掌握然后开始实操了
官方组件教程
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
...
)
- 通过
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,
),
),
);
}
}
触碰屏幕后
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,
);
范例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,
);
范例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,
);
注意,对其的参考系是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,
),
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
)
)
]
)),
Q.E.D.
Comments | 1 条评论