- 首先推荐两篇文章,写的非常的详细,从中可以了解到原理,写的非常的详细!
-
Demo 的下载地址(正式包,使用Flutter命令打的正式包)
蒲公英.png - App详情
ezgif-2-f3661cf95e.gif
App的页面详情
HomePage
;里面嵌套了四个页面,使用的是TabBar
和 TabBarView
的组合,比如安卓中的Fragment
Viewpager
- 1、首页的第一页使用豆瓣电影的接口,请求数据,并且展示出来了,工程中如何代码中如何使用依赖?如下代码所示
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
* 首页的关键代码
```
//为给定的[子]控件创建默认选项卡控制器。
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
,只不过获取值的时候有些变化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);
Fluttertoast.showToast( msg: "输入为空,请重新输入", timeInSecForIos: 1, bgcolor: "#e74c3c", textcolor: '#ffffff');
- 4、带框的Button的使用,具体请看实现的代码。
- 5、具体页面如下
- 6、代码如下
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
相当于View
,Widget
的实例仅仅存在每一帧之间,并且每一帧之间Flutter
都会主动的创建一颗Widget
树用于下一帧的渲染。 -
Android
中View
是可变的,在Flutter
中的Widget
是不可变的。这种特性使得Flutter
中的Widget
变得十分轻量级 - 一个
Widget
会变化,那么它就是有状态的。但是如果一个子Widget
是有状态的,但是其父Widget
是不可变的话父Widget
也可以是StatelessWidget
。 -
TatelessWidget
和StatefulWidget
的核心内容是一致的,它们都会在每一帧中被重构,不同之处在于StatefulWidget
有一个State
对象,它可以为StatefulWidget
在不同帧之间存储数据。 -
Flutter
中UI
的布局是通过在dart
文件中构建Widget
树来实现的。 - 在
Android
中,使用LinearLayout
使你的部件垂直或水平放置。在Flutter
中,你可以使用Row
或者Column
来实现相同的效果。 - 在
Flutter
中,最简单的方法是使用ListView
。在Flutter
中,ListView
既是ScrollView
又是Android
中的ListView
。 - 通过使用
Column
,Row
和Stack
等Widget
的组合来实现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
的标记
感谢以下资料给与我的帮助
- Android 开发者参考
- Api的接口 查询近义词
- Api的接口 豆瓣电影
- 打包的流程
网友评论