ios手势解锁
手势的解锁效果如下:
编写环境:Xcode 6
代码文件视图:
以九个按钮排列成九宫格形成手势解锁视图,自定义一个继承自UIButton得类来描述按钮(对按钮进行封装)
#import "CXCircleView.h"
@implementation CXCircleView
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self initialiseButton];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder]) {
[self initialiseButton];
}
return self;
}
/**
* 初始化按钮
*/
- (void)initialiseButton
{
// 取消用户交互
self.userInteractionEnabled = NO;
[self setBackgroundImage:[UIImage imageNamed:@"gesture_node_normal"] forState:UIControlStateNormal];
// 被选中状态下显示该图片,目的是手指滑动时按钮全部高亮
[self setBackgroundImage:[UIImage imageNamed:@"gesture_node_highlighted"] forState:UIControlStateSelected];
}
在storyboard里,为控制器的view上添加一个占满屏幕的UIImageView,设置背景图,再为九个按钮添加一个父控件View来排列按钮,父控件View的宽高大小设置为375(暂时不做屏幕适配,直接在肾6屏幕上显示),为该view自定义一个类,在该类里面实现手势解锁功能
#import "CXLocView.h"
#import "CXCircleView.h"
// 按钮总数
static const int CXButtonCount = 9;
// 九宫格列数
static const int CXColumns = 3;
@interface CXLocView ()
/**
* 被选中的按钮
*/
@property (nonatomic,strong) NSMutableArray *totalSelectedBtnArr;
/**
* 不在按钮范围上的当前点
*/
@property (nonatomic,assign) CGPoint currPoint;
@end
@implementation CXLocView
- (NSMutableArray *)totalSelectedBtnArr
{
if (_totalSelectedBtnArr == nil) {
_totalSelectedBtnArr = [NSMutableArray array];
}
return _totalSelectedBtnArr;
}
/**
* 初始化view
*/
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self initialiseView];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder]) {
[self initialiseView];
}
return self;
}
/**
* 初始化view,为view添加九宫格按钮
*/
- (void)initialiseView
{
for (int i = 0; i < CXButtonCount; i++) {
CXCircleView *btn = [CXCircleView buttonWithType:UIButtonTypeCustom];
btn.tag = i;
[self addSubview:btn];
}
}
/**
* 设置按钮的frame
*/
- (void)layoutSubviews
{
// 调用父类的方法
[super layoutSubviews];
for (int i = 0; i < CXButtonCount; i++) {
CGFloat btnW = 95.0;
CGFloat btnH = btnW;
// 按钮所在行号
int row = i / CXColumns;
// 按钮所在列号
int col = i % CXColumns;
// 按钮间距
CGFloat btnMarginX = (self.frame.size.width - (CXColumns * btnW)) / (CXColumns + 1);
CGFloat btnMarginY = btnMarginX;
CGFloat btnX = btnMarginX + (btnW + btnMarginX) * col;
CGFloat btnY = btnMarginY + (btnH + btnMarginY) * row;
[self.subviews[i] setFrame:CGRectMake(btnX, btnY, btnW, btnH)];
}
}
/**
* 获取当前触摸点
*/
- (CGPoint)pointWithTouches:(NSSet *)touches
{
UITouch *touch = [touches anyObject];
return [touch locationInView:touch.view];
}
/**
* 获取被触摸的按钮
*/
- (CXCircleView *)touchBtnWithPoint:(CGPoint)point
{
for (CXCircleView *btn in self.subviews) {
// 缩小按钮的有效范围
CGFloat wh = 60;
CGFloat btnX = btn.center.x - wh * 0.5;
CGFloat btnY = btn.center.y - wh * 0.5;
if(CGRectContainsPoint(CGRectMake(btnX, btnY, wh, wh), point))
{
return btn;
}
}
return nil;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 将当前点清零
self.currPoint = CGPointZero;
// 获得当前的点
CGPoint point = [self pointWithTouches:touches];
// 获得该点所在的范围的按钮
CXCircleView *btn = [self touchBtnWithPoint:point];
// 存在该按钮且未被选中
if (btn && btn.selected == NO) {
btn.selected = YES;
[self.totalSelectedBtnArr addObject:btn];
}
[self setNeedsDisplay];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint point = [self pointWithTouches:touches];
CXCircleView *btn = [self touchBtnWithPoint:point];
if (btn && btn.selected == NO) {
btn.selected = YES;
[self.totalSelectedBtnArr addObject:btn];
}
else
{
self.currPoint = point;
}
[self setNeedsDisplay];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
NSMutableString *pwd = [NSMutableString string];
for (CXCircleView *btn in self.totalSelectedBtnArr) {
[pwd appendFormat:@"%d",(int)btn.tag];
}
// 添加代理,将密码传递给控制器
if ([self.delegate respondsToSelector:@selector(CXLocView:DidFinishPassWord:)]) {
[self.delegate CXLocView:self DidFinishPassWord:pwd];
}
[self.subviews makeObjectsPerformSelector:@selector(setSelected:) withObject:@(NO)];
[self.totalSelectedBtnArr removeAllObjects];
// 重绘
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
// 如果没有被选按钮则返回
if(self.totalSelectedBtnArr.count == 0) return;
UIBezierPath *path = [UIBezierPath bezierPath];
for (int index = 0; index < self.totalSelectedBtnArr.count; index++) {
#warning CXCircleView *btn = self.subviews[index]; 错写成subviews
CXCircleView *btn = self.totalSelectedBtnArr[index];
if (0 == index) {
[path moveToPoint:btn.center];
}
else
{
[path addLineToPoint:btn.center];
}
}
// 画非按钮上的线
if (CGPointEqualToPoint(_currPoint, CGPointZero) == NO) {
[path addLineToPoint:_currPoint];
}
path.lineWidth = 8;
path.lineJoinStyle = kCGLineJoinRound;
path.lineCapStyle = kCGLineCapRound;
[[UIColor colorWithRed:32/255.0 green:210/255.0 blue:254/255.0 alpha:0.7] set];
[path stroke];
}
@end
#import <UIKit/UIKit.h>
@class CXLocView;
@protocol CXLocViewDelegate <NSObject>
@optional
- (void)CXLocView:(CXLocView *)view DidFinishPassWord:(NSString *)pwd;
@end
@interface CXLocView : UIView
#import <UIKit/UIKit.h>
@class CXLocView;
@protocol CXLocViewDelegate <NSObject>
@optional
- (void)CXLocView:(CXLocView *)view DidFinishPassWord:(NSString *)pwd;
@end
@interface CXLocView : UIView
@property (weak,nonatomic) IBOutlet id<CXLocViewDelegate> delegate;
@end
直接在storyboard里设置代理,如图
手势解锁完成!
需要源码的留下邮箱。
ps:有谁知道怎么在博客上上传gif,我上传了gif格式的但是是静态的动不了
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。