iOS实现手势解锁操作
程序员文章站
2023-11-29 23:28:04
本文主要介绍通过手势识别实现手势解锁功能,这个方法被广泛用于手机解锁,密码验证,快捷支付等功能实现。事例效果如下所示。
首先,我们先分析功能的实现过程,首...
本文主要介绍通过手势识别实现手势解锁功能,这个方法被广泛用于手机解锁,密码验证,快捷支付等功能实现。事例效果如下所示。
首先,我们先分析功能的实现过程,首先我们需要先看大致的实现过程:
1.加载九宫格页面
2.实现按钮被点击及滑动过程中按钮状态的改变
3.实现滑动过程中的连线
4.绘制完毕后判定密码是否正确,
5.密码判定后实现跳转。
下面我们就来用代码实现上述五个过程。
1.加载九宫格界面
1.1九宫格内控件的分布 3*3 ,我们可以自定义view(包含3*3个按钮),添加到viewcontroller上。
//添加view中子控件 -(void)awakefromnib { // 创建按钮 for (int i=0; i<9; i++) { self.linecolor=[uicolor bluecolor]; uibutton *btn=[uibutton buttonwithtype:uibuttontypecustom]; btn.userinteractionenabled=no; // 设置按钮属性 [btn setbackgroundimage:[uiimage imagenamed:@"gesture_node_normal"] forstate:uicontrolstatenormal]; [btn setbackgroundimage:[uiimage imagenamed:@"gesture_node_highlighted"] forstate:uicontrolstatehighlighted ]; [btn setbackgroundimage:[uiimage imagenamed:@"gesture_node_error"] forstate:uicontrolstatedisabled]; [self addsubview:btn]; } } //布局view子控件 -(void)layoutsubviews { [super layoutsubviews]; cgfloat width=74; cgfloat height=74; cgfloat margin=(self.bounds.size.width-3*width)/2; // 遍历设置9个button的frame [self.subviews enumerateobjectsusingblock:^(__kindof uiview * _nonnull obj, nsuinteger idx, bool * _nonnull stop) { // 通过tag设置按钮的索引标识 obj.tag=idx; int row=(int)idx/3; int col=idx%3; obj.frame=cgrectmake(col*(margin + width), row*(margin +height), width, height); }]; }
1.2将定义好的view通过xib添加到viewcontroller上
首先,定义一个blockview(九宫格view)的类方法,
// 加载xib文件 +(instancetype)lockview { return [[[nsbundle mainbundle]loadnibnamed:@"myblockview" owner:nil options:nil]lastobject]; }
然后加载到控制器上。
// 设置控制器view的背景图片 self.view.backgroundcolor=[uicolor colorwithpatternimage:[uiimage imagenamed:@"bg"]]; myblockview *blockview=[myblockview lockview]; blockview.center=self.view.center; // 将blockview添加到viewcontroller上 [self.view addsubview:blockview];
2.实现按钮被点击及滑动过程中按钮状态的改变
2.1定义数组类型的成员属性,用来装被点击的按钮
@property(nonatomic,strong)nsmutablearray *btnarr; //懒加载 -(nsmutablearray *)btnarr { if (_btnarr==nil) { _btnarr=[nsmutablearray array]; } return _btnarr; }
2.2创建路径,绘制图形
#pragma mark----绘制图形 -(void)drawrect:(cgrect)rect { if (self.btnarr.count==0 ) { return; } // 创建路径 uibezierpath *path=[uibezierpath bezierpath]; // 遍历所有按钮进行绘制 [self.btnarr enumerateobjectsusingblock:^(__kindof uibutton * _nonnull obj, nsuinteger idx, bool * _nonnull stop) { // 第一个按钮,中心点就是起点 if (idx==0) { [path movetopoint:obj.center]; }else { [path addlinetopoint:obj.center]; } }]; [path addlinetopoint:self.currentpoint]; // 设置路径属性 path.linewidth=10; path.linecapstyle=kcglinecapround; path.linejoinstyle=kcglinejoinround; [self.linecolor setstroke]; // 渲染 [path stroke]; }
2.3开始触摸
#pragma mark-----开始触摸 -(void)touchesbegan:(nsset<uitouch *> *)touches withevent:(uievent *)event { // 获取触摸对象 uitouch *touch=touches.anyobject; // 获取触摸点 cgpoint loc=[touch locationinview:self]; // 遍历按钮,判定触摸点是否在按钮上 [self.subviews enumerateobjectsusingblock:^(__kindof uibutton * _nonnull obj, nsuinteger idx, bool * _nonnull stop) { bool iscontains=cgrectcontainspoint(obj.frame, loc); // 如果在按钮上,将当前按钮保存在数组中,并改变按钮状态 if (iscontains&&obj.highlighted==no) { [self.btnarr addobject:obj]; obj.highlighted=yes; }else { obj.highlighted=no; } }]; }
2.4滑动过程中,重绘
#pragma mark----开始滑动 -(void)touchesmoved:(nsset<uitouch *> *)touches withevent:(uievent *)event { // 获取触摸对象 uitouch *touch=touches.anyobject; // 获取触摸点 cgpoint loc=[touch locationinview:self]; self.currentpoint=loc; // 遍历按钮,如果按钮在滑动路径上,就改变按钮状态 [self.subviews enumerateobjectsusingblock:^(__kindof uibutton * _nonnull obj, nsuinteger idx, bool * _nonnull stop) { bool iscontains=cgrectcontainspoint(obj.frame, loc); if (iscontains&&obj.highlighted==no) { [self.btnarr addobject:obj]; obj.highlighted=yes; } }]; // 重绘 [self setneedsdisplay]; }
3.实现滑动过程中的连线和4.绘制完毕后判定密码是否正确
#pragma mark----停止滑动结束 -(void)touchesended:(nsset<uitouch *> *)touches withevent:(uievent *)event { // 定义最后一个按钮 uibutton *lastbtn=[self.btnarr lastobject]; // 将最后一个按钮中心点定义为相对滑动的当前点 self.currentpoint=lastbtn.center; // 重绘 [self setneedsdisplay]; // 判定密码 self.password=[nsmutablestring string]; [self.btnarr enumerateobjectsusingblock:^( uibutton * _nonnull obj, nsuinteger idx, bool * _nonnull stop) { [self.password appendformat:@"%@",@(obj.tag)]; }]; nslog(@"%@",self.password); bool isok; if ([self.delegate respondstoselector:@selector(blockview:finishedwithpassword:)]) { isok= [self.delegate blockview:self finishedwithpassword:self.password]; } if (isok) { [self.btnarr enumerateobjectsusingblock:^(uibutton* _nonnull obj, nsuinteger idx, bool * _nonnull stop) { obj.highlighted=no; }]; [self.btnarr removeallobjects]; [self setneedsdisplay]; nslog(@"密码正确"); }else { nslog(@"密码错误"); } }
注意:我们在密码判定过程中是通过根据先前布局按钮的时候定义的按钮tag值进行字符串拼接,密码传值是通过代理实现。
#import <uikit/uikit.h> @class myblockview; //声明代理 @protocol myblockviewdelegate <nsobject> @optional //代理方法 -(bool) blockview:(myblockview *)blockview finishedwithpassword:(nsstring *)password; @end @interface myblockview : uiview +(instancetype)lockview; //设置代理成员属性 @property(nonatomic,weak)id<myblockviewdelegate>delegate; @end
5.密码判定后实现跳转。
else { // 关闭用户交互 self.userinteractionenabled=no; [self.btnarr enumerateobjectsusingblock:^(uibutton * _nonnull obj, nsuinteger idx, bool * _nonnull stop) { self.linecolor=[uicolor redcolor]; obj.highlighted=no; obj.enabled=no; [self setneedsdisplay]; dispatch_after(dispatch_time(dispatch_time_now, (int64_t)(1.0 * nsec_per_sec)), dispatch_get_main_queue(), ^{ // 回复按钮状态 [self.btnarr enumerateobjectsusingblock:^(uibutton * _nonnull obj, nsuinteger idx, bool * _nonnull stop) { obj.enabled=yes; }]; // 恢复线条的颜色 self.linecolor=[uicolor bluecolor]; [self.btnarr removeallobjects]; [self setneedsdisplay]; }); }]; nslog(@"密码错误"); } self.userinteractionenabled=yes; }
代理判定密码并实现跳转
-(bool)blockview:(myblockview *)blockview finishedwithpassword:(nsstring *)password { if ([password isequaltostring:@"012"]) { uiviewcontroller *two=[uiviewcontroller new]; two.view.backgroundcolor=[uicolor greencolor]; [self.navigationcontroller pushviewcontroller:two animated:yes]; return yes; } else{ return no; } }
最后设置控制器navigationbar属性
[self.navigationcontroller.navigationbar setbackgroundcolor:[uicolor redcolor]]; [ self.navigationcontroller.navigationbar settitletextattributes:@{ nsforegroundcolorattributename :[uicolor whitecolor] }];
以上就是本文的全部内容,希望对大家的学习有所帮助。
上一篇: Photoshop 一架怀旧的留声机
下一篇: JavaScript表单验证实现代码