Flutter boring coding是效仿Flutter官方Youtub视频专题“The Boring Flutter Development Show”,结合本人理解推出的系列专题。会持续更新。
既然是系列,我们先在andriod studio创建一个单独Flutter项目。(只有安装了Flutter跟Dart插件后才有Flutter项目选项)
image.png
image.png
后几步都是点点点就不说了。
以windows系统为例,项目打开之后,咱们先打开一个模拟器:
image.png
image.png
直到出现这样的界面就说明Flutter实例项目启动成功了。
image.png
转到项目,直接看到项目核心文件main.dart
image.png
我的目的不是研究他的代码,咱们把main.dart项目中占位置的注释都删了,顺便把他的页面元素即widget来个净化。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: '文章列表'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child:Text('123')
),
);
}
}
ctr+s 会看到模拟器展示跟着改变了,Flutter这点我非常喜欢,直接热重载。
看到我们之前1.0.1示例图,我第一反应想到的是用Column来做父级容器。于是改造_MyHomePageState部分的代码
这里提出一个有趣的小技巧,鼠标点一下Text组件,按住ctr+enter会出现这样的弹出菜单,我选择了第一个选项,然后输入了Container,是不是快速实现了一个Container组件的包裹,可能你会说这有啥,当你碰到很恐怖的树状的界面你就会发现这个东西的用处了。 image.png还有个问题包是包起来了,但是格式调整还是麻烦啊
image.png
对了前面我说的是Column,所以我改一下。
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: <Widget>[
Text("列表元素")
],
)
);
前面说的是文章列表,那么我这边需要造点文章列表数据,新建数据文件。这里是循序渐进的文章讲解,所以不用服务端数据,先用本地写死的数据。
image.png
这里有个小技巧,如果你想要新建文件夹加文件,直接这么写
image.png
不用多说看截图
image.png
数据文件代码:
final articles = [
Article(
text: "Flutter自定义Appbar",
description : "起初想到这个需求,是因项目中有头部定制化的功能。于是硬着头皮去搜索,最终实现了,我的效果图展示只是一个我做成的样子。实际上这是一个通用解决方案",
domain: "https://www.jianshu.com/p/14b70d345862",
by: "Easonyu"
),
Article(
text: "Flutter文件上传和下载",
description : "先说说我为了测试文件上传和下载做了哪些前期准备吧,首先我把我的个人域名申请了一张ssl证书(https),然后我自己写了一个文件上传接口(php)",
domain: "https://www.jianshu.com/p/e867567dd2ff",
by: "Easonyu"
),
Article(
text: "Flutter中文官网2",
description:"开篇先分享一个优秀的dart语法的学习基地:http://codingdict.com/article/21908我在这里面边学边写dart语法还是蛮开心的",
domain: "https://www.jianshu.com/p/80b736ac5448",
by: "Easonyu"
),
Article(
text: "Flutter中文官网3",
domain: "https://www.jianshu.com/p/c1854a4de4c1",
description :"继前篇flutter初探之后,此次我来聊聊从传统web项目角度剖析我是怎么一步步搭建flutter基础项目的。本文主要讲述如何实现flutter用户数据多页面共享,用户数据本地缓存",
by: "Easonyu"
),
Article(
text: "Flutter初探",
domain: "https://www.jianshu.com/p/f66cd0e23cfa",
description :"作为一名长期web前端开发,这次涉及app开发,我自我感觉确实有点膨胀。本篇我主要是以web开发者在flutter开发摸索中碰到的一些问题,进行记录",
by: "Easonyu"
)
];
class Article {
final String text;
final String description;
final String domain;
final String by;
Article({
this.text,
this.description,
this.domain,
this.by
});
}
在main.dart中引入数据源:
import 'src/articles.dart';
改造_MyHomePageState:
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: articles.map((article)=>Text(article.text)).toList(),
)
);
运行结果如图:
image.png
按照中文排列方式改造一下:
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,//左对齐
children: articles.map((article)=>Text(article.text)).toList(),
)
);
运行结果:
image.png
问题来了,如果我想要标题之外的其他元素我该如何去做?
第一步增加_BuildItem Widget扩展渲染方法:
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,//左对齐
children: articles.map(_BuildItem).toList(),
)
);
}
Widget _BuildItem(Article article){ //用js的方式去理解的话就是这里的_BuildItem替代了原有的箭头函数,并且_BuildItem的类型是Widget(与Flutter中一切皆Widget理念高度吻合)
return Text(article.text);
}
}
第二部宽展_BuildItem丰富界面
Widget _BuildItem(Article article){
return Padding(
padding: EdgeInsets.all(20.0),
child: ListTile(
title: Text(article.text),
subtitle: Text(article.description),
),
);
}
运行结果如下:
image.png
咱们来对标题和内容做一些修饰:
Widget _BuildItem(Article article){
return Padding(
padding: EdgeInsets.all(20.0),
child: ListTile(
title: Text(article.text, style: TextStyle(fontSize: 30.0),), //修改字体大小
subtitle: Text("简介:${article.description}", style: TextStyle(fontSize: 24.0)),
),
);
}
保存运行:
image.png
页面高度溢出了,回想一下,之前的我们外部容器用的Column,两点有问题,第一高度超出会出现溢出问题,第二超出内容我们也无法查看,于是我们用ListView替换掉它。
image.png
列表完成了,下面我们添加链接:
第一步添加页面记载的插件:
image.png
记得后面点一下package get。
这里有个小技巧,不同的Flutter SDK需要安装的插件版本也不一样,如果只是单纯的练习Coding可以在查看版本后面写any
image.png
到这里就实现了一个可以打开页面的文章列表。
为了跟原文同步,我这边继续改造展示部分_BuildItem:
return ExpansionTile(
title:Text(article.text),
children: <Widget>[
Padding(
padding:EdgeInsets.all(20.0),
child: Text("简介:${article.description}"),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("作者:${article.by}"),
IconButton(
icon: Icon(Icons.launch),
color: Colors.green,
onPressed: () async{
if(await canLaunch(article.domain)){
launch(article.domain);
}
},
)
],
)
],
);
运行结果如下:
image.png
通常列表数据都要配合下拉刷新,这里,我们用RefreshIndicator
运行结果如下:
image.png
页面完整代码如下:
import 'package:flutter/material.dart';
import 'src/articles.dart';
import 'package:url_launcher/url_launcher.dart';
import 'dart:io';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: '文章列表'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: RefreshIndicator(
onRefresh: () async{
await Future.delayed(Duration(seconds: 1));
setState(() {
articles.removeAt(0); //这里要注意跟其他语言setState区分,这里的setState主要做的是通知工作,不需要设置值
});
},
child: ListView(
children: articles.map(_BuildItem).toList(),
),
)
);
}
Widget _BuildItem(Article article){
return ExpansionTile(
title:Text(article.text),
children: <Widget>[
Padding(
padding:EdgeInsets.all(20.0),
child: Text("简介:${article.description}"),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("作者:${article.by}"),
IconButton(
icon: Icon(Icons.launch),
color: Colors.green,
onPressed: () async{
if(await canLaunch(article.domain)){
launch(article.domain);
}
},
)
],
)
],
);
}
}
文章总结:
1.实现了一个可以滚动的列表页
2.实现了自定义组建渲染
3.实现了下拉刷新
4.实现了列表到详情演示
网友评论