美文网首页
iOS手势解锁实现

iOS手势解锁实现

作者: 丹丹十个胆小鬼 | 来源:发表于2019-01-08 18:45 被阅读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];
    暂未找到因果关系!!!

    相关文章

      网友评论

          本文标题:iOS手势解锁实现

          本文链接:https://www.haomeiwen.com/subject/thvbrqtx.html