发表日期:2018-12 文章编辑:小灯 浏览次数:3237
还未安装环境的童鞋可以看下这个flutter环境安装
不错的学习网站:
1.flutter官方中文网站:https://flutterchina.club/docs/
2.Flutter七日游(张风捷特烈):https://juejin.im/user/5b42c0656fb9a04fe727eb37
3.咸鱼官方博客:https://zhuanlan.zhihu.com/xytech
ps:前2个都比较基础,最后一个比较深入
计划将基础控件,布局控件结束后,再进行自定义绘制控件
widget: 小器具,装饰品,窗口小部件;这里统一称为控件
要学flutter,肯定要先学会怎么使用控件
统计了一部分控件,做了一个表格:
| widget | flutter | android |
|---|---|---|
| 文本 | Text | TextView |
| 按钮 | ||
| 漂浮按钮 | RaisedButton | Button |
| 扁平按钮 | FlatButton | |
| 边框按钮 | OutlineButton | |
| 图片按钮 | IconButton | ImageButton |
| 浮动动作按钮 | FloatingActionButton | FloatingActionButton |
| 编辑框 | TextField | EditText |
| 图片 | Image | ImageView |
| 图标 | Icon | |
| 复选框 | Checkbox | CheckBox |
| 单选框 | Radio | RadioButton |
| 单选开关 | Switch | Switch |
| 底部弹框 | SnackBar | SnackBar |
| 滚动控件 | SingleChildScrollView | ScrollView |
| 线性滚动列表 | ListView | RecyclerView(LinearLayoutManager) |
| 网格滚动列表 | GridView | RecyclerView(GridLayoutManager) |
| 自定义滚动 | CustomScrollView | RecyclerView(StaggeredGridLayoutManager) |
| 滚动条 | ScrollBar | |
| 弹框 | Dialog | AlertDialog |
| 进度条 | ProgressIndicator | ProgressBar |
| 圆形进度条 | CircularProgressIndicator | |
| 线性进度条 | LinearProgressIndicator | |
| 滑动条 | Slider | SeekBar |
| 导航栏 | AppBar | ToolBar |
| 选项栏 | TapBar+TapBarView | |
| 底部导航栏 | BottomNavigationBar | |
| 分割线 | Divider | |
| 侧滑菜单 | Drawer | DrawerLayout |
| 底抽屉 | BottomSheet | BottomSheet |
| 流式标签 | Chip | Chip |
| 圆形头像 | CircleAvatar |
控件很多,怎么学习来快呢?(ps:自我感觉)
学习之前,我们需要明确2个感念:
androidstudio的三个快捷键| 快捷键 | 作用 |
|---|---|
| stless | 创建一个StatelessWidget |
| stful | 创建一个StatefullWidget |
| stanim | 创建一个StatefullWidget ,且包含动画 |
准备工作完成
接下来我们以ScrollBar为例,来学习这个控件:
工程目录我们创建一个新的flutter工程时,系统会创建一大堆文件,那么我们的dart代码是在哪呢?
dart代码就在同级目录下的lib文件中
这里会发现同时存在android和ios 2个文件夹,对的,flutter编译后的应用是同时支持双端的(ps:或者说是三端,fuchsia已经在布局了)
enum TargetPlatform { /// Android: <https://www.android.com/> android,/// Fuchsia: <https://fuchsia.googlesource.com/> fuchsia,/// iOS: <http://www.apple.com/ios/> iOS, } 回归正题,系统会创建一个main.dart文件
import 'package:flutter/material.dart'; //main 程序的主入口 void main() => runApp(MyApp()); //运行一个MaterialApp控件 class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( //应用的图标名称 title: 'Flutter Demo', //主题 theme: ThemeData( primarySwatch: Colors.blue, ), //主界面 home: MainPage() ); } } 这里代码基本固定了,你肯定要使用MaterialApp控件的,否则不好看(我这里不说不符合规范)
class MainPage extends StatelessWidget { @override Widget build(BuildContext context) { //脚手架 return Scaffold( //相当于toolbar,导航栏 appBar: AppBar( title: Text("flutter"), ), //正文 body: ScrollBarDemo ); } } 我们要开始创建一个ScrollBar了,先看下其的源码:
class Scrollbar extends StatefulWidget { /// typically a [Scrollable] widget. const Scrollbar({ Key key, @required this.child, }) : super(key: key);/// Typically a [ListView] or [CustomScrollView]. final Widget child;@override _ScrollbarState createState() => _ScrollbarState(); } 源码说需要传递一个child,且必须为Scrollable,然后给了2个选择[ListView] 或 [CustomScrollView]
构造函数中的{}表示可选命名参数,@required表示child这个参数必须传递
Scrollable我们可以大胆的猜测,能滚动的控件肯定都包涵这个控件,所以我们选类似android中的那个ScrollView的控件SingleChildScrollView
然后我们写下代码
class ScrollBarDemo extends StatelessWidget { @override Widget build(BuildContext context) { return Scrollbar( child: SingleChildScrollView( child:Container() ) ); } } 接下来看看SingleChildScrollView
class SingleChildScrollView extends StatelessWidget { const SingleChildScrollView({ Key key, this.scrollDirection = Axis.vertical, this.reverse = false, this.padding, bool primary, this.physics, this.controller, this.child, }) : ...,super(key: key);//省略了断言 final Axis scrollDirection; //滚动方向,水平和垂直 final bool reverse; //是否反向,默认不启用 final EdgeInsetsGeometry padding;//间距 final ScrollController controller;//滑动控制器 final bool primary;//默认true final ScrollPhysics physics;//超过物理边界后的动画效果 final Widget child; ... @override Widget build(BuildContext context) { ... //内部创建了一个Scrollable控件 final Scrollable scrollable = Scrollable( axisDirection: axisDirection, controller: scrollController, physics: physics, viewportBuilder: (BuildContext context, ViewportOffset offset) { return _SingleChildViewport( axisDirection: axisDirection, offset: offset, child: contents, ); }, ); return primary && scrollController != null ? PrimaryScrollController.none(child: scrollable) : scrollable; } } 源码可以看出,所有参数都是可选的,也就是说child其实也可以不传的,但这样就整个界面就是空白的
class ScrollBarDemo extends StatelessWidget { final String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; @override Widget build(BuildContext context) { return Scrollbar( child: SingleChildScrollView( child:Container( color: Colors.redAccent, width: 360, child: Column( //创建一个Text控件列表 children: str.split("").map((c) => Text(c, textScaleFactor: 2.0,)).toList(), ) ) ) ); } } 关于布局、监听、路由、手势等接下来在介绍
小小的总结一下
1.遇到一个widget,先看它的构造函数(可能有多个)
a. StatelessWidget,看其build方法做了什么
b. StatefulWidget,先找到createState(),然后在state类中看其build方法做了什么
2.配合源码中的英文注释加以理解
3.动手实践一番,测试效果
最后说明一下,flutter生成的代码都封装在libflutter.so中,不再是以前的.class文件
github代码:https://github.com/leaf-fade/flutterDemo
小尾巴:文章有错误的地方请不吝指出,会及时更改