思路:git
1.畫9個按鈕,經過按鈕的選中狀態控制按鈕.github
2.連線經過貝塞爾曲線繪製.swift
3.校驗密碼經過給按鈕綁定tag值判斷.數組
主要代碼:app
OC版本:ide
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
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
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, width: 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 }
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, width: btnW, height: btnH) 51 height = btnY + btnH //視圖的高 = 最後一個按鈕的高 + y 52 self.addSubview(btn) 53 } 54 self.frame = CGRect.init(x: 0, y: viewY, width: 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 }
基本演示:ui
這裏的只演示下基本九宮格校驗密碼(密碼已經存在:01258).atom
建立密碼,修改密碼思路相似.spa