Flutter正在开发一个超酷的登录页面
看到一个比较酷的登录页面效果是这样的:
我觉得很酷,所以自己实现了,效果如下:
我们一步步来步骤 分析是如何完成的?
需求分析
首先,这是一个老套路了,我们看看需要做什么:
- 首先,我们最明显的需求就是点击注册按钮打开Dialog
- 之后打开Dialog,它也会在延迟一段时间后出现在Dialog身上。内容
- 描述Dialog的文字有两种颜色
- 单击“接受”按钮会改变颜色,减少强烈反对并显示“确定”图标
- 单击“我同意”按钮会显示带有“白色面具”的所有其他Dialog文字
- 按钮后“同意”动画结束时,关闭当前对话框,并将标志向上移动
- 跳转到另一页,文字以波浪状跳转
- 文字跳转后,出现对话框会出现框和键盘
开始现在
的实现要求已经了解了,下面就是分步实现的效果了。 ?设置圆角是不行的,
所以你需要给它一个底页
背景。这个参数在showModalBottomSheet
方法中:
showModalBottomSheet(
context: context,
backgroundColor: Colors.transparent,
builder: (context) {
Future.delayed(Duration(milliseconds: 50), () {
_animationController.forward();
});
return AnimatedUserAgreement(
animation: _animation,
);
});
)
复制代码
设置backgroundColor
这样就可以了。
2。打开Dialog后,打开Dialog的内容一段时间
这里我写了一个“动画小部件”,在Dialog中同时动画小部件的透明度和位置:
return Container(
height: 270,
padding: EdgeInsets.all(30),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30), color: Colors.white),
child: Opacity(
opacity: _opacityTween.evaluate(animation),
child: Stack(
children: <Widget>[
SingleChildScrollView(
child: Container(
child: UserAgreementDialog(),
margin: EdgeInsets.only(top: _offsetTween.evaluate(animation)),
),
)
],
),
),
);
复制代码
也许细心的同学可以看到上面的代码有问题:
为什么要添加SingleChildScrollView
?
因为这里我使用了动画效果“动态改变容器边距值”,
所以如果你不使用ScrollView它会覆盖ScrollView。
3。描述Dialog的文字有两种颜色
这两种颜色的要求比较简单,用“TextSpan”就可以解决。
我不发布代码。
4。点击“接受”会改变颜色,减少后坐力并显示ok图标
重点来了。这个功能比较复杂,但是只要我们了解了需求,还是比较容易写的。
首先我们也把这个功能点一分为二:
- 点击按钮改变颜色
- 点击后变成原来的颜色并缩小成圆形
- 变成后的动画效果一个圆圈 OK 图标
的显示仍然是一步一步完成的。 ? 参数onTapDown
在“点击”时回调:
onTapDown: (d) {
setState(() {
btnColor = btnColors[1];
});
复制代码
没有不必要的复杂性,只需更改按钮的颜色即可。
2。点击后会变成原来的颜色并缩小成圆形
点击后怎么办?或者没有点击?
GestureDetector
还为我们包装了它:
- onTapUp:单击取消时的回调
- TapCancel:第一次调用单元格:单击单元格被取消单击获取更改颜色返回。
然后处理抬起时的逻辑。升起也有两个逻辑:
- 按钮缩小成圆圈
- 缩小成圆圈时弹出 ok 图标
首先说第一点:
有反弹效果它缩小成一个圆圈,因此您无法使用
AnimatedContainer
。要实现此效果,您必须使用动画
。我使用
AnimatedBuilder
来打包这个小部件。那么我们来说第二点:
用圆圈缩小时如何弹出确定图标?
我们可以使用
IndexStack
键来启动下降动画。由于ok图标的缩放状态初始为0,所以页面上没有图标,方便我们制作后续的动画。小部件代码如下:
AnimatedBuilder( animation: _widthAnimation, builder: (BuildContext context, Widget child) { return Container( width: _widthAnimation.value, alignment: Alignment.center, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(40)), color: btnColor), margin: EdgeInsets.only(top: btnMargin), height: btnHeight, child: IndexedStack( alignment: Alignment.center, index: index, children: <Widget>[ Text( 'Accepteer', style: TextStyle(fontSize: 18), ), ScaleTransition( scale: _scaleTween.animate(_animation), child: Image.asset( 'images/ok.png', width: 35, height: 35, ), ) ], ), ); }, ), 复制代码
5。当你点击“接受”时,Dialog中的所有其他文本都会被“白色蒙版”
这也很简单,
container
默认参数是::❀在这个参数中我们只需要指定我们想要遮盖的颜色。但是还必须注意一件事。如果一开始使用的蒙版颜色是“透明色”,则整体颜色将变为黑色。具体原因我还没有研究过。有知道的人可以告诉我一下。
这样点击按钮后效果就完成了。代码如下:
onTapUp: (d) { Future.delayed(Duration(milliseconds: 60), () { setState(() { foregroundColor = Colors.white70; btnColor = btnColors[0]; index = 1; }); _widthController.forward(); Future.delayed(Duration(milliseconds: 200), () { _controller.forward().then((va) { Navigator.pop(context); }); }); }); } 复制代码
6。动画结束后,关闭活动对话框并将徽标向上移动。如果被拒绝,只需调整margin值即可。
代码如下:
setState(() { logoMargin = 100; }); 复制代码
这样对话框就有了向下运动的动画,logo向上移动,就达到了想要的效果。
7。跳转到另一页,文字弹出为波浪形
如何让文字弹出为波浪形?
我们首先想到的一定是动画,因为只有动画才有这种反弹效果。
这么多字,每一个都要动画化吗?
答案是肯定的。
既然知道了这一点,我们就只能一步一步来了。
您可以看到每个文本都从透明变为不透明,并且位置也发生了变化。
那么我们先封装
动画Widget
。代码如下:
class AnimatedStrWidget extends AnimatedWidget { final Tween<double> _opacityTween = Tween(begin: 0, end: 1); final Tween<Offset> _offsetTween = Tween(begin: Offset(0, 3), end: Offset(0, 0)); final Widget child; AnimatedStrWidget( {Key key, @required Animation<double> animation, @required this.child}) : super(key: key, listenable: animation); @override Widget build(BuildContext context) { final Animation<double> animation = listenable; return Opacity( opacity: _opacityTween.evaluate(animation) < 0 ? 0 : _opacityTween.evaluate(animation) > 1 ? 1 : _opacityTween.evaluate(animation), child: SlideTransition( position: _offsetTween.animate(animation), child: child, ), ); } } 复制代码
这里有两点需要注意:
- 透明度不能为负数,不能大于1,因为我们的影响力有反弹作用,所以决策必须被制作。做。
- Tween 这里的值是总高度的倍数,所以不要以为它是像素值。
封装后,我们就可以愉快的玩了:
void startAnim() async { for (int i = 0; i < strs.length; i++) { Future.delayed( Duration( milliseconds: i * 100, ), () { _strController[i].forward(); }); } } 复制代码
文字弹出效果时间为600ms。这里我们设置动画每100ms一次。
这个效果比较好,更像是波浪弹窗。8。文本出现后,会出现一个对话框和键盘
我们都应该积极注意键盘弹出窗口。使用
FocusNode
,这里我们只需要指定最后一个动画何时完成即可。完成后,打开隐藏键盘,然后打开键盘就可以了。
代码如下:
_strPositionAnimation[strs.length - 1].addStatusListener((status){ if(status == AnimationStatus.completed){ setState(() { opacity = 1; FocusScope.of(context).requestFocus(myFocusNode); }); } }); 复制代码
总结
这个页面花了我一晚上的时间来实现。不得不说,事情还有很多。
要实现这么酷的登录页面还是蛮难的。
我在这里实现的效果仍然不完美,与原始图像相比看起来有点“苦恼”。
不过没关系,只是改变动画的时长而已。
俗话说,当你了解自己的需求时,一切都会变得更容易。
代码上传至GitHub:github.com/wanglu1209/…
作者:Flutter Notes
链接:https://juejin.im/post/5d6da963ad26来源:掘金
版权所有归作者。商业转载请联系作者获取授权。非商业转载请注明出处。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。