Flutter實(shí)現(xiàn)滑動(dòng)塊驗(yàn)證碼功能
Flutter實(shí)現(xiàn)滑動(dòng)塊驗(yàn)證碼功能,供大家參考,具體內(nèi)容如下
本文實(shí)現(xiàn)的是一個(gè)用于登錄時(shí),向右滑動(dòng)滑動(dòng)塊到最右邊完成驗(yàn)證的一個(gè)功能。當(dāng)滑動(dòng)未到最右邊時(shí),滑動(dòng)塊回彈回左邊起始位置。
import 'package:flutter/material.dart'; ? class SlideVerifyWidget extends StatefulWidget{ ? ? /// 背景色 ? final Color backgroundColor; ? /// 滑動(dòng)過(guò)的顏色 ? 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; ? ? /// 滑動(dòng)塊寬度 ? double sliderWidth = 64; ? ? /// 驗(yàn)證是否通過(guò),滑動(dòng)到最右方為通過(guò) ? bool verifySuccess = false; ? ? /// 是否允許拖動(dòng) ? 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; ? ? ? ? } ? ? ? ? /// 當(dāng)滑動(dòng)到最右邊時(shí),通知驗(yàn)證成功,并禁止滑動(dòng) ? ? ? ? if(sliderDistance > width - sliderWidth){ ? ? ? ? ? sliderDistance = width - sliderWidth; ? ? ? ? ? enableSlide = false; ? ? ? ? ? verifySuccess = true; ? ? ? ? ? if(widget.verifySuccessListener != null){ ? ? ? ? ? ? widget.verifySuccessListener(); ? ? ? ? ? } ? ? ? ? } ? ? ? ? setState(() { ? ? ? ? }); ? ? ? }, ? ? ? onHorizontalDragEnd: (DragEndDetails details){ ? ? ? ? /// 滑動(dòng)松開(kāi)時(shí),如果未達(dá)到最右邊,啟動(dòng)回彈動(dòng)畫(huà) ? ? ? ? if(enableSlide){ ? ? ? ? ? enableSlide = false; ? ? ? ? ? _animationController.forward(); ? ? ? ? } ? ? ? }, ? ? ? child: Container( ? ? ? ? height: height, ? ? ? ? width: width, ? ? ? ? decoration: BoxDecoration( ? ? ? ? ? color: widget.backgroundColor, ? ? ? ? ? border: Border.all(color: widget.borderColor), ? ? ? ? ? ? /// 圓角實(shí)現(xiàn) ? ? ? ? ? borderRadius: BorderRadius.all(new Radius.circular(height)) ? ? ? ? ), ? ? ? ? child: Stack( ? ? ? ? ? children: <Widget>[ ? ? ? ? ? ? Positioned( ? ? ? ? ? ? ? top: 0, ? ? ? ? ? ? ? left: 0, ? ? ? ? ? ? ? child: Container( ? ? ? ? ? ? ? ? height: height - 2, ? ? ? ? ? ? ? ? /// 當(dāng)slider滑動(dòng)到距左邊只有兩三像素距離時(shí),已滑動(dòng)背景會(huì)有一點(diǎn)點(diǎn)渲染出邊框范圍, ? ? ? ? ? ? ? ? /// 因此當(dāng)滑動(dòng)距離小于1時(shí),直接將寬度設(shè)置為0,解決滑動(dòng)塊返回左邊時(shí)導(dǎo)致的綠色閃動(dòng),但如果是緩慢滑動(dòng)到左邊該問(wèn)題仍沒(méi)解決 ? ? ? ? ? ? ? ? width: sliderDistance < 1? 0 : sliderDistance + sliderWidth / 2, ? ? ? ? ? ? ? ? decoration: BoxDecoration( ? ? ? ? ? ? ? ? ? ? color: widget.slideColor, ? ? ? ? ? ? ? ? ? ? /// 圓角實(shí)現(xiàn) ? ? ? ? ? ? ? ? ? ? borderRadius: BorderRadius.all(new Radius.circular(height / 2)) ? ? ? ? ? ? ? ? ), ? ? ? ? ? ? ? ), ? ? ? ? ? ? ), ? ? ? ? ? ? Center( ? ? ? ? ? ? ? child: Text(verifySuccess?"驗(yàn)證成功":"請(qǐng)按住滑塊,拖動(dòng)到最右邊", style: TextStyle(color: verifySuccess?Colors.white:Colors.black54, fontSize: 14),), ? ? ? ? ? ? ), ? ? ? ? ? ? Positioned( ? ? ? ? ? ? ? top: 0, ? ? ? ? ? ? ? /// 此處將sliderDistance距離往左偏2是解決當(dāng)滑動(dòng)塊滑動(dòng)到最右邊時(shí)遮擋外部邊框 ? ? ? ? ? ? ? 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), ? ? ? ? ? ? ? ? ? ? /// 圓角實(shí)現(xiàn) ? ? ? ? ? ? ? ? ? ? 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,), ? ? ? ? ? ? ? ? ? ? /// 因?yàn)橄蛴壹^有透明邊距導(dǎo)致兩個(gè)箭頭間隔過(guò)大,因此將第二個(gè)箭頭向左偏移,如果切圖無(wú)邊距則不用偏移 ? ? ? ? ? ? ? ? ? ? Transform( ? ? ? ? ? ? ? ? ? ? ? transform: Matrix4.translationValues(-8, 0, 0), ? ? ? ? ? ? ? ? ? ? ? child: Image.asset("assets/images/ic_next_primary.png", height: 16, width: 16,), ? ? ? ? ? ? ? ? ? ? ), ? ? ? ? ? ? ? ? ? ], ? ? ? ? ? ? ? ? ), ? ? ? ? ? ? ? ), ? ? ? ? ? ? ) ? ? ? ? ? ], ? ? ? ? ), ? ? ? ), ? ? ); ? } ? ? /// 回彈動(dòng)畫(huà) ? 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(); ? ? ? } ? ? }); ? } ? }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android入門之ActivityGroup+GridView實(shí)現(xiàn)Tab分頁(yè)標(biāo)簽的方法
這篇文章主要介紹了Android入門之ActivityGroup+GridView實(shí)現(xiàn)Tab分頁(yè)標(biāo)簽的方法,非常實(shí)用的功能,需要的朋友可以參考下2014-08-08基于flutter?sound插件實(shí)現(xiàn)錄音與播放功能
這篇文章主要介紹了基于flutter?sound插件實(shí)現(xiàn)錄音與播放功能,介紹了如何錄音,如何播放本地和遠(yuǎn)程音頻文件,以及如何實(shí)現(xiàn)動(dòng)畫(huà),在錄制完音頻文件后如何上傳,這些都是我們平常使用這個(gè)功能會(huì)遇到的問(wèn)題。在使用的過(guò)程中遇到的問(wèn)題也有列出,需要的朋友可以參考下2022-05-05Android使用CircleImageView實(shí)現(xiàn)圓形頭像的方法
圓形頭像看起來(lái)非常美觀,下文通過(guò)實(shí)例代碼給大家介紹android中使用CircleImageView實(shí)現(xiàn)圓形頭像的方法,一起看看吧2016-09-09Android通過(guò)手勢(shì)實(shí)現(xiàn)答題器翻頁(yè)效果
這篇文章主要為大家詳細(xì)介紹了Android通過(guò)手勢(shì)實(shí)現(xiàn)答題器翻頁(yè)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-05-05Android基于AudioManager、PhoneStateListener實(shí)現(xiàn)設(shè)置黑名單功能
這篇文章主要介紹了Android基于AudioManager、PhoneStateListener實(shí)現(xiàn)設(shè)置黑名單功能的方法,涉及Android操作手機(jī)通信錄及通話模式與手機(jī)狀態(tài)的相關(guān)技巧,需要的朋友可以參考下2016-01-01Android ListView的Item點(diǎn)擊效果的定制
這篇文章主要介紹了Android ListView的Item點(diǎn)擊效果的定制的相關(guān)資料,需要的朋友可以參考下2017-07-07Android自定義帶增長(zhǎng)動(dòng)畫(huà)和點(diǎn)擊彈窗提示效果的柱狀圖DEMO
這篇文章主要介紹了Android自定義帶增長(zhǎng)動(dòng)畫(huà)和點(diǎn)擊彈窗提示效果的柱狀圖的相關(guān)資料,非常不錯(cuò)具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2016-11-11Android自定義動(dòng)畫(huà)根據(jù)控件Y軸旋轉(zhuǎn)動(dòng)畫(huà)(仿紅包)
這篇文章主要介紹了Android自定義動(dòng)畫(huà)根據(jù)控件Y軸旋轉(zhuǎn)動(dòng)畫(huà)(仿紅包),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-06-06android實(shí)現(xiàn)簡(jiǎn)易登錄注冊(cè)界面及邏輯設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)簡(jiǎn)易登錄注冊(cè)界面及邏輯設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06activitygroup 切換動(dòng)畫(huà)效果如何實(shí)現(xiàn)
本文將詳細(xì)介紹activitygroup 切換動(dòng)畫(huà)效果實(shí)現(xiàn)過(guò)程,需要聊解的朋友可以參考下2012-12-12