• 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

    最后的效果图:

  • 相关阅读:
    C语言基础:C语言结构体(2)
    C语言基础:C语言结构体(1)
    C语言基础:C语言变量类型
    开源魔兽服务端代码托管地址大全
    新浪微博_第三期整理
    UITextField特性整理
    Xcode快捷键整理
    sleep和wait区别
    IOS7新特性-AVSpeechSynthesisVoice
    【OBJC类扩展之MD5加密】NSString+MD5
  • 原文地址:https://www.cnblogs.com/xiaomoge/p/4202240.html
Copyright © 2020-2023  润新知