iOS实现九宫格连线手势解锁

本文实例为大家分享了iOS实现九宫格连线手势解锁的具体代码,供大家参考,具体内容如下

Demo下载地址:手势解锁

效果图:

核心代码:

//
// ClockView.m
// 手势解锁
//
// Created by llkj on 2017/8/24.
// Copyright © 2017年 LayneCheung. All rights reserved.
//

#import "ClockView.h"

@interface ClockView ()

//存放当前选中的按钮
@property (nonatomic, strong) NSMutableArray *selectBtnArry;

//当前手指所在点
@property (nonatomic, assign) CGPoint curP;

@end

@implementation ClockView

- (void)awakeFromNib{

 [super awakeFromNib];

 //初始化
 [self setUp];
}

- (NSMutableArray *)selectBtnArry{

 if (_selectBtnArry == nil) {
  _selectBtnArry = [NSMutableArray array];
 }
 return _selectBtnArry;
}

- (void)setUp{

 for (int i = 0; i < 9; i ++) {

  //创建按钮
  UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];

  btn.tag = i;

  btn.userInteractionEnabled = NO;

  [btn setImage:[UIImage imageNamed:@"gesture_node_normal"] forState:UIControlStateNormal];

  [btn setImage:[UIImage imageNamed:@"gesture_node_selected"] forState:UIControlStateSelected];

  [self addSubview:btn];
 }
}

//获取当前点
- (CGPoint)getCurrentPoint:(NSSet *)point{

 UITouch *touch = [point anyObject];
 return [touch locationInView:self];

}

//返回按钮
- (UIButton *)btnRectContainsPoint:(CGPoint)point{

 //遍历brn判断当前点在不在btn上
 for (UIButton *btn in self.subviews) {
  if (CGRectContainsPoint(btn.frame, point)) {
   return btn;
  }
 }
 return nil;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

 //1.获取当前点
 CGPoint curP = [self getCurrentPoint:touches];

 //2.判断当前点在不在btn上
 UIButton *btn = [self btnRectContainsPoint:curP];
 if (btn && btn.selected == NO) {
  btn.selected = YES;

  //保存选中的按钮
  [self.selectBtnArry addObject:btn];
 }

}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

 //1.获取当前点
 CGPoint curP = [self getCurrentPoint:touches];
 self.curP = curP;

 //2.判断当前点在不在btn上
 UIButton *btn = [self btnRectContainsPoint:curP];
 if (btn && btn.selected == NO) {
  btn.selected = YES;

  //保存选中的按钮
  [self.selectBtnArry addObject:btn];
 }
 //重绘
 [self setNeedsDisplay];
}

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

 NSMutableString *str = [NSMutableString string];
 //1.取消所有选中的按钮
 for (UIButton *btn in self.selectBtnArry) {
  btn.selected = NO;
  [str appendFormat:@"%ld", btn.tag];
 }
 //2.清空路径
 [self.selectBtnArry removeAllObjects];
 [self setNeedsDisplay];

 //查看是否是第一次设置密码
 NSString *keyPwd = [[NSUserDefaults standardUserDefaults] objectForKey:@"keyPwd"];
 if (!keyPwd) {
  [[NSUserDefaults standardUserDefaults] setObject:str forKey:@"keyPwd"];
  [[NSUserDefaults standardUserDefaults] synchronize];

  UIAlertView *alertV = [[UIAlertView alloc] initWithTitle:@"第一次设置密码成功" message:nil delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
  [alertV show];
  NSLog(@"第一次输入密码");
 }else{

  if ([keyPwd isEqualToString:str]) {
   NSLog(@"密码正确");
   UIAlertView *alertV = [[UIAlertView alloc] initWithTitle:@"手势输入正确" message:nil delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
   [alertV show];

  }else{
   NSLog(@"密码错误");
   UIAlertView *alertV = [[UIAlertView alloc] initWithTitle:@"手势输入错误" message:nil delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
   [alertV show];
  }
 }
 //3.查看当前选中按钮的顺序
 NSLog(@"选中按钮顺序为:%@",str);
}

- (void)drawRect:(CGRect)rect{

 if (self.selectBtnArry.count) {
  //1.创建路径
  UIBezierPath *path = [UIBezierPath bezierPath];

  //2.取出所有保存的按钮
  for (int i = 0; i < self.selectBtnArry.count; i ++) {
   UIButton *btn = self.selectBtnArry[i];

   //当前按钮是不是第一个按钮
   if (i == 0) {
    //设置成路径的起点
    [path moveToPoint:btn.center];
   } else {
    //添加一根线到按钮中心
    [path addLineToPoint:btn.center];
   }
  }

  //添加一根线到当前手指所在点
  [path addLineToPoint:self.curP];

  //设置线宽/颜色
  [path setLineWidth:5];
  [[UIColor whiteColor] set];
  [path setLineJoinStyle:kCGLineJoinRound];

  //3.绘制路径
  [path stroke];
 }

}
- (void)layoutSubviews{

 [super layoutSubviews];

 CGFloat x = 0;
 CGFloat y = 0;

 CGFloat btnWH = 75;

 int column = 3;
 int margin = (self.bounds.size.width - (column * btnWH)) / (column + 1);

 int currentColumn = 0;
 int currentRow = 0;

 for (int i = 0; i < self.subviews.count; i ++) {

  // 求当前所在的列
  currentColumn = i % column;

  // 求当前所在的行
  currentRow = i / column;

  x = margin + (btnWH + margin) * currentColumn;

  y = margin + (btnWH + margin) * currentRow;

  UIButton *btn = self.subviews[i];

  btn.frame = CGRectMake(x, y, btnWH, btnWH);
 }
}
@end

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

时间: 2020-04-16

关于iOS自带九宫格拼音键盘和Emoji表情之间的一些坑

发现问题 最近产品提了一个需求:要求某个"输入框"禁止输入 Emoji 表情,我们能想到的方案是:在 UITextField 的 textField:shouldChangeCharactersInRange:replacementString: 代理方法中判断即将输入的字符串是否包含 Emoji 表情,如果包含,就在该方法中返回 NO,不允许输入. 关于如何判断一字符串是否包含 Emoji 表情的方法,网上已经有很多代码片段,一般是通过 Unicode 编码范围来判断 ,详见这里:h

深入解析iOS应用开发中九宫格视图布局的相关计算方法

来看一个简单的例子: 复制代码 代码如下: /*  * 总列数  */ NSUInteger totalloc = 3; /*  * View的宽高  */ CGFloat shopW = 80; CGFloat shopH = 100; /*  * 每个View之间的间隔  */ CGFloat margin = (self.view.frame.size.width - totalloc * shopW) / (totalloc + 1); /*  * View的总个数  */ NSUInt

iOS实现手势解锁操作

本文主要介绍通过手势识别实现手势解锁功能,这个方法被广泛用于手机解锁,密码验证,快捷支付等功能实现.事例效果如下所示. 首先,我们先分析功能的实现过程,首先我们需要先看大致的实现过程: 1.加载九宫格页面 2.实现按钮被点击及滑动过程中按钮状态的改变 3.实现滑动过程中的连线 4.绘制完毕后判定密码是否正确, 5.密码判定后实现跳转. 下面我们就来用代码实现上述五个过程. 1.加载九宫格界面 1.1九宫格内控件的分布 3*3 ,我们可以自定义view(包含3*3个按钮),添加到viewContr

iOS仿邮箱大师的九宫格手势密码解锁

本文实例为大家分享了iOS手势密码解锁的相关代码,供大家参考,具体内容如下 // // LockView.m // 手势解锁 // // Created by Daniel on 16/4/4. // Copyright © 2016年 Daniel. All rights reserved. // #import "LockView.h" @interface LockView () /** 保存已选中的按钮 */ @property(nonatomic, strong) NSMut

iOS实现九宫格自动生成视图

在移动开发里有相当多的时候需要使控件呈现九宫格格式的分布,最常见的如 图案解锁界面: 相册管理界面: 单独创建一个这样界面的步骤相当繁琐,要创建父视图用于控制每一个单独的控件,而控件添加的时候还要判断每一格的位置,而且代码复用性不高,因为每一种九宫格视图的控件边距,控件的宽高不同. 所以,是否可以写一个这样的模块,只需要提供一个子控件的frame就能够生成一个完整的九宫格视图呢? 以下是我的思路: 首先肯定是用一个类来管理整个模块的,所以创建一个UISodokuView类继承于UIScrollV

详解iOS应用UI开发中的九宫格坐标计算与字典转换模型

九宫格坐标计算 一.要求 完成下面的布局 二.分析 寻找左边的规律,每一个uiview的x坐标和y坐标. 三.实现思路 (1)明确每一块用得是什么view (2)明确每个view之间的父子关系,每个视图都只有一个父视图,拥有很多的子视图. (3)可以先尝试逐个的添加格子,最后考虑使用for循环,完成所有uiview的创建 (4)加载app数据,根据数据长度创建对应个数的格子 (5)添加格子内部的子控件 (6)给内部的子控件装配数据 四.代码示例 复制代码 代码如下: // //  YYViewC

IOS 九宫格布局实现方法

以前刚开始搞iOS的时候大部分都是通过计算frame来布局视图,搞着搞着貌似都是用自动布局来搞定了,因为自动布局实在太方便.太好用了,所以当我昨天突然回看以前代码的时候突然看到了以前写的九宫格布局,感觉很多东西都忘了,所以今天特意在这里记录一下,并且通过几个简单的宏定义来完成布局的需求,具体大家看代码吧,都有注释 很好懂: // // ButtonContainerView.h // chemuchao // // Created by 遇见远洋 on 16/3/7. // Copyright

IOS自定义UIButton九宫格效果

此篇文章给大家描写如何写自定义九宫格,因为在开发中,这种需求也是常见不少.因此,主要利用UIButton阐述的: 实列不复杂,就两三个步骤完成: 一.定义宽度与高度(self.view) #define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width #define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height #define JHRGB(r,g,b) [UIColor co

使用Swift代码实现iOS手势解锁、指纹解锁实例详解

一.手势密码 1. 1.1.用UIButton组成手势的节点. 1.2.当手指接触屏幕时,调用重写的 touchesBegan:withEvent方法(在touchesBegan里调用setNeedsDisplay,这样就会自动调用drawRect方法). 1.3.当手指在屏幕上滑动时,调用重写的touchesEnded:withEvent方法. 这两个方法执行的操作是一样的:通过locationInView获取 触摸的坐标,然后用 CGRectContainsPoint 判断手指是否经过UIB

IOS 获取APP 版本号的实例详解

IOS 获取APP 版本号的实例详解 看代码的时候看到一句,用于获取.plist文件的版本号 labelVersion.text = [NSString stringWithFormat:@"v%@", [[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString*)kCFBundleVersionKey]]; 比较感兴趣的是后面的参数 kcFBundleVersionKey ,竟然是CFBundle.h已经定于好的属性,下面有

IOS 创建并发线程的实例详解

IOS 创建并发线程的实例详解 创建并发线程 主线程一般都是处理UI界面及用户交互的事儿的.其他的事一般就要另外的线程去处理,如下载,计算等... 现在先简单创建3个线程,分别打印出1-1000,,为了方便,线程3就放在主线程中执行. - (void) firstCounter{ @autoreleasepool { NSUInteger counter = 0; for (counter = 0; counter < 1000; counter++){ NSLog(@"First Cou

基于iOS Realm数据库的使用实例详解

首先下载Realm源代码,https://realm.io/cn/docs/objc/latest 将下载的文件解压,从 ios/static/ 目录中将 Realm.framework 拖曳到 Xcode 工程的文件导航器内,然后在 Xcode 文件导航器中选中工程.然后选择应用目标,前往 Build Phases 选项卡.在 Link Binary with Libraries 部分中单击 + 按钮,然后添加 libc++.tbd 和 libz.tbd.这样还没有完,我们还需要安装插件,打开

IOS UITableView颜色设置的实例详解

IOS UITableView颜色设置的实例详解 1.系统默认的颜色设置  //无色 cell.selectionStyle = UITableViewCellSelectionStyleNone; //蓝色 cell.selectionStyle = UITableViewCellSelectionStyleBlue; //灰色 cell.selectionStyle = UITableViewCellSelectionStyleGray; 2.自定义颜色和背景设置 改变UITableView

IOS文件的简单读写实例详解

IOS文件的简单读写实例详解 数组(可变与不可变)和字典(可变与不可变)中元素对象的类型,必须是NSString,NSArray,NSDictionary,NSData,否则不能直接写入文件 #pragma mark---NSString的写入与读取--- //1:获取路径 NSString *docunments = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)firstObje

微信小程序 监听手势滑动切换页面实例详解

微信小程序 监听手势滑动切换页面实例详解 1.对应的xml里写上手势开始.滑动.结束的监听: <view class="touch" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd" ></view> 2.js: var touchDot = 0;//触摸时的原点 var time = 0;// 时

IOS 陀螺仪开发(CoreMotion框架)实例详解

iOS陀螺仪 参数意义 self.mManager = [[CMMotionManager alloc]init]; self.mManager.deviceMotionUpdateInterval = 0.5; if (self.mManager.gyroAvailable) { [self.mManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMDeviceMotion

iOS如何自定义启动界面实例详解

简介: 平常开发中对于启动页可能会有一些特别的要求,比如在启动页加动画或加一些按键可以响应事件等,最近项目中要在启动页增加版本号,因为版本号是不断的改变,所以要动态实现把它加到启动页上 正巧最近在重构app,原app用的是xcode自带的启动图设置.但相对来说自定义启动图可扩展性更强一点,今天花了一些时间弄了一下~ 实现思路: 思路是自定义一个控制器,在viewDidLoad的方法中调用要设置的启动图的方法,方法中主要是创建一个UIImageView,对UIImageView的image进行定义

iOS中的线程死锁实例详解

什么是线程死锁 是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去. 线程死锁怎么发生 发生死锁的情况一般是两个对象的锁相互等待造成的. 死锁发生的条件 1.互斥条件:所谓互斥就是进程在某一时间内独占资源. 2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放. 3.不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺. 4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系. 死锁通常是一个线程锁定了一