Flutter滑动块验证码功能
yuan1809 人气:0Flutter实现滑动块验证码功能,供大家参考,具体内容如下
本文实现的是一个用于登录时,向右滑动滑动块到最右边完成验证的一个功能。当滑动未到最右边时,滑动块回弹回左边起始位置。
import 'package:flutter/material.dart'; class SlideVerifyWidget extends StatefulWidget{ /// 背景色 final Color backgroundColor; /// 滑动过的颜色 final Color slideColor; /// 边框颜色 final Color borderColor; final double height; final double width; final VoidCallback verifySuccessListener; const SlideVerifyWidget({ Key key, this.backgroundColor = Colors.blueGrey, this.slideColor = Colors.green, this.borderColor = Colors.grey, this.height = 44, this.width = 240, this.verifySuccessListener }) : super(key: key); @override State<StatefulWidget> createState() { return SlideVerifyState(); } } class SlideVerifyState extends State<SlideVerifyWidget> with TickerProviderStateMixin{ double height; double width ; double sliderDistance = 0; double initial = 0.0; /// 滑动块宽度 double sliderWidth = 64; /// 验证是否通过,滑动到最右方为通过 bool verifySuccess = false; /// 是否允许拖动 bool enableSlide = true; AnimationController _animationController; Animation _curve; @override void initState() { super.initState(); this.width = widget.width; this.height = widget.height; _initAnimation(); } @override void dispose() { _animationController?.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return GestureDetector( onHorizontalDragStart: (DragStartDetails details){ if(!enableSlide){ return; } initial = details.globalPosition.dx; }, onHorizontalDragUpdate: (DragUpdateDetails details){ if(!enableSlide){ return; } sliderDistance = details.globalPosition.dx - initial; if(sliderDistance < 0){ sliderDistance = 0; } /// 当滑动到最右边时,通知验证成功,并禁止滑动 if(sliderDistance > width - sliderWidth){ sliderDistance = width - sliderWidth; enableSlide = false; verifySuccess = true; if(widget.verifySuccessListener != null){ widget.verifySuccessListener(); } } setState(() { }); }, onHorizontalDragEnd: (DragEndDetails details){ /// 滑动松开时,如果未达到最右边,启动回弹动画 if(enableSlide){ enableSlide = false; _animationController.forward(); } }, child: Container( height: height, width: width, decoration: BoxDecoration( color: widget.backgroundColor, border: Border.all(color: widget.borderColor), /// 圆角实现 borderRadius: BorderRadius.all(new Radius.circular(height)) ), child: Stack( children: <Widget>[ Positioned( top: 0, left: 0, child: Container( height: height - 2, /// 当slider滑动到距左边只有两三像素距离时,已滑动背景会有一点点渲染出边框范围, /// 因此当滑动距离小于1时,直接将宽度设置为0,解决滑动块返回左边时导致的绿色闪动,但如果是缓慢滑动到左边该问题仍没解决 width: sliderDistance < 1? 0 : sliderDistance + sliderWidth / 2, decoration: BoxDecoration( color: widget.slideColor, /// 圆角实现 borderRadius: BorderRadius.all(new Radius.circular(height / 2)) ), ), ), Center( child: Text(verifySuccess?"验证成功":"请按住滑块,拖动到最右边", style: TextStyle(color: verifySuccess?Colors.white:Colors.black54, fontSize: 14),), ), Positioned( top: 0, /// 此处将sliderDistance距离往左偏2是解决当滑动块滑动到最右边时遮挡外部边框 left: sliderDistance > sliderWidth ? sliderDistance - 2 : sliderDistance, child: Container( width: sliderWidth, height: height - 2 , alignment: Alignment.center, decoration: BoxDecoration( color: Colors.white, border: Border.all(color: widget.borderColor), /// 圆角实现 borderRadius: BorderRadius.all(new Radius.circular(height)) ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ SizedBox(width: 6,), Image.asset("assets/images/ic_safety.png", height: 24, width: 24,), Image.asset("assets/images/ic_next_primary.png", height: 16, width: 16,), /// 因为向右箭头有透明边距导致两个箭头间隔过大,因此将第二个箭头向左偏移,如果切图无边距则不用偏移 Transform( transform: Matrix4.translationValues(-8, 0, 0), child: Image.asset("assets/images/ic_next_primary.png", height: 16, width: 16,), ), ], ), ), ) ], ), ), ); } /// 回弹动画 void _initAnimation(){ _animationController = AnimationController( duration: const Duration(milliseconds: 300), vsync: this); _curve = CurvedAnimation(parent: _animationController, curve: Curves.easeOut); _curve.addListener(() { setState(() { sliderDistance = sliderDistance - sliderDistance * _curve.value; if(sliderDistance <= 0){ sliderDistance = 0; } }); }); _animationController.addStatusListener((status) { if(status == AnimationStatus.completed){ enableSlide = true; _animationController.reset(); } }); } }
加载全部内容