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)松開時(shí),如果未達(dá)到最右邊,啟動(dòng)回彈動(dòng)畫
? ? ? ? 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)題仍沒解決
? ? ? ? ? ? ? ? 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)畫
? 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)畫,在錄制完音頻文件后如何上傳,這些都是我們平常使用這個(gè)功能會(huì)遇到的問(wèn)題。在使用的過(guò)程中遇到的問(wèn)題也有列出,需要的朋友可以參考下2022-05-05
Android使用CircleImageView實(shí)現(xiàn)圓形頭像的方法
圓形頭像看起來(lái)非常美觀,下文通過(guò)實(shí)例代碼給大家介紹android中使用CircleImageView實(shí)現(xiàn)圓形頭像的方法,一起看看吧2016-09-09
Android通過(guò)手勢(shì)實(shí)現(xiàn)答題器翻頁(yè)效果
這篇文章主要為大家詳細(xì)介紹了Android通過(guò)手勢(shì)實(shí)現(xiàn)答題器翻頁(yè)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-05-05
Android基于AudioManager、PhoneStateListener實(shí)現(xiàn)設(shè)置黑名單功能
這篇文章主要介紹了Android基于AudioManager、PhoneStateListener實(shí)現(xiàn)設(shè)置黑名單功能的方法,涉及Android操作手機(jī)通信錄及通話模式與手機(jī)狀態(tài)的相關(guān)技巧,需要的朋友可以參考下2016-01-01
Android ListView的Item點(diǎn)擊效果的定制
這篇文章主要介紹了Android ListView的Item點(diǎn)擊效果的定制的相關(guān)資料,需要的朋友可以參考下2017-07-07
Android自定義帶增長(zhǎng)動(dòng)畫和點(diǎn)擊彈窗提示效果的柱狀圖DEMO
這篇文章主要介紹了Android自定義帶增長(zhǎng)動(dòng)畫和點(diǎn)擊彈窗提示效果的柱狀圖的相關(guān)資料,非常不錯(cuò)具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2016-11-11
Android自定義動(dòng)畫根據(jù)控件Y軸旋轉(zhuǎn)動(dòng)畫(仿紅包)
這篇文章主要介紹了Android自定義動(dòng)畫根據(jù)控件Y軸旋轉(zhuǎn)動(dòng)畫(仿紅包),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-06-06
android實(shí)現(xiàn)簡(jiǎn)易登錄注冊(cè)界面及邏輯設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)簡(jiǎn)易登錄注冊(cè)界面及邏輯設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06
activitygroup 切換動(dòng)畫效果如何實(shí)現(xiàn)
本文將詳細(xì)介紹activitygroup 切換動(dòng)畫效果實(shí)現(xiàn)過(guò)程,需要聊解的朋友可以參考下2012-12-12

