Main.storyboard
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="5053" systemVersion="13D65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" initialViewController="vXZ-lx-hvc"> <dependencies> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3733"/> </dependencies> <scenes> <!--View Controller--> <scene sceneID="ufC-wZ-h7g"> <objects> <viewController id="vXZ-lx-hvc" customClass="LWTViewController" sceneMemberID="viewController"> <view key="view" contentMode="scaleToFill" id="kh9-bI-dsS"> <rect key="frame" x="0.0" y="0.0" width="320" height="480"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <subviews> <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Home_refresh_bg" id="70g-Bh-a7j"> <rect key="frame" x="0.0" y="0.0" width="320" height="480"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> </imageView> <view contentMode="scaleToFill" id="SVk-1V-3b7" customClass="LWTLockView"> <rect key="frame" x="0.0" y="80" width="320" height="320"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/> <color key="tintColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/> <connections> <outlet property="delegate" destination="vXZ-lx-hvc" id="P3U-ve-9af"/> </connections> </view> </subviews> <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/> </view> </viewController> <placeholder placeholderIdentifier="IBFirstResponder" id="x5A-6p-PRh" sceneMemberID="firstResponder"/> </objects> </scene> </scenes> <resources> <image name="Home_refresh_bg" width="640" height="1008"/> </resources> <simulatedMetricsContainer key="defaultSimulatedMetrics"> <simulatedStatusBarMetrics key="statusBar"/> <simulatedOrientationMetrics key="orientation"/> <simulatedScreenMetrics key="destination"/> </simulatedMetricsContainer> </document>
LWTViewController.h
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#import <UIKit/UIKit.h> @interface LWTViewController : UIViewController @end
LWTViewController.m
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#import "LWTViewController.h" #import "LWTLockView.h" @interface LWTViewController ()<LWTLockViewDelegate> @end @implementation LWTViewController - (void)lockViewDidClick:(LWTLockView *)lockView andPwd:(NSString *)pwd { NSLog(@"LWTViewController %@",pwd); } @end
LWTLockView.h
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#import <UIKit/UIKit.h> @class LWTLockView; @protocol LWTLockViewDelegate <NSObject> - (void)lockViewDidClick:(LWTLockView *)lockView andPwd:(NSString *)pwd; @end @interface LWTLockView : UIView @property (nonatomic, strong) IBOutlet id<LWTLockViewDelegate> delegate; @end
LWTLockView.m
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
// // LWTLockView.m // 手势解锁 // // Created by apple on 14-6-12. // Copyright (c) 2014年 lwt. All rights reserved. // #import "LWTLockView.h" #define KTotalCols 3 #define KTotalBtn 9 @interface LWTLockView () /** * 保存选中的所有按钮 */ @property (nonatomic, strong) NSMutableArray *btns; /** * 定义属性,记录用户当前手指的位置(非按钮范围内) */ @property (nonatomic, assign) CGPoint currentPoint; @end @implementation LWTLockView - (NSMutableArray *)btns { if (!_btns) { _btns = [NSMutableArray array]; } return _btns; } // 当视图是通过代码创建出来的就会调用initWithFrame - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code [self setup]; } return self; } // 当视图从xib或storyboard中创建出来就会调用 - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { // Initialization code [self setup]; } return self; } /** * 创建9个按钮添加到自定view中 */ - (void) setup { for (int i = 0; i < KTotalBtn; i++) { // 创建按钮 UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; // 设置按钮的背景图片 [btn setImage:[UIImage imageNamed:@"gesture_node_normal"] forState:UIControlStateNormal]; [btn setBackgroundImage:[UIImage imageNamed:@"gesture_node_highlighted"] forState:UIControlStateSelected]; // 设置按钮的tag作为唯一标识 btn.tag = i + 1; // 添加按钮到View [self addSubview:btn]; // 禁止按钮的点击事件(因为我们需要监听触摸事件) btn.userInteractionEnabled = NO; } } - (void)layoutSubviews { // 设置按钮的frame [super layoutSubviews]; CGFloat btnW = 74; CGFloat btnH = 74; CGFloat margin = (self.frame.size.width - (KTotalCols * btnW)) / (KTotalCols + 1); for (int i = 0; i < self.subviews.count; i++) { CGFloat row = i / KTotalCols; // 行号 CGFloat col = i % KTotalCols; // 列号 CGFloat btnX = margin + col * (btnW + margin); CGFloat btnY = margin + row * (btnH + margin); UIButton *btn = self.subviews[i]; btn.frame = CGRectMake(btnX, btnY, btnW, btnH); } } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // 得到触摸点 CGPoint startPoint = [self getCurrentPointWithTouchPoint:touches]; // 判断触摸的位置是否在按钮的范围内 UIButton *btn = [self getSelectedBtnWithCurrentPoint:startPoint]; // 判断该按钮是否存在,存储按钮 if (btn) { // 设置选中状态 btn.selected = YES; // 将按钮保存到数组中 [self.btns addObject:btn]; } } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { // 得到触摸点 CGPoint movePoint = [self getCurrentPointWithTouchPoint:touches]; // 判断触摸的位置是否在按钮的范围内 UIButton *btn = [self getSelectedBtnWithCurrentPoint:movePoint]; // 记录当前手指移动的位置 self.currentPoint = movePoint; // 判断该按钮是否存在和是否已选中, 存储按钮 if (btn && btn.selected == NO) { // 设置选中状态 btn.selected = YES; // 将按钮保存到数组中 [self.btns addObject:btn]; } // 通知view绘制线段 [self setNeedsDisplay]; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { // 取出用户输入的密码 NSMutableString *result = [NSMutableString string]; for (UIButton *btn in self.btns) { [result appendFormat:@"%d", btn.tag]; } // 通知代理,告诉代理用户输入的密码 if ([self.delegate respondsToSelector:@selector(lockViewDidClick:andPwd:)]) { [self.delegate lockViewDidClick:self andPwd:result]; } // 清空按钮选中状态 [self.btns makeObjectsPerformSelector:@selector(setSelected:) withObject:@(NO)]; // 清空数组 [self.btns removeAllObjects]; // 清空currentPoint // self.currentPoint = CGPointZero; [self setNeedsDisplay]; } /** * 根据系统传入的UITouch集合获取当前触摸的点 * @return 当初触摸的点 */ - (CGPoint)getCurrentPointWithTouchPoint:(NSSet *)touches { UITouch *touch = [touches anyObject]; CGPoint point = [touch locationInView:touch.view]; return point; } /** * 根据触摸点获取触摸到的按钮 * @return 触摸的按钮 */ - (UIButton *)getSelectedBtnWithCurrentPoint:(CGPoint)point { // 判断触摸的位置是否在按钮的范围内 for (UIButton *btn in self.subviews) { if (CGRectContainsPoint(btn.frame, point)) { return btn; } } return nil; } - (void)drawRect:(CGRect)rect { // 判断是否已有选中按钮 if (self.btns.count) { // 获取图形上下文 CGContextRef ctx = UIGraphicsGetCurrentContext(); // 背景颜色是默认背景颜色的话需要 // 清空上下文 CGContextClearRect(ctx, rect); // 从数组中取出所有的按钮, 连接所有按钮的中点 for (int i = 0; i < self.btns.count; i++) { // 取出按钮 UIButton *btn = self.btns[i]; if (0 == i) { CGContextMoveToPoint(ctx, btn.center.x, btn.center.y); }else { CGContextAddLineToPoint(ctx, btn.center.x, btn.center.y); } } // 当所有的按钮的终点都连接号之后再连接手指当前的位置 CGContextAddLineToPoint(ctx, self.currentPoint.x , self.currentPoint.y); CGContextSetLineJoin(ctx, kCGLineJoinRound); CGContextSetLineWidth(ctx, 2); [[UIColor redColor] set]; CGContextStrokePath(ctx); } } @end