zoukankan      html  css  js  c++  java
  • iOS 九宫格解锁

    思路:

    1.画9个按钮,通过按钮的选中状态控制按钮.

    2.连线通过贝塞尔曲线绘制.

    3.校验密码通过给按钮绑定tag值判断.

    主要代码:

    OC版本:

      1 //
      2 //  NineLockView.m
      3 //  lockView
      4 //
      5 //  Created by Shaoting Zhou on 2018/1/24.
      6 //  Copyright © 2018年 Shaoting Zhou. All rights reserved.
      7 //
      8 
      9 #import "NineLockView.h"
     10 
     11 CGFloat const btnCount = 9; //九宫格个数
     12 CGFloat const btnW = 74;    //单个按钮宽
     13 CGFloat const btnH = 74;    //单个按钮高
     14 CGFloat const viewY = 300;  //视图Y
     15 int const columnCount = 3;   //列数
     16 #define kScreenWidth [UIScreen mainScreen].bounds.size.width
     17 
     18 @interface NineLockView ()
     19 @property (nonatomic, strong) NSMutableArray * selectBtnsAry; //选中按钮的数组
     20 @property (nonatomic, assign) CGPoint currentPoint;    //当前的点 坐标 用于判断最后一个点
     21 @end
     22 
     23 
     24 @implementation NineLockView
     25 
     26 -(NSMutableArray *)selectBtnsAry{
     27     if(!_selectBtnsAry){
     28         _selectBtnsAry = [NSMutableArray array];
     29     }
     30     return _selectBtnsAry;
     31 }
     32 
     33 //通过代码布局时会调用这个方法
     34 -(instancetype)initWithFrame:(CGRect)frame{
     35     if(self = [super initWithFrame:frame]){
     36         self.backgroundColor = [UIColor clearColor];
     37         [self addButton];
     38     }
     39     return self;
     40 }
     41 
     42 //通过sb xib布局时会调用这个方法
     43 -(instancetype)initWithCoder:(NSCoder *)aDecoder{
     44     if(self = [super initWithCoder:aDecoder]){
     45         [self addButton];
     46     }
     47     return self;
     48 }
     49 
     50 #pragma Mark - 布局按钮
     51 - (void)addButton{
     52     CGFloat height = 0;;
     53     for (int i = 0; i < btnCount; i++) {
     54         UIButton * btn = [UIButton buttonWithType:(UIButtonTypeCustom)];
     55         btn.tag = i;
     56         btn.userInteractionEnabled = NO; //不可交互
     57         //设置默认的图片
     58         [btn setBackgroundImage:[UIImage imageNamed:@"gesture_normal"] forState:(UIControlStateNormal)];
     59         //设置选中的图片
     60         [btn setBackgroundImage:[UIImage imageNamed:@"gesture_selected"] forState:(UIControlStateSelected)];
     61         int row = i / columnCount;  //第几行
     62         int column = i % columnCount;   //第几列
     63         CGFloat margin = (self.frame.size.width - columnCount * btnW) / (columnCount + 1); //边距
     64         CGFloat btnX = margin + column * (btnW + margin);   //x轴
     65         CGFloat btnY = row * (btnW + margin);       //y轴
     66 //        btn.backgroundColor =[UIColor redColor];
     67         btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
     68         height = btnH + btnY;   //视图高等于 最后一个点的高+y
     69         [self addSubview:btn];
     70     }
     71     self.frame = CGRectMake(0, viewY, kScreenWidth, height);   //视图frame
     72 }
     73 
     74 
     75 - (CGPoint)pointWithTouch:(NSSet *)touches{
     76     UITouch * touch = [touches anyObject];
     77     CGPoint point = [touch locationInView:self];
     78     return point;
     79 }
     80 - (UIButton *)buttonWithPoint:(CGPoint)point{
     81     for (UIButton * btn in self.subviews) {
     82         if(CGRectContainsPoint(btn.frame, point)){
     83             return btn;
     84         }
     85     }
     86     return nil;
     87 }
     88 
     89 
     90 #pragma Mark - 开始移动
     91 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
     92     //1.拿到触摸的点
     93     CGPoint point = [self pointWithTouch:touches];
     94     //2.根据触摸的点拿到相应的按钮
     95     UIButton * btn = [self buttonWithPoint:point];
     96     //3.设置状态
     97     if(btn && btn.selected == NO){
     98         btn.selected = YES;
     99         [self.selectBtnsAry addObject:btn];
    100     }
    101     
    102     
    103 }
    104 
    105 #pragma Mark  - 移动中
    106 - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    107     //1.拿到触摸的点
    108     CGPoint point = [self pointWithTouch:touches];
    109     //2.根据触摸的点拿到相应的按钮
    110     UIButton * btn = [self buttonWithPoint:point];
    111     //3.设置状态
    112     if(btn && btn.selected == NO){
    113         btn.selected = YES;
    114         [self.selectBtnsAry addObject:btn];
    115     }else{
    116         self.currentPoint = point;
    117     }
    118     [self setNeedsDisplay];
    119 }
    120 
    121 #pragma Mark - 结束移动
    122 - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    123     if([self.delegete respondsToSelector:@selector(lockView:didFinishPath:)]){
    124         NSMutableString * path = [NSMutableString string];
    125         for (UIButton * btn in self.selectBtnsAry) {
    126             [path appendFormat:@"%ld",(long)btn.tag];
    127         }
    128         [self.delegete lockView:self didFinishPath:path];
    129     }
    130     //清空状态
    131     for(int i = 0; i < self.selectBtnsAry.count; i++ ){
    132         UIButton * button = self.selectBtnsAry[i];
    133         button.selected = NO;
    134     }
    135     [self.selectBtnsAry removeAllObjects];
    136     [self setNeedsDisplay];
    137 }
    138 
    139 #pragma  Mark - 取消移动
    140 - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    141     [self touchesEnded:touches withEvent:event];
    142 }
    143 
    144 #pragma Mark - 绘图
    145 - (void)drawRect:(CGRect)rect{
    146     if(self.selectBtnsAry.count  == 0){
    147         return;
    148     }
    149     UIBezierPath * path = [UIBezierPath bezierPath];
    150     path.lineWidth = 8;
    151     path.lineJoinStyle = kCGLineJoinRound;
    152     [[UIColor colorWithRed:32/255.0 green:210/255.0 blue:254/255.0 alpha:0.5] set];
    153     //遍历按钮
    154     for(int i = 0; i < self.selectBtnsAry.count; i++ ){
    155         UIButton * button = self.selectBtnsAry[i];
    156         NSLog(@"%d",i);
    157         if(i == 0){
    158             //设置起点
    159             [path moveToPoint:button.center];
    160         }else{
    161             //连线
    162             [path addLineToPoint:button.center];
    163         }
    164 
    165     }
    166     [path addLineToPoint:self.currentPoint]; //最后一点 连接自己
    167     [path stroke];
    168 
    169 }
    170 
    171 
    172 
    173 
    174 @end
    OC版本
     1 //
     2 //  ViewController.m
     3 //  lockView
     4 //
     5 //  Created by Shaoting Zhou on 2018/1/24.
     6 //  Copyright © 2018年 Shaoting Zhou. All rights reserved.
     7 //
     8 
     9 #import "ViewController.h"
    10 #import "NineLockView.h"
    11 
    12 #define kScreenWidth [UIScreen mainScreen].bounds.size.width
    13 #define kScreenHeight [UIScreen mainScreen].bounds.size.height
    14 
    15 @interface ViewController () <NineLockViewDelegate>
    16 
    17 @end
    18 
    19 @implementation ViewController
    20 
    21 - (void)viewDidLoad {
    22     [super viewDidLoad];
    23     self.view.backgroundColor = [UIColor brownColor];
    24     NineLockView * lockView = [[NineLockView alloc]initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight)];
    25     lockView.delegete = self;
    26     [self.view addSubview:lockView];
    27 }
    28 
    29 -(void)lockView:(NineLockView *)lockView didFinishPath:(NSString *)path{
    30     if(path.length <= 3){
    31         NSLog(@"请至少连4个点");
    32         return;
    33     }
    34     if([path isEqualToString:@"01258"]){
    35         NSLog(@"OK");
    36     }else{
    37         NSLog(@"error");
    38     }
    39 }
    40 
    41 - (void)didReceiveMemoryWarning {
    42     [super didReceiveMemoryWarning];
    43     // Dispose of any resources that can be recreated.
    44 }
    45 
    46 
    47 @end
    OC版本

    swift版本:

     1 //
     2 //  ViewController.swift
     3 //  lockView-Swift
     4 //
     5 //  Created by Shaoting Zhou on 2018/1/25.
     6 //  Copyright © 2018年 Shaoting Zhou. All rights reserved.
     7 //
     8 
     9 import UIKit
    10 
    11 class ViewController: UIViewController,nineLockViewDelegate  {
    12     
    13     
    14     let kScreenHeight = UIScreen.main.bounds.size.height
    15     let kScreenWidth = UIScreen.main.bounds.size.width
    16     override func viewDidLoad() {
    17         super.viewDidLoad()
    18         self.view.backgroundColor = UIColor.brown
    19         let nineLockView = NineLockView.init(frame: CGRect.init(x: 0, y: 0,  kScreenWidth, height: kScreenHeight))
    20         nineLockView.delegate = self
    21         self.view.addSubview(nineLockView)
    22         
    23         // Do any additional setup after loading the view, typically from a nib.
    24     }
    25     //MARK: - 代理方法
    26     func lockView(lockView: NineLockView, path: String) {
    27         if(path.description.count < 4){
    28             print("至少连4个");
    29             return;
    30         }
    31         if(path == "01258"){
    32             print("密码正确");
    33         }else{
    34             print("密码错误");
    35         }
    36     }
    37     
    38     
    39     override func didReceiveMemoryWarning() {
    40         super.didReceiveMemoryWarning()
    41         // Dispose of any resources that can be recreated.
    42     }
    43     
    44     
    45 }
    Swift版本
      1 //
      2 //  NineLockView.swift
      3 //  lockView-Swift
      4 //
      5 //  Created by Shaoting Zhou on 2018/1/25.
      6 //  Copyright © 2018年 Shaoting Zhou. All rights reserved.
      7 //
      8 
      9 import UIKit
     10 
     11 let btnCount = 9; //九宫格个数
     12 let btnW:CGFloat = 74.0;    //单个按钮宽
     13 let btnH:CGFloat = 74.0;    //单个按钮高
     14 let viewY:CGFloat = 300.0;  //视图Y
     15 let columnCount = 3;   //列数
     16 let kScreenHeight = UIScreen.main.bounds.size.height
     17 let kScreenWidth = UIScreen.main.bounds.size.width
     18 
     19 //创建协议
     20 protocol nineLockViewDelegate:NSObjectProtocol
     21 {
     22     func lockView(lockView:NineLockView,path:String)
     23 }
     24 
     25 class NineLockView: UIView {
     26     weak var delegate:nineLockViewDelegate?
     27     var selectBtnsAry = [UIButton] ()
     28     var currentPoint:CGPoint!
     29     
     30     override init(frame: CGRect) {
     31         super.init(frame: frame)
     32         self.backgroundColor = UIColor.clear
     33         self .addButton();
     34     }
     35     
     36     // MARK: 添加按钮
     37     func addButton(){
     38         var height:CGFloat = 0.0
     39         for var i in 0 ..< btnCount{
     40             let btn = UIButton.init(type: .custom)
     41             btn.setImage(#imageLiteral(resourceName: "gesture_normal"), for: .normal)  //默认图片
     42             btn.setImage(#imageLiteral(resourceName: "gesture_selected"), for: .selected)  //选中图片
     43             btn.tag = i
     44             btn.isUserInteractionEnabled = false  //取消用户交互
     45             let row = i / columnCount  //行数
     46             let column = i % columnCount //列数
     47             let margin:CGFloat = (self.frame.size.width - CGFloat(columnCount) * btnW) / CGFloat( (columnCount + 1)); //边距
     48             let btnX:CGFloat = margin + CGFloat(column) * (btnW + margin);   //x轴
     49             let btnY:CGFloat = CGFloat(row) * (btnW + margin);       //y轴
     50             btn.frame = CGRect.init(x: btnX, y: btnY,  btnW, height: btnH)
     51             height = btnY + btnH   //视图的高 = 最后一个按钮的高 + y
     52             self.addSubview(btn)
     53         }
     54         self.frame = CGRect.init(x: 0, y: viewY,  kScreenWidth, height: height)
     55     }
     56     
     57     func pointWithTouch(touches:Set<UITouch>) -> CGPoint{
     58         let touch:UITouch = (touches as NSSet).anyObject() as! UITouch
     59         let point = touch.location(in: self)
     60         return point;
     61     }
     62     func buttonWithPoint(point:CGPoint) -> UIButton?{
     63         for var view:UIView in self.subviews {
     64             let btn:UIButton =  view as! UIButton
     65             if(btn.frame.contains(point)){
     66                 return btn
     67             }
     68         }
     69         return nil
     70     }
     71     
     72     
     73     // MARK:  开始移动
     74     override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
     75         //1.拿到触摸的点
     76         let point:CGPoint = self.pointWithTouch(touches: touches)
     77         //2.根据触摸的点拿到相应的按钮
     78         guard let btn:UIButton = self.buttonWithPoint(point: point) else{
     79             return;
     80         }
     81         //3.设置状态
     82         if(btn.isSelected == false){
     83             btn.isSelected  = true
     84             self.selectBtnsAry.append(btn)
     85         }
     86         
     87     }
     88     
     89     // MARK:  移动中
     90     override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
     91         //1.拿到触摸的点
     92         let point:CGPoint = self.pointWithTouch(touches: touches)
     93         //2.根据触摸的点拿到相应的按钮
     94         guard let btn:UIButton = self.buttonWithPoint(point: point) else{
     95             return;
     96         }
     97         //3.设置状态
     98         if(btn.isSelected == false){
     99             btn.isSelected  = true
    100             self.selectBtnsAry.append(btn)
    101         }else{
    102             self.currentPoint = point;
    103         }
    104         self.setNeedsDisplay()
    105 
    106     }
    107     // MARK:  移动停止
    108     override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    109         if delegate != nil{
    110             var str = "";
    111             for var i in 0 ..< self.selectBtnsAry.count{
    112                 let btn:UIButton = self.selectBtnsAry[i]
    113                 str = str  + String(btn.tag)
    114             }
    115             self.delegate?.lockView(lockView: self, path: str)
    116         }
    117         
    118         for var i in 0 ..< self.selectBtnsAry.count{
    119             let btn:UIButton = self.selectBtnsAry[i]
    120             btn.isSelected = false
    121         }
    122         self.selectBtnsAry.removeAll()
    123         self.setNeedsDisplay()
    124     }
    125     
    126     // MARK:  移动取消
    127     override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
    128         self.touchesEnded(touches, with: event)
    129     }
    130     
    131     // MARK:  绘图
    132     override func draw(_ rect: CGRect) {
    133         if(self.selectBtnsAry.count == 0){
    134             return;
    135         }
    136         let  path:UIBezierPath = UIBezierPath.init()
    137         path.lineWidth = 8
    138         path.lineJoinStyle = .round
    139         UIColor.init(red: 32/255.0, green: 210/255.0, blue: 254/255.0, alpha: 0.5).set()
    140         //遍历按钮
    141         for var i in 0 ..< self.selectBtnsAry.count{
    142             let btn:UIButton = self.selectBtnsAry[i]
    143             if(i == 0){
    144                 //起点
    145                 path.move(to: btn.center)
    146             }else{
    147                 //划线
    148                 path.addLine(to: btn.center)
    149             }
    150         }
    151         path.addLine(to: self.currentPoint) //最后一点 连接自己
    152         path.stroke()
    153     }
    154     
    155     
    156     required init?(coder aDecoder: NSCoder) {
    157         fatalError("init(coder:) has not been implemented")
    158     }
    159     
    160 }
    Swift版本

    基本演示:

    这里的只演示下基本九宫格校验密码(密码已经存在:01258).

    创建密码,修改密码思路类似.

    github: https://github.com/pheromone/iOS-nineLock

  • 相关阅读:
    java.util.concurrent.atomic 包详解
    SpringBoot RESTful 应用中的异常处理小结
    Spring 核心框架体系结构
    Java 的静态代理 动态代理(JDK和cglib)
    Spring5:@Autowired注解、@Resource注解和@Service注解
    offsetWidth/offsetHeight,clientWidth/clientHeight与scrollWidth/scrollHeight的区别
    一个小技能
    在chrome console添加jQuery支持
    如和判断两个浮点数是否相等
    Object.create() vs new SomeFunction() in javascript
  • 原文地址:https://www.cnblogs.com/shaoting/p/8353687.html
Copyright © 2011-2022 走看看