首页 > 系统 > iOS > 正文

iOS实现手势解锁操作

2020-07-26 03:26:16
字体:
来源:转载
供稿:网友

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

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

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]                   }];

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表