336 lines
12 KiB
Markdown
336 lines
12 KiB
Markdown
# flutter 学习笔记
|
||
|
||
# 组件的使用
|
||
* Text文字组件
|
||
* `textAlign: TextAlign.start,` // 文本对齐方式
|
||
* `textDirection: TextDirection.ltr` // 文本方向
|
||
* `maxLines:1` // 最大行数
|
||
* `textScaleFactor: 1.5,` // 文字缩放
|
||
* `overflow: TextOverflow.ellipsis,` // 超出处理
|
||
* `style:`
|
||
* TextStyle组件
|
||
```dart
|
||
TextStyle(
|
||
color: Colors.blue,
|
||
fontSize: 18.0,
|
||
height: 1.2,
|
||
fontFamily: "Courier",
|
||
background: new Paint()..color=Colors.yellow,
|
||
decoration:TextDecoration.underline,
|
||
decorationStyle: TextDecorationStyle.dashed
|
||
),
|
||
```
|
||
* 文本接合,多个textSpan对文本进行修饰,然后拼合在一起
|
||
```dart
|
||
Text.rich(TextSpan(
|
||
children: [
|
||
TextSpan(
|
||
text: "https://flutterchina.club",
|
||
style: TextStyle(
|
||
color: Colors.blue
|
||
),
|
||
recognizer: _tapRecognizer
|
||
),
|
||
...
|
||
]
|
||
))
|
||
```
|
||
* 字体设置[链接]('https://book.flutterchina.club/chapter3/text.html')
|
||
* 按钮
|
||
* `RaisedButton` // 悬浮按钮
|
||
* `FlatButton` // 扁平按钮
|
||
* `OutlineButton` // 默认有边框
|
||
* `IconButton` // 可点击的icon
|
||
* `icon: Icon(Icons.thumb_up),`
|
||
* 前三个都可以加`.icon`然后属性变成`icon`和`label`
|
||
* 自定义
|
||
```dart
|
||
const FlatButton({
|
||
...
|
||
@required this.onPressed, //按钮点击回调
|
||
this.textColor, //按钮文字颜色
|
||
this.disabledTextColor, //按钮禁用时的文字颜色
|
||
this.color, //按钮背景颜色
|
||
this.disabledColor,//按钮禁用时的背景颜色
|
||
this.highlightColor, //按钮按下时的背景颜色
|
||
this.splashColor, //点击时,水波动画中水波的颜色
|
||
this.colorBrightness,//按钮主题,默认是浅色主题
|
||
this.padding, //按钮的填充
|
||
this.shape, //外形
|
||
@required this.child, //按钮的内容
|
||
})
|
||
```
|
||
* 图片
|
||
* pubspec.yaml配置
|
||
```yaml
|
||
assets:
|
||
- images/avatar.png
|
||
```
|
||
* 加载图片
|
||
```dart
|
||
Image(
|
||
image: AssetImage("images/avatar.png"),
|
||
width: 100.0
|
||
);
|
||
Image.asset("images/avatar.png",
|
||
width: 100.0,
|
||
)
|
||
Image(
|
||
image: NetworkImage(
|
||
"https://avatars2.githubusercontent.com/u/20411648?s=460&v=4"),
|
||
width: 100.0,
|
||
)
|
||
Image.network(
|
||
"https://avatars2.githubusercontent.com/u/20411648?s=460&v=4",
|
||
width: 100.0,
|
||
)
|
||
const Image({
|
||
...
|
||
this.width, //图片的宽
|
||
this.height, //图片高度
|
||
this.color, //图片的混合色值
|
||
this.colorBlendMode, //混合模式
|
||
this.fit,//缩放模式
|
||
this.alignment = Alignment.center, //对齐方式
|
||
this.repeat = ImageRepeat.noRepeat, //重复方式
|
||
...
|
||
})
|
||
```
|
||
* ICON
|
||
* `Icon(Icons.accessible,color: Colors.green,),`
|
||
* 使用自定义字体图标[链接]('https://book.flutterchina.club/chapter3/img_and_icon.html')
|
||
* Switch开关组件
|
||
* `value: true`
|
||
* `onChanged`
|
||
* Checkbox多选组件
|
||
* `value: true`
|
||
* `onChanged`
|
||
* Stack层叠组件
|
||
* 定位相对于父元素
|
||
* `alignment: Alignment.center` // 总体控制
|
||
* `alignment: Alignment(0,0)` // float(-1~1) 0,0居中
|
||
* `children: <Widget>[]`
|
||
* Align组件
|
||
* `alignment: Alignment.center` // 单独控制
|
||
* `alignment: Alignment(0,0)` // float(-1~1) 0,0居中
|
||
* `child: ` // 需要定位的子组件
|
||
* Positioned组件
|
||
* `left, bottom, top, right` // int 默认为0
|
||
* `child: ` // 需要定位的子组件image
|
||
* AspectRatio组件
|
||
* 默认横向占满父组件
|
||
* 可以用来控制图片
|
||
* `aspectTatio: 2.0/1.0` // 宽高比
|
||
* `child: ` // 子组件
|
||
* Card组件
|
||
* `margin: EdgeInsets.all(10)` // 外边距
|
||
* `child: ` // 子组件
|
||
* ClipOval组件
|
||
* 可以用来裁剪原型头像
|
||
* `child: ` // 子组件
|
||
* CircleAvatar组件
|
||
* 感觉可以自适应头像大小
|
||
* `backgroungImage: NetworkImage('src')`
|
||
* RaisedButton组件
|
||
* `child:` // 子组件
|
||
* `textColor: Theme.of(context).accentColor,` // 文字颜色
|
||
* `textColor: Colors.red,` // 文字颜色
|
||
* `onPressed: (){}` // 点击事件
|
||
* Warp组件
|
||
* 相对于父组件横向占满
|
||
* 可以自动换行
|
||
* `spacing: 10,` // 元素和元素之间的距离
|
||
* `runSpacing: 10` // 元素在纵轴之间的距离
|
||
* `alignment: WarpAlignment.srart` // 水平对齐方式
|
||
* `runAlignment: WarpAlignment.spaceAround` // 纵向对齐方式
|
||
* `direction: Axis.vertical` // 纵向排列
|
||
* SizedBox组件
|
||
* `height: 30,`
|
||
* `width:10,`
|
||
* 空白盒子
|
||
* StatefullWidget
|
||
* `setState((){})` 修改需要刷新的内容,类似小程序的setData
|
||
* Scaffold组件
|
||
* appBar组件
|
||
* `title: Text('text')` // 标题
|
||
* `backgroundColor: Colors.red` // 背景颜色
|
||
* `leading: IconButton(icon: Icon(Icons.menu), onPressed:(){})` // 左边加东西
|
||
* `actions: <Widget>[]` // 右边加东西
|
||
* `centerTitle: true` // 不论是不是ios都给居中显示
|
||
* 菜单栏
|
||
```dart
|
||
DefaultTabController(
|
||
length : 2, // tab的个数
|
||
child: Scafford(
|
||
appBar: AppBar(
|
||
title: Text('title'),
|
||
bottom: TabBar(
|
||
tabs: <Widget>[
|
||
Tab(text:'1'),
|
||
Tab(text:'2'),
|
||
Tab(text:'3'),
|
||
]
|
||
)
|
||
),
|
||
body: TabBarView(
|
||
children: <Widget>[
|
||
Text('text1'),
|
||
Text('text2'),
|
||
Text('text3'),
|
||
]
|
||
)
|
||
)
|
||
)
|
||
```
|
||
* TabBar组件
|
||
* `indicatorColor: Colors.red,`
|
||
* `isScrollable: true` // 允许滑动
|
||
* `tabs: <Widget>[]`
|
||
* Tab组件
|
||
* `text:"text"`
|
||
* TabBarView组件
|
||
* `children: <Widget>[]`
|
||
* body
|
||
* bottomNavigationBar组件
|
||
* `currentIndex: 0,` // 当前选中的tab
|
||
* `onTap: (int index){}` // 点击事件,默认参数是点击了第几个按钮
|
||
* `items: <BottomNavigationBarItem>[]` // 按钮内容
|
||
* BottomNavigationBarItem组件
|
||
* `icon: Icon(Icons.home),` // 图标
|
||
* `title: Text('主页')` // 文字
|
||
* floatingActionButton浮动按钮组件
|
||
* child:
|
||
* onPressed: (){}
|
||
* Navigator路由跳转组件
|
||
```dart
|
||
// 路由跳转
|
||
Navigator.of(context).push(
|
||
MaterialPageRoute(
|
||
builder: (context)=> FormPage(参数)
|
||
)
|
||
)
|
||
// 返回上一界面
|
||
Navigator.of(context).pop()
|
||
// 替换掉当前界面
|
||
Navigator.of(context).pushReplacementNamed('/home')
|
||
// 重置路由
|
||
Navigator.of(context).pushAndRemoveUntil(
|
||
new MaterialPageRoute(
|
||
builder: (context) => new Tabs(index: 1),
|
||
),
|
||
(route) => route == null
|
||
)
|
||
```
|
||
* MaterialPageRoute
|
||
* `WidgetBuilder builder` // 是一个WidgetBuilder类型的回调函数,它的作用是构建路由页面的具体内容,返回值是一个widget。我们通常要实现此回调,返回新路由的实例。
|
||
* `RouteSettings settings` // 包含路由的配置信息,如路由名称、是否初始路由(首页)。
|
||
* `bool maintainState = true,` // 默认情况下,当入栈一个新路由时,原来的路由仍然会被保存在内存中,如果想在路由没用的时候释放其所占用的所有资源,可以设置maintainState为false。
|
||
* `bool fullscreenDialog = false,` // 表示新的路由页面是否是一个全屏的模态对话框,在iOS中,如果fullscreenDialog为true,新页面将会从屏幕底部滑入(而不是水平方向)。
|
||
* MaterialApp
|
||
* `debugShowCheckedModeBanner: false` // 去除斜着的debug标识
|
||
* routes
|
||
```dart
|
||
routes: {
|
||
'/form': (context) => FromPage(),
|
||
'/search': (context) => SearchPage(),
|
||
}
|
||
|
||
Navigator.pushNamed(context, '/search')
|
||
|
||
// 在跳转到的路由的build方法里写
|
||
var args=ModalRoute.of(context).settings.arguments;
|
||
// 就可以传输参数了
|
||
Naviagtor.pushNamed(context, '/search', arguments:{"id": 123});
|
||
|
||
// 或者是定义路由的时候进行传参,这样就可以正常的使用了
|
||
routes: {
|
||
"tip2": (context){
|
||
return TipRoute(text: ModalRoute.of(context).settings.arguments);
|
||
},
|
||
},
|
||
```
|
||
* `initialRoute: '/'` // 初始化加载的路由
|
||
* 对于路由的固定写法
|
||
```dart
|
||
// Route.dart
|
||
import 'package:flutter/material.dart';
|
||
import '../pages/Tabs.dart';
|
||
import '../pages/Search.dart';
|
||
import '../pages/Form.dart';
|
||
|
||
final Map<String, Function> routes = {
|
||
'/':(contxt,{arguments})=>Tabs(),
|
||
'/search':(contxt,{arguments}) =>SearchPage(arguments: arguments),
|
||
'/form': (context,{arguments}) =>FormPage(arguments: arguments),
|
||
};
|
||
|
||
// 这个东西实际上是一个路由生成钩子,只有在没有找到指定路由的时候才会被调用,当前没有设置route所有的路由都会经过这个钩子进行处理,这里也可以当成路由守卫,判断各种权限然后进行路由的导航
|
||
var onGenerateRoute=(RouteSettings settings) {
|
||
// 统一处理
|
||
final String name = settings.name;
|
||
final Function pageContentBuilder = routes[name];
|
||
|
||
if (pageContentBuilder != null) {
|
||
if (settings.arguments != null) {
|
||
final Route route = MaterialPageRoute(
|
||
builder: (context) =>
|
||
pageContentBuilder(context, arguments: settings.arguments));
|
||
return route;
|
||
} else {
|
||
final Route route = MaterialPageRoute(
|
||
builder: (context) =>
|
||
pageContentBuilder(context));
|
||
return route;
|
||
}
|
||
}
|
||
};
|
||
// main.dart
|
||
import 'package:flutter/material.dart';
|
||
import 'routes/Routes.dart';
|
||
void main() => runApp(MyApp());
|
||
|
||
class MyApp extends StatelessWidget {
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return MaterialApp(
|
||
// home:Tabs(),
|
||
initialRoute: '/',
|
||
onGenerateRoute: onGenerateRoute
|
||
);
|
||
}
|
||
}
|
||
// 路由跳转
|
||
Naviagtor.pushNamed(context, '/search', arguments:{"id": 123});
|
||
```
|
||
* 资源管理 `pubspec.yaml`
|
||
```yaml
|
||
flutter:
|
||
assets:
|
||
- assets/my_icon.png
|
||
- assets/background.png
|
||
```
|
||
assets指定应包含在应用程序中的文件, 每个asset都通过相对于pubspec.yaml文件所在的文件系统路径来标识自身的路径。asset的声明顺序是无关紧要的,asset的实际目录可以是任意文件夹(在本示例中是assets文件夹)
|
||
* 在Widget树中获取State对象
|
||
* 方法一
|
||
```dart
|
||
// 直接通过of静态方法来获取ScaffoldState
|
||
ScaffoldState _state=Scaffold.of(context);
|
||
_state.showSnackBar(
|
||
SnackBar(
|
||
content: Text("我是SnackBar"),
|
||
),
|
||
);
|
||
```
|
||
* 方法二
|
||
```dart
|
||
//定义一个globalKey, 由于GlobalKey要保持全局唯一性,我们使用静态变量存储
|
||
static GlobalKey<ScaffoldState> _globalKey= GlobalKey();
|
||
...
|
||
Scaffold(
|
||
key: _globalKey , //设置key
|
||
...
|
||
)
|
||
_globalKey.currentState.openDrawer()
|
||
```
|
||
GlobalKey是Flutter提供的一种在整个APP中引用element的机制。如果一个widget设置了GlobalKey,那么我们便可以通过globalKey.currentWidget获得该widget对象、globalKey.currentElement来获得widget对应的element对象,如果当前widget是StatefulWidget,则可以通过globalKey.currentState来获得该widget对应的state对象。
|
||
* |