【iOS开发之旅】手势解锁

BOERLockView.h

//
//  BOERLockView.h
//  BoerScore
//
//  Created by ChenQianPing on 16/2/18.
//  Copyright © 2016年 boer. All rights reserved.
//

#import <UIKit/UIKit.h>

@class BOERLockView;
@protocol BOERLockViewDelegate <NSObject>

// 结束手势解锁代理事件
@optional
- (void) boerLockView:(BOERLockView *) boerLockView didFinishedWithPath:(NSString *) path;

@end

@interface BOERLockView : UIView

// 代理
@property(nonatomic, weak) IBOutlet id<BOERLockViewDelegate> delegate;

@end

BOERLockView.m

//
//  BOERLockView.m
//  BoerScore
//
//  Created by ChenQianPing on 16/2/18.
//  Copyright © 2016年 boer. All rights reserved.
//

#import "BOERLockView.h"
#import "BOERLockButton.h"

#define BUTTON_COUNT 9
#define BUTTON_COL_COUNT 3

@interface BOERLockView()

// 已选择按钮数组
@property(nonatomic, strong) NSMutableArray *selectedButtons;
// 触摸位置
@property(nonatomic, assign) CGPoint currentTouchLocation;

@end

@implementation BOERLockView

// 初始化数组
- (NSMutableArray *)selectedButtons {
    if (nil == _selectedButtons) {
        _selectedButtons = [NSMutableArray array];
    }
    return _selectedButtons;
}

#pragma mark - 初始化方法
// 使用文件初始化
- (id)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        [self initView];
    }
    return self;
}

// 使用代码初始化
- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self initView];
    }
    return self;
}

// 初始化view内的控件(按钮)
- (void) initView {
    // 设置透明背景
    self.backgroundColor = [[UIColor alloc] initWithRed:1 green:1 blue:1 alpha:0];

    for (int i=0; i<BUTTON_COUNT; i++) {
        BOERLockButton *button = [BOERLockButton buttonWithType:UIButtonTypeCustom];

        // 设置指标tag,用来记录轨迹
        button.tag = i;

        // 加入按钮到lock view
        [self addSubview:button];
    }
}

// 设置按钮位置尺寸
- (void)layoutSubviews {
    [super layoutSubviews];

    // 取出所有按钮
    for (int i=0; i<self.subviews.count; i++) {
        BOERLockButton *button = self.subviews[i];
        CGFloat buttonWidth = 74;
        CGFloat buttonHeight = 74;

        // 此按钮所在列号
        int col = i % BUTTON_COL_COUNT;
        // 此按钮所在行号
        int row = i / BUTTON_COL_COUNT;
        // 等分水平多余空间,计算出间隙
        CGFloat marginX = (self.frame.size.width - BUTTON_COL_COUNT * buttonWidth) / (BUTTON_COL_COUNT + 1);
        CGFloat marginY = marginX;

        // x坐标
        CGFloat buttonX = marginX + col * (buttonWidth + marginX);
        // y坐标
        CGFloat buttonY = marginY + row * (buttonHeight + marginY);

        button.frame = CGRectMake(buttonX, buttonY, buttonWidth, buttonHeight);
    }
}

#pragma mark - 触摸事件
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    [self touchesMoved:touches withEvent:event];

}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    CGPoint touchLocation = [touch locationInView:touch.view];

    // 检测哪个按钮被点中了
    for (BOERLockButton *button in self.subviews) {

        // 如果触碰到了此按钮
        if (CGRectContainsPoint(button.touchFrame, touchLocation)) {
            button.selected = YES;

            // 如果此按钮没有被触碰过才进行处理
            if (![self.selectedButtons containsObject:button]) {
                // 加入到数组
                [self.selectedButtons addObject:button];
            }
        }

        // 当前触摸位置
        self.currentTouchLocation = touchLocation;
    }

    // 重绘
    [self setNeedsDisplay];
}

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    // 轨迹序列
    NSMutableString *passPath = [NSMutableString string];

    // 合成轨迹序列
    for (BOERLockButton *button in self.selectedButtons) {
        // 清除选中状态
        button.selected = NO;

        // 添加到轨迹序列
        [passPath appendFormat:@"%ld", button.tag];
    }

//    NSLog(@"1 %@",passPath);

    // 调用代理方法
    if ([self.delegate respondsToSelector:@selector(boerLockView:didFinishedWithPath:)]) {
        [self.delegate boerLockView:self didFinishedWithPath:passPath];
//        NSLog(@"2 %@",passPath);
    }

    // 清除选中状态,发现这种方法在真机8.2系统中不能起作用
    [self.selectedButtons makeObjectsPerformSelector:@selector(setSelected:) withObject:@(NO)];

    // 清空数组
    [self.selectedButtons removeAllObjects];

    // 重绘
    [self setNeedsDisplay];
}

#pragma mark - 绘图方法
- (void)drawRect:(CGRect)rect {
    UIBezierPath *path = [UIBezierPath bezierPath];

    // 遍历已选择按钮数组
    for (int i=0; i<self.selectedButtons.count; i++) {
        BOERLockButton *button = self.selectedButtons[i];

        if (0 == i) {
            [path moveToPoint:button.center];
        } else {
            [path addLineToPoint:button.center];
        }
    }

    if (self.selectedButtons.count) {
        [path addLineToPoint:self.currentTouchLocation];
    }

    // 设置画笔
    [[UIColor redColor] set];
    [path setLineWidth:10];
    [path setLineCapStyle:kCGLineCapRound];
    [path setLineJoinStyle:kCGLineJoinBevel];

    [path stroke];
}

@end

BOERLockButton.h

//
//  BOERLockButton.h
//  BoerScore
//
//  Created by ChenQianPing on 16/2/18.
//  Copyright © 2016年 boer. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface BOERLockButton : UIButton

// 可触碰范围
@property(nonatomic, assign) CGRect touchFrame;

@end

BOERLockButton.m

//
//  BOERLockButton.m
//  BoerScore
//
//  Created by ChenQianPing on 16/2/18.
//  Copyright © 2016年 boer. All rights reserved.
//

#import "BOERLockButton.h"

@implementation BOERLockButton

// 使用文件创建会调用
- (id)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        [self initLockButton];
    }
    return self;
}

// 使用代码创建会调用
- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self initLockButton];
    }
    return self;
}

// 初始化
- (void) initLockButton {
    // 取消交互事件(点击)
    self.userInteractionEnabled = NO;

    // 设置普通状态图片
    [self setBackgroundImage:[UIImage imageNamed:@"gesture_node_normal"] forState:UIControlStateNormal];

    // 设置选中状态图片
    [self setBackgroundImage:[UIImage imageNamed:@"gesture_node_highlighted"] forState:UIControlStateSelected];
}

- (void)layoutSubviews {
    [super layoutSubviews];

    // 可触碰范围
    CGFloat touchWidth = 24;
    CGFloat touchHeight = 24;
    CGFloat touchX = self.center.x - touchWidth/2;
    CGFloat touchY = self.center.y - touchHeight/2;
    self.touchFrame = CGRectMake(touchX, touchY, 24, 24);
}

@end

ViewController.m

//
//  ViewController.m
//  BoerScore
//
//  Created by ChenQianPing on 16/2/18.
//  Copyright © 2016年 boer. All rights reserved.
//

#import "ViewController.h"
#import "BOERLockView.h"

@interface ViewController () <BOERLockViewDelegate>
//storyboard连线
@property (weak, nonatomic) IBOutlet BOERLockView *showView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // 设置背景
    self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"Home_refresh_bg"]];

    self.showView.delegate = self;

}

// 设置状态栏样式
- (UIStatusBarStyle)preferredStatusBarStyle {
    return UIStatusBarStyleLightContent;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)boerLockView:(BOERLockView *)boerLockView didFinishedWithPath:(NSString *)path
{
    NSLog(@"手势解锁的输出序列:%@", path);
}

@end
时间: 2024-08-08 22:01:34

【iOS开发之旅】手势解锁的相关文章

李洪强iOS开发之添加手势

李洪强iOS开发之添加手势 02 - 添加手势

iOS开发UI篇—手势识别器(敲击)

iOS开发UI篇—手势识别器(敲击) 一.监听触摸事件的做法 如果想监听一个view上面的触摸事件,之前的做法通常是:先自定义一个view,然后再实现view的touches方法,在方法内部实现具体处理代码 通过touches方法监听view触摸事件,有很明显的几个缺点 (1)必须得自定义view (2)由于是在view内部的touches方法中监听触摸事件,因此默认情况下,无法让其他外界对象监听view的触摸事件(需要通过代理) (3)不容易区分用户的具体手势行为 iOS 3.2之后,苹果推出

iOS开发UI篇—手势识别器(长按+轻扫)

iOS开发UI篇—手势识别器(长按+轻扫) 一.长按事件 1 // 2 // YYViewController.m 3 // 03-长按 4 // 5 // Created by apple on 14-6-19. 6 // Copyright (c) 2014年 itcase. All rights reserved. 7 // 8 9 #import "YYViewController.h" 10 11 @interface YYViewController () 12 @prop

IOS开发UI篇—手势识别器(拖拽+旋转+缩放)

IOS开发UI篇—手势识别器(拖拽+旋转+缩放) 一.拖拽 示例代码: 1 // 2 // YYViewController.m 3 // 06-拖拽事件 4 // 5 // Created by apple on 14-6-19. 6 // Copyright (c) 2014年 itcase. All rights reserved. 7 // 8 9 #import "YYViewController.h" 10 11 @interface YYViewController ()

大钟的ios开发之旅(2)————简单说说ios中ARC与非ARC模式下的property的变量修饰词

/******************************************************************************************** * author:[email protected]大钟 * E-mail:[email protected] *site:http://www.idealpwr.com/ *深圳市动力思维科技发展有限公司 * http://blog.csdn.net/conowen * 注:本文为原创,仅作为学习交流使用,转

iOS开发之旅之UIViewController解析

就iOS开发来说,UIViewController就最核心的类型之一.而iOS的整个UI开发的核心思想也是MVC的架构,从UIViewController的命名就可以看出它在MVC中所扮演的角色,那就是Controller啦. Controller作为整个UI视图的控制器,对于用户的输入做出逻辑处理,例如用户点击某个按钮应该执行什么操作等:View角色只负责显示视图,view的这部分就是我们在nib或者storyboard设计的UI了.Model也就是我们的数据模型,例如从Core data中加

大钟的ios开发之旅(4)————简单谈谈ios程序界面实现的三种方式(代码创建,xib和storyboard)

/******************************************************************************************** * author:[email protected]大钟 * E-mail:[email protected] *site:http://www.idealpwr.com/ *深圳市动力思维科技发展有限公司 * http://blog.csdn.net/conowen * 注:本文为原创,仅作为学习交流使用,转

iOS开发-高级UI-手势解锁

一.手势解锁分析1.搭建界面(一个整屏UIView和一个较小的View上)2.新建一个类NJLockView,将较小View的Class设置为NJLockView在NJLockView.m中 //当视图是通过代码创建出来的就会调用initWithFrame:方法- (id)initWithFrame:(CGRect)frame{ self = [super initWithFrame:frame]: if(self){ // Initialization cade [self setup]: }

iOS开发之旅之App的生命周期

在iOS App中,入口函数并不在根目录下,而是在"Supporting Files"目录的main.m文件的main函数中.这很容易理解,C/C++都是以main为入口. int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } 这个函数比较简单,只是调用了UI