iOS手势解锁实现

2019-01-08  本文已影响0人  丹丹十个胆小鬼

1、界面分析

当手指在界面移动时,移动到一个按钮范围内当中,它会把按钮给成为选中的状态,并且把第一个选中的按钮当做一个线的起点,当手指移动到另一个按钮上时,就会添加一根线到选中的那妞上,当手指松开时,所有按钮取消选中,所有的线都清空。

2、实现思路

3、实现代码

FLLockView.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@class FLLockView;
@protocol FLLockViewDelegate <NSObject>

@optional
- (void)lockView:(FLLockView *)lockView unlockPsw:(NSString *)unlockStr;

@end

@interface FLLockView : UIView
/** delegate*/
@property (weak, nonatomic) id<FLLockViewDelegate> delegate;

/**
 创建一个lockView

 @param frame lockView的frame
 @param normalImg 按钮normal状态下图片
 @param selectedImg 按钮选中状态下图片
 @return 返回lockView
 */
+(instancetype)lockViewWithFrame:(CGRect)frame btnNormalImage:(NSString *)normalImg btnSelectedImage:(NSString *)selectedImg;
/**
 创建一个lockView
 
 @param frame lockView的frame
 @param normalImg 按钮normal状态下图片
 @param selectedImg 按钮选中状态下图片
 @return 返回lockView
 */
-(instancetype)initWithFrame:(CGRect)frame btnNormalImage:(NSString *)normalImg btnSelectedImage:(NSString *)selectedImg;
@end

NS_ASSUME_NONNULL_END

FLLockView.m

#import "FLLockView.h"

@interface FLLockView ()
/** 存放手指划过的btn*/
@property (strong, nonatomic) NSMutableArray *selectedBtnArray;

/** 手指滑动的当前点*/
@property (assign, nonatomic) CGPoint currP;
@end

@implementation FLLockView

- (NSMutableArray *)selectedBtnArray {
    if (_selectedBtnArray == nil) {
        _selectedBtnArray = [NSMutableArray array];
    }
    return _selectedBtnArray;
}

+(instancetype)lockViewWithFrame:(CGRect)frame btnNormalImage:(NSString *)normalImg btnSelectedImage:(NSString *)selectedImg {
    FLLockView *lockView = [[self alloc] initWithFrame:frame btnNormalImage:normalImg btnSelectedImage:selectedImg];
    return lockView;
}

- (instancetype)initWithFrame:(CGRect)frame btnNormalImage:(NSString *)normalImg btnSelectedImage:(NSString *)selectedImg {
    if (self = [super initWithFrame:frame]) {
        [self setupSubViewsWithBtnNormalImage:normalImg btnSelectedImage:selectedImg];
    }
    
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self setupSubViewsWithBtnNormalImage:@"gesture_node_normal" btnSelectedImage:@"gesture_node_highlighted"];
    }
    return self;
}

- (void)awakeFromNib {
    [super awakeFromNib];
    [self setupSubViewsWithBtnNormalImage:@"gesture_node_normal" btnSelectedImage:@"gesture_node_highlighted"];
}

- (void)setupSubViewsWithBtnNormalImage:(NSString *)normalImg btnSelectedImage:(NSString *)selectedImg  {
    // 代码创建LockView时,不设置该背景颜色,会出现画线错乱的情况
    self.backgroundColor = [UIColor clearColor];
    for (int i = 0; i < 9; i++) {
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        btn.userInteractionEnabled = NO;
        [btn setImage:[UIImage imageNamed:normalImg] forState:UIControlStateNormal];
        [btn setImage:[UIImage imageNamed:selectedImg] forState:UIControlStateSelected];
        btn.tag = i;
        [self addSubview:btn];
    }
}

- (void)layoutSubviews {
    [super layoutSubviews];
    CGFloat btnX = 0;
    CGFloat btnY = 0;
    CGFloat btnWH = 74;
    CGFloat SpaceW = (self.frame.size.width - 3 * btnWH) / 4;
    int btnR = 0; // btn所在的行
    int btnC = 0; // btn所在的列
    // 确定btn九宫格排列
    for (int i = 0; i < self.subviews.count; i++) {
        btnR = i / 3;
        btnC = i % 3;
        btnX = SpaceW * (btnC+1) + btnC*btnWH;
        btnY = SpaceW * (btnR+1) + btnR*btnWH;
        UIButton *btn = self.subviews[i];
        btn.frame = CGRectMake(btnX, btnY, btnWH, btnWH);
    }
}

/**
 获取当前点所在的btn

 @param currP 当前点坐标
 @return 点所在的btn,如果点不在btn上,返回nil
 */
- (UIButton *)getBtnWithPoint:(CGPoint)currP {
    for (UIButton *btn in self.subviews) {
        //判断一个点在不在指定的区域当中
        if (CGRectContainsPoint(btn.frame, currP)) {
            
            return btn;
        }
    }
    
    return nil;
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    self.currP = [touch locationInView:self];
    
    UIButton *btn = [self getBtnWithPoint:self.currP];
    if (btn && btn.selected == NO) {
        btn.selected = YES;
        [self.selectedBtnArray addObject:btn];
    }
}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    self.currP = [touch locationInView:self];
    
   
    UIButton *btn = [self getBtnWithPoint:self.currP];
    if (btn && btn.selected == NO) {
        btn.selected = YES;
        if (![self.selectedBtnArray containsObject:btn]) {
            [self.selectedBtnArray addObject:btn];
        }
    }
    
    [self setNeedsDisplay];
}

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    NSMutableString *selectStr = [NSMutableString string];
    for (int i = 0; i < self.selectedBtnArray.count; i++) {
        UIButton *btn = self.selectedBtnArray[i];
        
        [selectStr appendFormat:@"%ld",(long)btn.tag];
        btn.selected = NO;
    }
    
    if ([self.delegate respondsToSelector:@selector(lockView:unlockPsw:)]) {
        [self.delegate lockView:self unlockPsw:selectStr];
    }
//    NSLog(@"解锁密码:%@", selectStr);

    // 删除选中的btn
    [self.selectedBtnArray removeAllObjects];
    [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect {
    if (self.selectedBtnArray.count) {
        UIBezierPath *path = [UIBezierPath bezierPath];
        for (int i = 0; i < self.selectedBtnArray.count; i++) {
            UIButton *tempBtn = self.selectedBtnArray[i];
            if (i==0) {
                [path moveToPoint:tempBtn.center];
            } else {
                [path addLineToPoint:tempBtn.center];
            }
        }
        [path addLineToPoint:self.currP];
        path.lineWidth = 10;
        path.lineJoinStyle = kCGLineJoinRound;
        path.lineCapStyle = kCGLineCapRound;
        [[UIColor redColor] set];
        
        [path stroke];
    }
}

@end

疑问:使用纯代码创建lockView时,出现了画线错乱的情况,最后设置了背景颜色才正常,
// 代码创建LockView时,不设置该背景颜色,会出现画线错乱的情况
self.backgroundColor = [UIColor clearColor];
暂未找到因果关系!!!

上一篇下一篇

猜你喜欢

热点阅读