概述
优美的应用体验 来自于细节的处理,更源自于码农的自我要求与努力,当然也需要码农年轻灵活的思维,不局限于思维,不局限语言限制,才是编程的最高境界。
- 优美的音乐节奏带你浏览这个效果的编码过程
- 坚持每一天,是每个有理想青年的追求
- 追寻年轻人的脚步,也许你的答案就在这里
本文章实现的效果如下图所示:
1 Flutter项目中单文件定义启动测试入口
void main() {
//启动根目录
runApp(MaterialApp(
//默认的页面
home: Example820(),
));
}
2 页面初始化
波浪也是在波动,所以先来个动画控制器 Example820 的构建如下:
class Example820 extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _ExampleState();
}
}
class _ExampleState extends State with SingleTickerProviderStateMixin {
///动画控制器
AnimationController _animationController;
@override
void initState() {
super.initState();
//创建动画控制器
_animationController = AnimationController(
//默认的初始值
value: 0.0,
//执行时间
duration: Duration(seconds: 10),
//值变化范围
upperBound: 1,
lowerBound: -1,
vsync: this,
);
//重复执行
_animationController.repeat();
}
@override
void dispose() {
//销毁
_animationController.dispose();
super.dispose();
}
...
}
3 页面的主体UI构建
页面主体使用 Scaffold脚手架构建,通过层叠布局Stack来组合,代码如下:
@override
Widget build(BuildContext context) {
//获取当前组件的大小
Size size = MediaQuery
.of(context)
.size;
return Scaffold(
//允许键盘弹出布局文件上移
resizeToAvoidBottomPadding: true,
body: Container(
//填充
width: size.width,
height: size.height,
//层叠
child: Stack(
children: <Widget>[
//第一部分 水波纹背景
buildFirstAnimation(size),
//第二部分 顶部的文本
buildTopText(size),
//第三部分 底部的按钮
buildBottomButton(size),
],
),
),
);
}
3.1 Hello World
Stack 中有三层,先来看最简单的文本 ,代码如下:
/// 代码清单 8-31 顶部对齐的文本
///
Positioned buildTopText(Size size) {
return Positioned(
top: size.height * 0.2,
left: 0,
right: 0,
child: Text(
"Hello World",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 33, color: Colors.white, fontWeight: FontWeight.bold),
),
);
}
3.2 底部的文本输入区域
使用线性布局Column 来构建,代码如下:
///底部对齐的输入框
Positioned buildBottomButton(Size size) {
return Positioned(
bottom: 60,
left: 0,
right: 0,
child: Column(
//包裹子Widget
mainAxisSize: MainAxisSize.min,
//主方向子Widget 底部对齐 (Column的垂直方向)
mainAxisAlignment: MainAxisAlignment.end,
//次方向子Widget居中对齐 (Column的水平方向)
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: size.width * 0.8,
margin: EdgeInsets.only(top: 18),
child: buildInputWidget('请输入账号'),
),
Container(
width: size.width * 0.8,
margin: EdgeInsets.only(top: 18),
child: buildInputWidget('请输入密码', isPass: true),
),
Container(
margin: EdgeInsets.only(top: 20),
padding: EdgeInsets.only(bottom: 60),
width: size.width * 0.7,
child: ElevatedButton(
onPressed: () {},
child: Text(
'登录',
style: TextStyle(
color: Colors.white,
fontSize: 20,
),
),
),
),
],
),
);
}
}
因为这里的文本输入框是比较类似的,所以也进行了封装调用 ,代码如下:
///
Widget buildInputWidget(String hint, {bool isPass = false}) {
return TextField(
//是否隐藏文本
obscureText: isPass,
//文本的边框装饰
decoration: InputDecoration(
//提示文本
hintText: hint,
//提示文本的样式
hintStyle: TextStyle(color: Color(0xFFACACAC), fontSize: 14),
//输入内容的内边距
contentPadding: EdgeInsets.only(top: 20, bottom: 20, left: 38),
//输入框可用时的边框样式
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.lightBlueAccent),
borderRadius: BorderRadius.all(Radius.circular(30.0)),
),
//输入框获取输入焦点时的边框样式
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.green),
borderRadius: BorderRadius.all(Radius.circular(30.0)),
),
),
);
}
4 波浪样式的背景构建
先通过 Container 的BoxDecoration 来设置渐变的背景样式,然后再通过 ClipPath 来裁剪,最后通过 AnimatedBuilder 与 AnimationController 动起来,代码如下:
/// 构建 AnimatedBuilder 与裁剪水波纹
///
AnimatedBuilder buildFirstAnimation(Size size) {
return AnimatedBuilder(
//绑定动画控制器
animation: _animationController,
builder: (BuildContext context, Widget child) {
//裁剪组件
return ClipPath(
//自定义裁剪路径
clipper: HeaderClipper(_animationController.value),
//裁剪的子Widget
child: Container(
//高度
height: size.height * 0.5,
//线性渐变颜色的样式
decoration: BoxDecoration(
gradient: LinearGradient(
//线性渐变的方向
begin: Alignment.bottomLeft,
end: Alignment.topRight,
colors: [Color(0xFFE0647B), Color(0xFFFCDD89)]),
),
),
);
},
);
}
ClipPath 用来裁剪自定义图片,定义如下:
/// 代码清单 8-34 自定义 Clipper
///
class HeaderClipper extends CustomClipper<Path> {
///取值为 -1 ~ 1.0
double moveFlag = 0;
HeaderClipper(this.moveFlag);
@override
Path getClip(Size size) {
//创建 Path
Path path = Path();
//移动到点 P0点 也是曲线的起点
path.lineTo(0, size.height * 0.8);
//计算控制点 P1 的坐标
double xCenter = size.width * 0.5 +
(size.width * 0.6 + 1) * sin(moveFlag * pi);
double yCenter = size.height * 0.8 + 69 * cos(moveFlag*pi);
//构建 二阶贝塞尔曲线
path.quadraticBezierTo(xCenter, yCenter, size.width, size.height * 0.8);
path.lineTo(size.width, 0);
return path;
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) {
//刷新
return true;
}
}
用到了 二阶贝塞尔曲线 ,占位分析图如下:
二阶贝塞尔曲线:
也用到了 pi :
pi 、cos、sin 是Flutter Sdk dart.math类中提供的。
【x1】微信公众号的每日提醒 随时随记 每日积累 随心而过 文章底部扫码关注
【x2】各种系列的视频教程 免费开源 关注 你不会迷路
【x3】系列文章 百万 Demo 随时 复制粘贴 使用
【x4】简短的视频不一样的体验
【x5】必须有源码
不局限于思维,不局限语言限制,才是编程的最高境界。
以小编的性格,肯定是要录制一套视频的,随后会上传
有兴趣 你可以关注一下 西瓜视频 — 早起的年轻人
最后
以上就是彩色枫叶为你收集整理的周末也需要学习 分享一个 Flutter 波浪波动效果的登录页面的背景 Flutter ClipPath实现的波动的全部内容,希望文章能够帮你解决周末也需要学习 分享一个 Flutter 波浪波动效果的登录页面的背景 Flutter ClipPath实现的波动所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复