UI进阶--Quartz2D和触摸事件的简单使用:手势解锁

需求:实现一个简易的手势解锁应用,具体效果如下图所示:

实现步骤:

1、代码创建界面,自定义一个view,设置view的背景,颜色等属性;

2、在自定义的view中,定义2个属性,一个是存储被选中按钮的可变数组,另外一个是最后的触摸点(CGPoint);

3、重写initWithFrame方法,在这里,自定义一个方法给initWithFrame方法调用即可,这个自定义的方法里,初始化9个按钮,设置每个按钮的tag,正常状态下的图片以及选中状态的图片,并设置和用户的交互为NO;

4、在自定义的view中的layoutSubviews方法中,自定义9个按钮;

5、在touchesBegan:和touchesMoved:方法中,判断触摸点是否在view上的9个按钮中,如果在,那么设置按钮的选中状态;(在这里,只写其中一个方法即可,另外一个方法直接调用)

5.1、进行遍历,并把选中的按钮放在选中按钮的可变数组中,并记录最后的触摸点;

5.2、在最后记得重绘图形,调用setNeedsDisplay方法;

6、在drawRect:方法中,绘制选中按钮之间的连线;

6.1、遍历选中按钮数组,得到选中按钮的数量,如果为0,直接返回;

6.2、使用UIBezierPath画线;

6.3、对绘制的线进行线宽,颜色、样式等设置

6.4、对绘制的线进行渲染;

7、在touchesEnded:方法中取消连线,并移除选中的按钮,最后重绘图形;

8、选择完密码后,把密码传回给控制器,让控制器判断选择是否正确;

8.1、在自定义的view中设置代理;

8.2、在touchesEnded:方法中拼接选中按钮的索引;

8.3、通知代理按钮的选择;

具体实现代码:

Controller:

 1 //
 2 //  ViewController.m
 3 //  1-4-Deblocking
 4 //
 5 //  Created by xiaomoge on 15/1/4.
 6 //  Copyright (c) 2015年 xiaomoge. All rights reserved.
 7 //
 8
 9 #import "ViewController.h"
10 #import "DeblockingView.h"
11 @interface ViewController () <DeblockingViewDelegate>
12
13 @end
14
15 @implementation ViewController
16
17 - (void)viewDidLoad {
18     [super viewDidLoad];
19     //设置背景颜色
20     self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"Home_refresh_bg"]];
21     //取得当前屏幕的宽度
22     CGFloat screenW = [UIScreen mainScreen].bounds.size.width;
23     //初始化一个DeblockingView
24     DeblockingView *deblockingView = [[DeblockingView alloc] initWithFrame:CGRectMake(0, 0, screenW, screenW)];
25     //设置背景颜色
26     deblockingView.backgroundColor = [UIColor clearColor];
27    //居中显示
28     deblockingView.center = self.view.center;
29    //设置代理
30     deblockingView.delegate = self;
31     [self.view addSubview:deblockingView];
32 }
33 #pragma mark - DeblockingViewDelegate方法
34 - (void)selectBtn:(DeblockingView *)deblockingView andSelectPwd:(NSString *)pwd {
35     NSString *tips;
36     if ([pwd isEqualToString:@"03478"]) {//设置一个固定的密码
37         tips = @"解锁成功";
38     }else {
39         tips = @"密码错误";
40     }
41     //弹出窗口提示
42     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:tips delegate:nil cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
43     [alert show];
44 }
45 @end

View:

 1 //
 2 //  DeblockingView.h
 3 //  1-4-Deblocking
 4 //
 5 //  Created by xiaomoge on 15/1/4.
 6 //  Copyright (c) 2015年 xiaomoge. All rights reserved.
 7 //
 8
 9 #import <UIKit/UIKit.h>
10 @class DeblockingView;
11 @protocol DeblockingViewDelegate <NSObject>
12 @optional
13 - (void)selectBtn:(DeblockingView *)deblockingView andSelectPwd:(NSString *)pwd;
14
15 @end
16 @interface DeblockingView : UIView
17 @property (nonatomic,assign) id<DeblockingViewDelegate> delegate;
18 @end
  1 //
  2 //  DeblockingView.m
  3 //  1-4-Deblocking
  4 //
  5 //  Created by xiaomoge on 15/1/4.
  6 //  Copyright (c) 2015年 xiaomoge. All rights reserved.
  7 //
  8
  9 #import "DeblockingView.h"
 10 @interface DeblockingView ()
 11 /*
 12  选中的按钮数组
 13  */
 14 @property (nonatomic,strong) NSMutableArray *selectedBtns;
 15 /*
 16  最后触摸到的点
 17  */
 18 @property (nonatomic,assign) CGPoint lastPoint;
 19 @end
 20 @implementation DeblockingView
 21 //懒加载
 22 - (NSMutableArray *)selectedBtns {
 23     if (!_selectedBtns) {
 24         _selectedBtns = [NSMutableArray array];
 25     }
 26     return _selectedBtns;
 27 }
 28 //绘制选中按钮间的连线
 29 - (void)drawRect:(CGRect)rect {
 30     //取得当前选中的按钮的个数
 31     NSInteger selectBtnCount = self.selectedBtns.count;
 32     //如果被选中的按钮个数为0,即返回。
 33     if (selectBtnCount == 0) return;
 34
 35     UIBezierPath *path = [UIBezierPath bezierPath];
 36     for (NSInteger i = 0; i < selectBtnCount; i++) {
 37         //取得按钮先连接的点
 38         CGPoint btnCenter = [self.selectedBtns[i] center];
 39         if (i == 0) {//设置为起点
 40             [path moveToPoint:btnCenter];
 41         }else {//设置为连接点
 42             [path addLineToPoint:btnCenter];
 43         }
 44     }
 45     //如果最后有未选中按钮的连线点
 46     [path addLineToPoint:self.lastPoint];
 47     //设置连线的宽度
 48     path.lineWidth = 8;
 49     //设置连线的头尾样式
 50     path.lineCapStyle = kCGLineCapRound;
 51     //设置连线的连接点样式
 52     path.lineJoinStyle = kCGLineJoinRound;
 53     //设置连线的颜色
 54     [[UIColor greenColor] set];
 55     //渲染
 56     [path stroke];
 57 }
 58 //加载完view后会调用这个方法
 59 - (void)layoutSubviews {
 60     [super layoutSubviews];//别忘记要写父类的方法
 61     //取得按钮的数量
 62     NSInteger btnCount = self.subviews.count;
 63     //设置按钮的宽度
 64     CGFloat btnW = 74;
 65     //设置按钮的高度
 66     CGFloat btnH = 74;
 67     //设置按钮间的间距
 68     CGFloat margin = (self.bounds.size.width - 3 * btnW) / 4;
 69     for (int i = 0; i < btnCount; i++) {
 70         //取得一个按钮
 71         UIButton *btn = self.subviews[i];
 72         //获得当前的行号
 73         int row = i / 3;
 74         //获得当前列号
 75         int culomns = i % 3;
 76         //设置按钮的X(可参考应用管理中的计算)
 77         CGFloat btnX = margin + culomns * (margin + btnW);
 78         //设置按钮的Y
 79         CGFloat btnY = margin + row * (margin + btnH);
 80         btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
 81     }
 82 }
 83 //初始化方法
 84 - (instancetype)initWithFrame:(CGRect)frame {
 85     if (self = [super initWithFrame:frame]) {
 86         [self setBtns];
 87     }
 88     return self;
 89 }
 90 //设置9个按钮
 91 - (void)setBtns {
 92     for (int i = 0; i < 9; i++) {
 93         UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
 94         btn.tag = i;
 95         //设置按钮正常状态下的图片
 96         [btn setImage:[UIImage imageNamed:@"gesture_node_normal"] forState:UIControlStateNormal];
 97         //设置按钮被选中时的图片
 98         [btn setImage:[UIImage imageNamed:@"gesture_node_highlighted"] forState:UIControlStateSelected];
 99         //取消与用户的交互
100         btn.userInteractionEnabled = NO;
101         [self addSubview:btn];
102     }
103 }
104 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
105     [self touchesMoved:touches withEvent:event];
106 }
107
108 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
109     //获取当前触摸点
110     UITouch *touch = [touches anyObject];
111     CGPoint touchPoint = [touch locationInView:touch.view];
112
113     for (UIButton *btn in self.subviews) {
114         if (CGRectContainsPoint(btn.frame, touchPoint)) {//判断触摸点是否在按钮的范围内
115             if (btn.selected == NO) {//在按钮范围内,并且为未选中状态时
116                 [self.selectedBtns addObject:btn];//加进选中按钮的数组
117             }
118             btn.selected = YES;
119         }else {//否则设置这个点为最后的触摸点
120             self.lastPoint = touchPoint;
121         }
122     }
123     //重绘
124     [self setNeedsDisplay];
125 }
126
127 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
128     //拼接选中按钮的tag作为密码
129     NSMutableString *pwd = [NSMutableString string];
130     for (UIButton *btn in self.selectedBtns) {
131         [pwd appendFormat:@"%ld",btn.tag];
132     }
133     //如果代理实现了方法,通知代理对象
134     if ([self.delegate respondsToSelector:@selector(selectBtn:andSelectPwd:)]) {
135         [self.delegate selectBtn:self andSelectPwd:pwd];
136     }
137     //设置所有被选中的按钮为未选中状态
138     [self.selectedBtns makeObjectsPerformSelector:@selector(setSelected:) withObject:@NO];
139     //移除所有被选中的按钮
140     [self.selectedBtns removeAllObjects];
141     //重绘
142     [self setNeedsDisplay];
143 }
144 @end

最后的效果图:

时间: 01-04

UI进阶--Quartz2D和触摸事件的简单使用:手势解锁的相关文章

UI进阶--Quartz2D和触摸事件的简单使用:简易涂鸦板

需求:实现一个简易的涂鸦板应用,使用鼠标在涂鸦板内拖动即可进行涂鸦,点击保存按钮,可以把完成的涂鸦保存,点击回退按钮可以向后退回一步,点击清空可以让涂鸦板清空. 实现步骤: 1.布局storyboard,连线各按钮以及涂鸦板: 2.监听触摸事件,主要为touchesBegan:和touchesMoved:; 3.获取移动的路径并添加到 UIBezierPath 对象: 4.渲染: 示例文件结构: 具体实现代码: 1 // 2 // Scrawl.h 3 // 1-04-Scrawl 4 // 5

[iOS UI进阶 - 3.0] 触摸事件的基本处理

A.需要掌握和练习的 1.介绍事件类型2.通过按钮的事件处理引出view的事件处理3.响应者对象 --> UIResponder --> UIView4.view的拖拽* 实现触摸方法,打印查看* 介绍touches和UIEvent参数* 扩展:点哪去哪5.涂鸦6.手势解锁7.事件的产生和传递8.响应者链条 9.手势 B.概念 1.iOS有3种主要事件 触摸事件 加速计事件 远程控制事件 2.响应者对象 在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接收并处理事

[iOS UI进阶 - 3.1] 触摸事件的传递

A.事件的产生和传递 发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的事件队列中 UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常,先发送事件给应用程序的主窗口(keyWindow) 主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件,这也是整个事件处理过程的第一步 找到合适的视图控件后,就会调用视图控件的touches方法来作具体的事件处理touchesBegan-touchesMoved- touchedEnded-

iOS开发UI篇—实现一个简单的手势解锁应用(基本)

iOS开发UI篇—实现一个简单的手势解锁应用(基本) 一.实现效果 实现效果图: 二.手势解锁应用分析 1.监听手指在view上的移动,首先肯定需要自定义一个view,重写touch began,touch move等方法,当手指移动到圈上时,让其变亮.可以通过button按钮来实现. 2.界面搭建 背景图片(给控制器的view添加一个imageview,设置属性背景图片) 九个按钮(把九个按钮作为一个整体,使用一个大的view来管理这些小的view,这些小的view就是9个button.如果使

iOS开发UI篇—实现一个简单的手势解锁应用(完善)

iOS开发UI篇—实现一个简单的手势解锁应用(完善) 一.需要实现的效果 二.应用完善 1.绘制不处于按钮范围内的连线 2.解决bug(完善) bug1:如果在began方法中通知view绘图,那么会产生bug.因为,当前点没有清空,在手指移开之后要清空当前点.可以在绘制前进行判断,如果当前点是(0,0)那么就不划线.或者在began方法中不进行重绘. bug2:无限菊花.自定义view的背景色为默认的(黑色),只要重写了drawrect方法,view默认的背景颜色就是黑色的,因为上下文默认的颜

触摸事件,响应者链和手势

1.触摸事件 1 #import "ViewController.h" 2 @interface ViewController () 3 @property (strong,nonatomic) UILabel *simple; 4 @end 5 6 @implementation ViewController 7 8 - (void)viewDidLoad { 9 [super viewDidLoad]; 10 // Do any additional setup after loa

UI进阶--Quartz2D简单介绍

1.Quartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统的API是纯C语言的,API来自于Core Graphics框架,数据类型和函数基本都以CG作为前缀,如: CGContextRef CGPathRef CGContextStrokePath(ctx); …… 2.Quartz2D可以做的工作: 绘制图形 : 线条\三角形\矩形\圆\弧\扇形等; 绘制文字; 绘制\生成图片(图像); 读取\生成PDF; 截图\裁剪图片; 自定义UI控件; ...... 3.Quartz2D在i

IOS开发——UI进阶篇(十三)UITabBarController简单使用,qq主流框架

一.UITabBarController简单使用 // 程序加载完毕 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 创建窗口 self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; // 设置窗口的根控制器 UITabB

IOS开发——UI进阶篇(八)pickerView简单使用,通过storyboard加载控制器,注册界面,通过xib创建控制器,控制器的view创建,导航控制器的基本使用

一.pickerView简单使用 1.UIPickerViewDataSource 这两个方法必须实现 // 返回有多少列 - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView; // 返回第component有多少行 - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;