前言
当你看到这篇文章的时候,已经是2020的某一天,从此以后再无2019。不知道这一年来你收获了多少呢,我也十分感谢你能打开这份年末我予你最好的礼物,不得不说你是个上进的人
首先值得开心的有两件事
-
没错这款就是
BENQ 明基的BL2480T
我怎么感觉我像个开箱的UP,周末没事,我还看了看掘金大佬们的分享,我裂开了 -
第二件事,就是我在 两台设备上都装了图床小工具
这个很好用,对于时长写文章的话,能提高些效率,Mac
上装的是uPic
其实自己想写点东西,又中断,主要原因是自己的那台小Mac
是12-13年的机子,Flutter 应用是打不开的,很卡很卡,期望自己在2020年能DIY一台,专门写文章,手动加到 一位前端弱者的2019年总结|掘金年度征文 这里
上期回顾
言归正传(不知道为什么总喜欢扯点别的),就像写的一篇很实用的flutter状态管理相关的 文章
好像并没有多少阅读量,扯的太远,不过你放心,这篇依然是很干
读读评论
-
-
其中他是这样说的:
有个地方变了,search_widget的包名变了,建议更新下 插件官方说明
pub.dev/packages/se… 引入方式 import 'package:search_widget/search_widget.dart';
当时写的一个搜索模块,是借助第三方的包,不过在实际开发中还是尽量手写比较基础的模块,比如AppBar搜索,或者页面中的搜索,正是在搜索的分享中,有的地方有点错误,谢谢指正
-
-
-
其中他是这样说的:
赞,最近刚开始看flutter,dart真的可以。但是flutter的套娃写法真的有点把我劝退了
首先还是很感谢对自己的肯定,有很多人接触
flutter
的时候,总是说嵌套地狱,怕了怕了,笔者倒没有觉得有这个问题啊,打个比方,我们要写一个布局,要换一种思维来写,从小部件来出发
// 我是第一行 Widget _firRow() => Container( child: Row( children: <Widget>[ Text('我是第一行'), ], )); // 我是第二行 Widget _SecRow() => Container( child: Row( children: <Widget>[ Text('我是第er行'), ], )); // 我是第三行 Widget _ThrRow() => Container( child: Row( children: <Widget>[ Text('我是第er行'), ], )); // 我是三行的汇总 Widget _all() => Container( child: Column( children: <Widget>[ // 第一行 _firRow(), // 第二行 _SecRow(), // 第三行 _ThrRow() ], ), ); 复制代码
-
这也是我实际开发中的模式,所以也没觉得有嵌套的问题,反而觉得写起来很舒服,我还特地的 看了下,关注者,
不知你是不是101
呢
期待效果
实际效果
开始操练
遗留问题
-
首先,咱们克隆下仓库之后,发现,代码是不完全的,只有
4 commits
这应该是我自己的原因 没有把代码同步上去 -
第二个问题是克隆下来代码,run 了一下是报错误的
遇到问题莫要慌张,本章节,我会整理一下项目,再clone
代码就不会有问题了,看过前几篇文章的应该知道,在我创建项目的时候,Flutter SDK 还是1.9+版本
,那么就在前几天不久前,它翘首以盼的更新了,大体没有让开发者失望,包括HOT UI
等,网上有大佬分享出一些新的东西,这段路就不多做唠
- 当前项目的flutter 版本
- 当前直接克隆代码就可
Dio数据再分析
在上一篇的时候
Flutter实战 从头撸一个「孤岛」APP(No.3、书单、搜索框、Dio初探)
我们简单的分析了一下Dio的数据,此时不要慌,这里先埋下一个伏笔,那就是Json to Dart
, 接触过flutter 开发的可能已经知道了那就是很犯迷糊的一步,把json数据转为Model类,至于怎么才能一步到位,傻瓜式转换,拿来直接用,那像Web 开发中,直接用后台返回json 不行吗,为什么还要转化,咱们留到下一段旅程
流行、点赞
本篇咱们就来先看一下首页(流行)模块的点赞效果,首先还是先初始化一行(头部)
body: SingleChildScrollView(
child: Flex(
direction: Axis.vertical,
children: <Widget>[
Container(
child: _like(),
)
],
),
)
复制代码
// 点赞 第一行
Widget _like() => Container(
child: Row(
children: <Widget>[
Container(
width: width750,
height: height100,
decoration: BoxDecoration(
border: Border.all(width: 1, color: Colors.red)),
child: Text('头部'),
)
],
),
);
复制代码
这样是不是就不怎么嵌套了呢,就像开头提及的那样,然后在widgets
文件夹下新建一个点赞的 文件,用来放点赞的效果
使用编辑器的快捷方式来新建代码段
这里你可以去翻下我的其他文章,也有提到一些常用的快捷键
动画Animation
控制器
控制器在应用中还是很常见的,包括像文本输入、还有滚动部件,那么动画当然也不例外
-
初始化控制器
AnimationController _animationController; // 复制代码
-
初始化控制器
void initState() { super.initState(); _animationController = AnimationController( ); } 复制代码
那么有个问题 我们怎么知道有什么值呢
AnimationController({
double value,
this.duration, // 时长
this.reverseDuration,
this.debugLabel,
this.lowerBound = 0.0, // 开始的值
this.upperBound = 1.0, // 结束的值
this.animationBehavior = AnimationBehavior.normal,
@required TickerProvider vsync,
}) : assert(lowerBound != null),
assert(upperBound != null),
assert(upperBound >= lowerBound),
assert(vsync != null),
_direction = _AnimationDirection.forward {
_ticker = vsync.createTicker(_tick);
_internalSetValue(value ?? lowerBound);
}
复制代码
以上我们可以简单的看下
-
开始播放动画
_animationController.forward(); 复制代码
-
销毁无用的控制器
@override void dispose() { super.dispose(); _animationController.dispose(); } 复制代码
完整代码
import 'package:flutter/material.dart';
import 'package:lsolated_island_app/utils/global.dart';
class WidgetLike extends StatefulWidget {
WidgetLike({Key key}) : super(key: key);
@override
_WidgetLikeState createState() => _WidgetLikeState();
}
class _WidgetLikeState extends State<WidgetLike> with TickerProviderStateMixin {
AnimationController _animationController; // 动画控制器
Animation _animationSize; // 大小
Animation _animationColor; // 颜色
CurvedAnimation _curvedAnimation;
// 初始化
@override
void initState() {
super.initState();
_animationController = AnimationController(
// value: 20.0, //
// lowerBound: 20.0,
// upperBound: 100.0,
duration: Duration(milliseconds: 1000), // 持续的时长
vsync: this, // 每一帧的反应 一秒60 this 当前对象
);
_animationSize =
Tween(begin: 30.0, end: 100.0).animate(_animationController);
// // 监听
_animationController.addListener(() {
// print('${_animationController.value}');
setState(() {});
});
// 开始播放动画
// _animationController.forward();
// // 设置动画的范围
_animationColor = ColorTween(begin: Colors.red, end: Colors.red[900])
.animate(_animationController);
_curvedAnimation = CurvedAnimation(
parent: _animationController, curve: Curves.bounceOut); // 动画曲线
// // 监听状态
_animationController.addStatusListener((AnimationStatus status) {});
}
@override
void dispose() {
super.dispose();
_animationController.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Container(
child: Text('${_animationController.value}'),
),
Container(
child: IconButton(
iconSize: _animationSize.value,
color: _animationColor.value,
onPressed: () {
print('点击了');
// _animationController.forward();
switch (_animationController.status) {
case AnimationStatus.completed:
_animationController.reverse();
break;
default:
_animationController.forward();
}
},
icon: Icon(Icons.favorite),
),
)
],
));
}
}
复制代码
第三方辅助
当然了,通过如上我们会对动画有一定的理解,不过像这这种常见的效果,一般会有些对Flutter积淀的大佬们写成共用的第三方部件,来提供开发者使用,并不断的更新维护,但是这个也是跟情况而定,一般移动的应用都会牵扯到包的大小,一些简单的效果,可以尝试自己来写,那么接下来,来pub.dev
上一个开放的轮子
- 包名称 :like_button
- 版本 :0.1.9
- 更新频次 更新频率还是很不错的,也是
- 中文文档 Like Button 支持推特点赞效果和喜欢数量动画的Flutter库.
从仓库了解到 这是
FlutterCandies
仓库里的作品,有几个大佬在守护,看下文档写的也是十分详细,
社区概览
那我们怎么使用呢 ?引入包之后,像这样使用一下就可
return Scaffold(
appBar: AppBar(),
body: Container(
child: Center(
child: LikeButton(),
),
));
复制代码
代码同步至Demo 点赞Demo