1、有图有真相
2、设计思路
2.1、以屏幕宽度为边长创建一个正方形View;
2.2、一个for循环创建9个按钮并自动布局;
2.3、监听该view的触摸事件,触摸区域落在某按钮区域则按钮发光
2.4、记录发光的按钮,输出按钮顺序(可以在for循环创建按钮时给按钮做tag标记,这样就有对应关系了,从而把按钮转换成字符串密码)
3、代码示例
SAScreenLockView.h
[Objective-C] 纯文本查看 复制代码 //
// SAScreenLockView.h
// SAScreenLock
//
// Created by 余西安 on 14/12/27.
// Copyright (c) 2014年 Sian. All rights reserved.
//
#import <UIKit/UIKit.h>
/***************代理协议***************/
@class SAScreenLockView;
@protocol SAScreenLockViewDelegate <NSObject>
- (void)screenLock:(SAScreenLockView *)screenLockView didFinishPaht:(NSNumber *)path;
@end
/***************圆圈控件***************/
@interface SACircle : UIButton
@end
/***************解锁视图***************/
@interface SAScreenLockView : UIView
@property (nonatomic, weak) id<SAScreenLockViewDelegate> delegate;
- (id)initWithDelegate:(id<SAScreenLockViewDelegate>)delegate;
@end SAScreenLockView.m
[Objective-C] 纯文本查看 复制代码 //
// SAScreenLockView.m
// SAScreenLock
//
// Created by 余西安 on 14/12/27.
// Copyright (c) 2014年 Sian. All rights reserved.
//
#import "SAScreenLockView.h"
/*********************圆圈控件*********************/
@implementation SACircle
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder]) {
[self setup];
}
return self;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
- (void)setup
{
self.userInteractionEnabled = NO;
UIImage *normal = [UIImage imageNamed:@"gesture_node_normal.png"];
UIImage *selected = [UIImage imageNamed:@"gesture_node_highlighted"];
[self setImage:normal forState:UIControlStateNormal];
[self setImage:selected forState:UIControlStateSelected];
}
@end
/*********************解锁视图*********************/
@interface SAScreenLockView ()
@property (nonatomic, strong) NSMutableArray *circles;
@property (nonatomic, assign) CGPoint position;
@end
@implementation SAScreenLockView
#pragma mark - 初始化方法
- (id)initWithDelegate:(id<SAScreenLockViewDelegate>)delegate
{
if (self = [super init]) {
self.delegate = delegate;
}
return self;
}
// xib创建时调用
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder]) {
[self setup];
}
return self;
}
// 代码创建时调用
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
// 初始化9个子控件
- (void)setup
{
self.backgroundColor = [UIColor clearColor];
CGFloat width = [[UIScreen mainScreen] bounds].size.width;
self.frame = (CGRect){CGPointZero, width, width};
for (int i = 0; i < 9; i++) {
SACircle *circle = [SACircle buttonWithType:UIButtonTypeCustom];
circle.tag = i + 1;
[self addSubview:circle];
}
}
// 被选中的子控件
- (NSMutableArray *)circles
{
if (_circles == nil){
_circles = [NSMutableArray array];
}
return _circles;
}
// 子控件位置调整
- (void)layoutSubviews
{
NSInteger columns = 3;
CGFloat width = self.frame.size.width;
CGFloat dimeter = 64.0f;
CGFloat margic = (width - dimeter * columns) / (columns + 1);
for (SACircle *circle in self.subviews) {
CGFloat x = (circle.tag - 1) % columns * (dimeter + margic) + margic;
CGFloat y = (circle.tag - 1) / columns * (dimeter + margic);
CGFloat w = dimeter;
CGFloat h = dimeter;
circle.frame = (CGRect){x, y, w, h};
}
CGRect rect = self.frame;
rect.size.height = dimeter * 3 + margic * 2;
self.frame = rect;
}
#pragma mark - 触摸交互事件处理
- (CGPoint)pointWithTouch:(NSSet *)touches
{
UITouch *touch = [touches anyObject];
return [touch locationInView:self];
}
- (SACircle *)circleWithTouches:(NSSet *)touches
{
CGPoint pos = [self pointWithTouch:touches];
// 判断当前触摸位置是否进入9个圆圈内
for (SACircle *circle in self.subviews) {
CGRect touchArea = circle.frame;
CGFloat w = touchArea.size.width;
touchArea.origin.x += w / 4;
touchArea.origin.y += w / 4;
touchArea.size.width -= w / 2;
touchArea.size.height -= w / 2;
if (CGRectContainsPoint(touchArea, pos)){
return circle;
}
}
return nil;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
self.position = CGPointZero;
SACircle *circle = [self circleWithTouches:touches];
// 如果进入圆圈内并且当前圆圈未被选中则加入到选中数组
if (circle && !circle.selected){
circle.selected = YES;
[self.circles addObject:circle];
}
[self setNeedsDisplay];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
self.position = [self pointWithTouch:touches];
SACircle *circle = [self circleWithTouches:touches];
// 如果进入圆圈内并且当前圆圈未被选中则加入到选中数组
if (circle && !circle.selected){
circle.selected = YES;
[self.circles addObject:circle];
}
[self setNeedsDisplay];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
NSMutableString *path = [NSMutableString string];
for (SACircle *circle in self.circles) {
circle.selected = NO;
[path appendFormat:@"%d", (int)circle.tag];
}
// 当选中的圆圈不为空,并且代理有实现代理方法时通知代理
if ([self.delegate respondsToSelector:@selector(screenLock:didFinishPaht:)] && self.circles.count)
[self.delegate screenLock:self didFinishPaht:@([path longLongValue])];
[self.circles removeAllObjects];
[self setNeedsDisplay];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[self touchesEnded:touches withEvent:event];
}
#pragma mark - 视图绘制方法
- (void)drawRect:(CGRect)rect
{
if (self.circles.count == 0) return;
UIBezierPath *path = [UIBezierPath bezierPath];
path.lineWidth = 8;
path.lineCapStyle = kCGLineCapRound;
path.lineJoinStyle = kCGLineJoinRound;
for (int i = 0; i < self.circles.count; i++) {
SACircle *circle = self.circles[i];
if (i == 0) {
[path moveToPoint:circle.center];
} else {
[path addLineToPoint:circle.center];
}
}
if (!CGPointEqualToPoint(self.position, CGPointZero))
[path addLineToPoint:self.position];
[[UIColor colorWithRed:122/255.0 green:214/255.0 blue:250/255.0 alpha:0.7] set];
[path stroke];
}
@end
4、Demo下载:
|