服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - IOS - iOS实现手势解锁操作

iOS实现手势解锁操作

2021-01-10 14:44羽若其 IOS

这篇文章主要为大家详细介绍了iOS实现手势解锁操作功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文主要介绍通过手势识别实现手势解锁功能,这个方法被广泛用于手机解锁,密码验证,快捷支付等功能实现。事例效果如下所示。

iOS实现手势解锁操作

 首先,我们先分析功能的实现过程,首先我们需要先看大致的实现过程:

1.加载九宫格页面

2.实现按钮被点击及滑动过程中按钮状态的改变

3.实现滑动过程中的连线

4.绘制完毕后判定密码是否正确,

5.密码判定后实现跳转。

下面我们就来用代码实现上述五个过程。

1.加载九宫格界面

1.1九宫格内控件的分布 3*3 ,我们可以自定义view(包含3*3个按钮),添加到viewcontroller上。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//添加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)的类方法,

?
1
2
3
4
5
// 加载xib文件
+(instancetype)lockview
{
  return [[[nsbundle mainbundle]loadnibnamed:@"myblockview" owner:nil options:nil]lastobject];
}

然后加载到控制器上。

?
1
2
3
4
5
6
//  设置控制器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定义数组类型的成员属性,用来装被点击的按钮

?
1
2
3
4
5
6
7
8
9
@property(nonatomic,strong)nsmutablearray *btnarr;
//懒加载
-(nsmutablearray *)btnarr
{
  if (_btnarr==nil) {
    _btnarr=[nsmutablearray array];
  }
  return _btnarr;
}

2.2创建路径,绘制图形

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#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开始触摸

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#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滑动过程中,重绘

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#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.绘制完毕后判定密码是否正确

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#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值进行字符串拼接,密码传值是通过代理实现。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
#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.密码判定后实现跳转。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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;
 
}

代理判定密码并实现跳转

?
1
2
3
4
5
6
7
8
9
10
11
12
13
-(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属性

?
1
2
3
4
[self.navigationcontroller.navigationbar setbackgroundcolor:[uicolor redcolor]];
 [ self.navigationcontroller.navigationbar settitletextattributes:@{
                             nsforegroundcolorattributename :[uicolor whitecolor] 
                                  }];

以上就是本文的全部内容,希望对大家的学习有所帮助。

延伸 · 阅读

精彩推荐
  • IOSiOS 雷达效果实例详解

    iOS 雷达效果实例详解

    这篇文章主要介绍了iOS 雷达效果实例详解的相关资料,需要的朋友可以参考下...

    SimpleWorld11022021-01-28
  • IOS解析iOS开发中的FirstResponder第一响应对象

    解析iOS开发中的FirstResponder第一响应对象

    这篇文章主要介绍了解析iOS开发中的FirstResponder第一响应对象,包括View的FirstResponder的释放问题,需要的朋友可以参考下...

    一片枫叶4662020-12-25
  • IOSiOS布局渲染之UIView方法的调用时机详解

    iOS布局渲染之UIView方法的调用时机详解

    在你刚开始开发 iOS 应用时,最难避免或者是调试的就是和布局相关的问题,下面这篇文章主要给大家介绍了关于iOS布局渲染之UIView方法调用时机的相关资料...

    windtersharp7642021-05-04
  • IOSIOS 屏幕适配方案实现缩放window的示例代码

    IOS 屏幕适配方案实现缩放window的示例代码

    这篇文章主要介绍了IOS 屏幕适配方案实现缩放window的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要...

    xiari5772021-06-01
  • IOSIOS开发之字典转字符串的实例详解

    IOS开发之字典转字符串的实例详解

    这篇文章主要介绍了IOS开发之字典转字符串的实例详解的相关资料,希望通过本文能帮助到大家,让大家掌握这样的方法,需要的朋友可以参考下...

    苦练内功5832021-04-01
  • IOSiOS中tableview 两级cell的展开与收回的示例代码

    iOS中tableview 两级cell的展开与收回的示例代码

    本篇文章主要介绍了iOS中tableview 两级cell的展开与收回的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    J_Kang3862021-04-22
  • IOSiOS通过逆向理解Block的内存模型

    iOS通过逆向理解Block的内存模型

    自从对 iOS 的逆向初窥门径后,我也经常通过它来分析一些比较大的应用,参考一下这些应用中某些功能的实现。这个探索的过程乐趣多多,不仅能满足自...

    Swiftyper12832021-03-03
  • IOS关于iOS自适应cell行高的那些事儿

    关于iOS自适应cell行高的那些事儿

    这篇文章主要给大家介绍了关于iOS自适应cell行高的那些事儿,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的...

    daisy6092021-05-17