一个Flutter的Demo

ezgif-2-c954a6dd5e.gif
ezgif-2-f3661cf95e.gif

### App的页面详情

HomePage;里面嵌套了四个页面,使用的是TabBarTabBarView的组合,比如安卓中的Fragment Viewpager

  • 1、首页的第一页使用豆瓣电影的接口,请求数据,并且展示出来了,工程中如何代码中如何使用依赖?如下代码所示
    1
    2
    3
    4
    5
    6
    7
    8
      flutter:
    sdk: flutter
    # The following adds the Cupertino Icons font to your application.
    # Use with the CupertinoIcons class for iOS style icons.
    cupertino_icons: ^0.1.0
    fluttertoast: ^2.0.7 #"Packages get" 要去主动的 get 一次依赖
    dio: ^v1.0.3
    # 添加网络依赖
  • 2、演示了图片控件摆放
  • 3、综合列表的展示
  • 4、其他控件的使用Demo

    首页.jpg

一些控件.jpg

 * 首页的关键代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 //为给定的[子]控件创建默认选项卡控制器。
return new DefaultTabController(
length: 5,
child: new Scaffold(
appBar: new AppBar(
backgroundColor: Colors.black45,
// title: titleWidget(),
title: new Text("首页",style: new TextStyle(color: Colors.white,fontSize: 22.00),),
actions: <Widget>[
new IconButton(
icon: new Icon(Icons.add_a_photo), onPressed: () {
Navigator
.of(context)
.push(new MaterialPageRoute(builder: (context) {
return new OtherPage();
}));
})
],
bottom: new TabBar(
isScrollable: true,
labelStyle: new TextStyle(fontSize: 22.00,color: Colors.red),
indicatorPadding:EdgeInsets.zero,
labelColor: Colors.white,
indicatorWeight:4.0,
unselectedLabelColor: Colors.blueAccent,
tabs: [
new Tab(
text: "豆瓣电影",
),
new Tab(
text: "控件摆放",
),
new Tab(
text: "列表展示",
),
new Tab(
text: "其他控件展示",
),
]),
),
body: new TabBarView(children: [new TabOne(), new TabTwo(),new TabThree(),new TabFroth()]),
));

SimilarWordsPage寻找近义词Demo,就是一个点击按钮,然后请求网络,刷新页面的流程。

  • 1、使用了TextField相当于安卓中的Edittext,只不过获取值的时候有些变化

    1
    2
    3
    4
    5
    6
    7
    8
    9
    new Expanded(
    child: new TextField(
    //不要主动弹起来
    autofocus: false,
    controller: _textController,
    decoration: new InputDecoration.collapsed(
    hintText: "请输入要查找的词",
    hintStyle: new TextStyle(color: Colors.red)),
    ),
  • 2、如何退出页面Navigator.of(context).pop();

  • 3、如何使用Toast,这里我是使用了三方的依赖!底层原理是使用了反射,具体实现的方法,有兴趣的同学可以看看String res = await _channel.invokeMethod('showToast', params);

    1
    2
    3
    4
    5
    Fluttertoast.showToast(
    msg: "输入为空,请重新输入",
    timeInSecForIos: 1,
    bgcolor: "#e74c3c",
    textcolor: '#ffffff');
    • 4、带框的Button的使用,具体请看实现的代码。
    • 5、具体页面如下

近义词页面.jpg

  • 6、代码如下
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
                 import 'dart:convert';
    import 'dart:io';
    import 'package:flutter/material.dart';
    import 'package:flutter_app/bean/DataBean.dart';
    import 'package:fluttertoast/fluttertoast.dart';

    class SimilarWordsPage extends StatefulWidget {
    @override
    State<StatefulWidget> createState() {
    return new SimilarWordsPageState();
    }
    }

    class SimilarWordsPageState extends State<SimilarWordsPage> {
    List<DataBean> datas = [];
    static int i=0;
    final TextEditingController _textController = new TextEditingController();

    @override
    Widget build(BuildContext context) {
    return new Scaffold(
    appBar: findAppBar(),
    backgroundColor: Colors.black12,
    body: findBody(),
    );
    }

    findBody() {
    return new Container(
    child: new Scaffold(
    body: new ListView.builder(
    itemCount: datas.length,
    itemBuilder: (BuildContext context, int position) {
    i=position;
    return getRow(position);
    },
    ),
    ));
    }

    Widget findAppBar() {
    return new AppBar(
    title: new Container(
    child: new Row(
    children: <Widget>[
    new Container(
    child: new FlatButton.icon(
    onPressed: () {
    // 本来就在栈顶,退出会有显示的问题
    Navigator.of(context).pop();
    },
    icon: new Icon(Icons.close, color: Colors.white30),
    label: new Text(""),
    ),
    width: 60.0,
    ),
    new Expanded(
    child: new TextField(
    //不要主动弹起来
    autofocus: false,
    controller: _textController,
    decoration: new InputDecoration.collapsed(
    hintText: "请输入要查找的词",
    hintStyle: new TextStyle(color: Colors.red)),
    ),
    ),
    //点击事件的第一种实现的方式 我觉得不太好
    // new GestureDetector(child: new Icon(Icons.find_in_page),onTap: (){print("dd");})
    // 这种点击时间有点效果
    new IconButton(
    icon: new Icon(Icons.find_in_page),
    onPressed: () {
    print(_textController.text);
    if (_textController.text.isEmpty) {
    Fluttertoast.showToast(
    msg: "输入为空,请重新输入",
    timeInSecForIos: 1,
    bgcolor: "#e74c3c",
    textcolor: '#ffffff');
    } else {
    FocusNode focusNode = new FocusNode();
    FocusScope.of(context).requestFocus(new FocusNode());
    Fluttertoast.showToast(
    msg: "查找值为:" + _textController.text,
    timeInSecForIos: 1,
    bgcolor: "#e74c3c",
    textcolor: '#ffffff');
    getApiData(_textController.text);
    focusNode.unfocus();
    }
    })
    ],
    ),
    decoration: new BoxDecoration(
    borderRadius: const BorderRadius.all(const Radius.circular(4.0)),
    color: Colors.white10),
    ));
    }

    Widget getRow(int i) {
    return new Padding(
    padding: new EdgeInsets.all(10.0),
    // child: new Text("Row ${datas[i].key}",style: new TextStyle(color: Colors.orange,fontSize: 18.00),)
    // Column 相当于 相对布局 Row 线性布局
    child: new Column(
    children: <Widget>[
    new Padding(
    padding: new EdgeInsets.fromLTRB(0.0, 5.0, 0.0, 5.0),
    child: new Row(
    children: <Widget>[
    new Expanded(
    child: new OutlineButton(
    borderSide:new BorderSide(color: Theme.of(context).primaryColor),
    child: new Text('条目 = '+i.toString(),style: new TextStyle(color: Theme.of(context).primaryColor),),
    onPressed: (){},
    )
    ),
    ],
    ),
    ),

    new Container(
    child: new Text(
    "联想到的词:" + datas[i].key,
    style: new TextStyle(color: Colors.purple, fontSize: 12.00),
    ),
    padding: new EdgeInsets.all(10.0),
    ),
    new Container(
    child: new Text("联想到词的翻译信息:" + datas[i].message,
    style: new TextStyle(color: Colors.cyan, fontSize: 15.00)),
    padding: new EdgeInsets.all(10.0),
    )
    ],
    ),
    );
    }

    @override
    void initState() {
    super.initState();
    // 网络请求
    //http://dict-mobile.iciba.com/interface/index.php?c=word&m=getsuggest&nums=10&client=6&is_need_mean=1&word=sm
    //我的 Api的地址
    getApiData("sm");
    }

    // 网络请求
    void getApiData(String tag) async {
    // 注意导入的包的地方是 import 'dart:io';
    var httpClient = new HttpClient();
    var url =
    "http://dict-mobile.iciba.com/interface/index.php?c=word&m=getsuggest&nums=20&client=6&is_need_mean=1&word=" +
    tag;
    var request = await httpClient.getUrl(Uri.parse(url));
    var response = await request.close();
    if (response.statusCode == HttpStatus.OK) {
    var jsonData = await response.transform(utf8.decoder).join();
    setState(() {
    datas = DataBean.decodeData(jsonData);
    });
    for (int i = 0; i < datas.length; i++) {
    print(datas[i].key);
    print(datas[i].message);
    }
    }
    }
    }

官方Demo

官方Demo.jpg

关于我

关于我.jpg

一些总结

  • widget相当于ViewWidget的实例仅仅存在每一帧之间,并且每一帧之间 Flutter都会主动的创建一颗Widget树用于下一帧的渲染。
  • AndroidView 是可变的,在 Flutter 中的 Widget 是不可变的。这种特性使得 Flutter 中的 Widget 变得十分轻量级
  • 一个 Widget会变化,那么它就是有状态的。但是如果一个子Widget是有状态的,但是其父Widget是不可变的话父Widget也可以是 StatelessWidget
  • TatelessWidgetStatefulWidget 的核心内容是一致的,它们都会在每一帧中被重构,不同之处在于StatefulWidget 有一个 State 对象,它可以为 StatefulWidget 在不同帧之间存储数据。
  • FlutterUI的布局是通过在dart 文件中构建 Widget 树来实现的。
  • Android中,使用 LinearLayout 使你的部件垂直或水平放置。在 Flutter中,你可以使用Row 或者 Co​​lumn 来实现相同的效果。
  • Flutter 中,最简单的方法是使用ListView 。在Flutter 中,ListView 既是ScrollView 又是Android中的ListView
  • 通过使用ColumnRowStackWidget 的组合来实现 RelativeLayout 的效果
  • Flutter 中,添加触摸监听器有两种方法
    • 如果Widget支持事件检测,则可以将一个函数传递给它并进行处理。例如,RaisedButton 有一个onPressed 参数
    • 如果 Widget不支持事件检测,则可以将该 Widget 包装到 GestureDetector中,并将函数传递给onTap 参数。
  • GestureDetector 我们可以监听广泛的手势
  • 要充分利用应用程序中的 Material风格的组件的话,可以把顶级部件 MaterialApp作为应用程序的入口。MaterialApp作为一个比较方便的部件,包装了许多实现了 Material 风格所需要的部件(如 Scaffold)。MaterialApp是在 WidgetsApp 的基础上进行实现的
  • Flutter不会自动导入包
  • Column相当于 相对布局Row线性布局
  • 首页的数据结构展示
  • HttpClient导入的包是 io里面的
  • DEBUG 包要不正式包大很多 Built build\app\outputs\apk\debug\app-debug.apk (31.9MB).而正式包才8.4M.
  • 解决的Bug的时候太痛苦了,Flutter使用 ide ,太痛苦了
  • 在脑袋要构思出 这个布局的整体的结构
  • 关闭系统自带的防火墙,重启OK 由于需要出差,就是用的是笔记本开发,导致自己笔记本的防火墙没有被关闭,真的是日了狗了,解决防火墙
  • MediaQuery.of(context).size.width / 4分之一的屏幕
  • MaterialApp 带有 Debug的标记

感谢以下资料给与我的帮助

求赞或者求星星 FlutterApp


  转载请注明: 仕明同学 一个Flutter的Demo

 上一篇
Spring Boot整合Swagger2、Mybatis构建RESTfulAPI Spring Boot整合Swagger2、Mybatis构建RESTfulAPI
首先推荐一个好玩的网站 ASCll ,可以把你想要的字母生成文本的图形,然后copy到banner.txt,即可替换Spring Boot的开启图标 12345678910111213141516171819202122
2018-09-27 Shiming_Li
下一篇 
剑指几道算法题的思考 剑指几道算法题的思考
1、在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 假如二维数组为 { {1, 2, 8, 9}, {2, 4, 9,
2018-09-03 Shiming_Li
  目录