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格式的但是是靜態的動不了
總結
- 上一篇: 杀戮空间2服务器协议,杀戮空间2 云服务
- 下一篇: URI跳转方式地图导航的代码实践