手勢密碼。xcode
界面:spa
畫面主要代碼:code
buttonArray = [[NSMutableArray alloc]init]; for (int i = 0; i< 9; i++) { int row = (i/3); int col = (i%3); int distance = (view.frame.size.width/3); int size = ((distance)/1.5); int margin = (size/4); GesturePasswordButton * gesturePasswordButton = [[GesturePasswordButton alloc] initWithFrame:CGRectMake(col*distance+margin, row*distance, size, size) ]; gesturePasswordButton.tag = i; [view addSubview:gesturePasswordButton]; [buttonArray addObject:gesturePasswordButton]; } tentacleView = [[TentacleView alloc] initWithFrame:view.frame]; tentacleView.buttonArray = buttonArray; tentacleView.tentacleDelegate = self; [self.view addSubview:tentacleView];
就是畫面上九個button和手勢界面tentacleview。component
tentacleview.m的代碼:orm
#import "TentacleView.h" #import "GesturePasswordButton.h" @implementation TentacleView @synthesize buttonArray; @synthesize touchedArray; @synthesize touchesArray; @synthesize success; @synthesize drawed; @synthesize style; @synthesize tentacleDelegate; - (instancetype)initWithFrame:(CGRect)frame{ self = [super initWithFrame:frame]; if (self) { [self setBackgroundColor:[UIColor clearColor]]; touchesArray=[[NSMutableArray alloc] init]; touchedArray=[[NSMutableArray alloc] init]; success = false; drawed = false; style = 2; } return self; } -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ CGPoint touchPoint; UITouch *touch = touches.allObjects[0]; [touchesArray removeAllObjects]; [touchedArray removeAllObjects]; success = true; drawed = false; if(touch != nil){ touchPoint = [touch locationInView:self]; for (int i=0; i<buttonArray.count;i++) { GesturePasswordButton * buttonTemp = buttonArray[i]; buttonTemp.success = true; buttonTemp.selected = false; if ([buttonTemp contains:touchPoint]) { CGRect frameTemp = buttonTemp.frame; CGPoint point = CGPointMake(frameTemp.origin.x+frameTemp.size.width/2,frameTemp.origin.y+frameTemp.size.height/2); NSDictionary *model = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithFloat: point.x ],@"x",[ NSNumber numberWithFloat:point.y],@"y",nil]; [touchesArray addObject:model]; } [buttonTemp setNeedsDisplay]; } [self setNeedsDisplay]; } } -(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ CGPoint touchPoint; UITouch *touch = touches.allObjects[0]; if(touch != nil){ touchPoint = [touch locationInView:self]; for (int i=0; i<buttonArray.count;i++) { GesturePasswordButton *buttonTemp = buttonArray[i]; if ([buttonTemp contains:touchPoint]){ buttonTemp.selected = true; id wid = nil; for(id obj in touchedArray){ if ([[NSString stringWithFormat:@"num%d",i] isEqual:obj]) { wid = obj; } } if(wid){ lineEndPoint = touchPoint; [self setNeedsDisplay]; return; } [touchedArray addObject:[NSString stringWithFormat:@"num%d",i]]; [buttonTemp setNeedsDisplay]; CGRect frameTemp = buttonTemp.frame; CGPoint point = CGPointMake(frameTemp.origin.x+frameTemp.size.width/2, frameTemp.origin.y+frameTemp.size.height/2); NSDictionary *model = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithFloat: point.x ],@"x",[ NSNumber numberWithFloat:point.y],@"y",[ NSNumber numberWithFloat:i],@"num",nil]; [touchesArray addObject:model]; break; } } lineEndPoint = touchPoint; [self setNeedsDisplay]; } } -(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ NSString * resultString = @""; for(NSDictionary *p in touchesArray ){ if([p objectForKey:@"num"] == nil){ continue; } int num=[[p objectForKey:@"num"] intValue]; resultString = [resultString stringByAppendingString:[NSString stringWithFormat:@"%d",num]]; } drawed = true; if(style==1){ success = [self.tentacleDelegate verification:resultString]; }else{ success = [self.tentacleDelegate resetPassword:resultString]; } for (int i=0; i<touchesArray.count;i++ ){ if([touchesArray[i] objectForKey:@"num"] == nil){ continue; } int selection = [[touchesArray[i] objectForKey:@"num"] intValue]; GesturePasswordButton * buttonTemp = buttonArray[selection]; buttonTemp.success = success; [buttonTemp setNeedsDisplay]; } [self setNeedsDisplay]; } -(void)drawRect:(CGRect)rect{ if(touchesArray.count<=0){ return; } NSLog(@"drawRect==%@",touchesArray); for (int i =0; i<touchesArray.count; i++) { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetLineWidth(context, 3.0); CGContextSetLineCap(context, kCGLineCapSquare); if([touchesArray[i] objectForKey:@"num"] == nil){ [touchesArray removeObjectAtIndex:i]; //i = i-1; continue; } if (success) { NSLog(@"drawRect==success1"); CGContextSetRGBStrokeColor(context, 0.0, 0.0, 1.0, 0.3); //CGContextSetStrokeColorWithColor(context, color); } else { NSLog(@"drawRect==success0"); CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 0.3); } CGContextAddRect(context, rect); //CGContextBeginPath(context); //鏈接線裁剪,註釋掉,鏈接線連結圓心。 for (GesturePasswordButton *btn in buttonArray) { CGContextAddEllipseInRect(context, btn.frame); } CGContextEOClip(context); CGContextMoveToPoint(context,[[touchesArray[i] objectForKey:@"x"] floatValue],[[touchesArray[i] objectForKey:@"y"] floatValue]); if(i<touchesArray.count-1){ NSLog(@"drawRect==i<touchesArray.count-1"); CGContextAddLineToPoint(context, [[touchesArray[i+1] objectForKey:@"x"] floatValue], [[touchesArray[i+1] objectForKey:@"y"] floatValue]); } else{ if(success && drawed != true){ NSLog(@"drawRect==success && drawed != true"); CGContextAddLineToPoint(context,lineEndPoint.x,lineEndPoint.y); } } CGContextStrokePath(context); } } -(void)enterArgin{ [touchesArray removeAllObjects]; [touchedArray removeAllObjects]; for( int i=0; i<buttonArray.count;i++ ){ GesturePasswordButton * buttonTemp = buttonArray[i]; buttonTemp.success = true; buttonTemp.selected = false; [buttonTemp setNeedsDisplay]; } [self setNeedsDisplay]; } @end
九個button不是xcode中標準控件,看代碼:ip
#import <UIKit/UIKit.h> #import <QuartzCore/QuartzCore.h> #import "GesturePasswordButton.h" #define PI 3.14159265358979323846 @implementation GesturePasswordButton @synthesize selected; @synthesize success; - (instancetype)initWithFrame:(CGRect)frame{ self = [super initWithFrame:frame]; if (self) { selected = false; success = true; [self setBackgroundColor:[UIColor clearColor]]; } return self; } - (void)drawRect:(CGRect)rect{ CGContextRef context= UIGraphicsGetCurrentContext(); if(selected){ if(success){ CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); CGFloat components[] = {0.0,0.0,1.0,0.5};//顏色元素 CGColorRef color = CGColorCreate(colorspace, components);//這兩行建立顏色 CGContextSetStrokeColorWithColor(context, color); CGContextSetFillColorWithColor(context, color); }else{ CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); CGFloat components[] = {1.0,0.0,0.0,0.5};//顏色元素 CGColorRef color = CGColorCreate(colorspace, components);//這兩行建立顏色 CGContextSetStrokeColorWithColor(context, color); CGContextSetFillColorWithColor(context, color); } CGRect rectangle = CGRectMake(self.bounds.size.width/2-self.bounds.size.width/8+1, self.bounds.size.height/2-self.bounds.size.height/8, self.bounds.size.width/4, self.bounds.size.height/4); //CGContextAddEllipse(in: frame); CGContextAddEllipseInRect(context, rectangle); CGContextFillPath(context); }else{ //線條顏色 CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); CGFloat components[] = {1.0,1.0,1.0,1.0};//顏色元素 CGColorRef color = CGColorCreate(colorspace, components);//這兩行建立顏色 CGContextSetStrokeColorWithColor(context, color); } CGContextSetLineWidth(context, 2.0); CGRect frame = CGRectMake(2,2,self.bounds.size.width-3,self.bounds.size.height-3); CGContextAddEllipseInRect(context, frame); CGContextStrokePath(context); /*>>>>>>>> if(success){ //context.setFillColor(red: 30/225, green: 175/255, blue: 235/255, alpha: 0.3) CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); //CGFloat components[] = {30/225,175/255,235/255,1.0};//顏色元素 CGFloat components[] = {0.0,0.0,1.0,0.5};//顏色元素 CGColorRef color = CGColorCreate(colorspace, components);//這兩行建立顏色 CGContextSetFillColorWithColor(context, color); }else{ CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); //CGFloat components[] = {208/225,36/255,36/255,1.0};//顏色元素 CGFloat components[] = {1.0,0.0,0.0,0.5};//顏色元素 CGColorRef color = CGColorCreate(colorspace, components);//這兩行建立顏色 CGContextSetFillColorWithColor(context, color); //context.setFillColor(red: 208/225, green: 36/255, blue: 36/255, alpha: 0.3) } //context.addEllipse(in: frame) CGContextAddEllipseInRect(context, frame); if(selected){ CGContextFillPath(context); } *///<<<<<< } -(BOOL)contains:(CGPoint)touchPoint{ return CGRectContainsPoint(self.frame,touchPoint); } @end
核心的原理就在tentacleview.m和GesturePasswordButton.m裏。仔細看下就會明白。rem
我也是參考網友寫的。你們的原理都大同小異。string