IOS-------製作手機圖案解鎖
一、要先進行頁面佈局 1、在View Controller裡面新增操作圖片
-(void)initUI{ //建立操作圖片 UIImageView *opImageView = [[UIImageView alloc]initWithframe:CGRectMake:((self.view.frame.size.width-320)/2,100,320,460)]; opImageView.image = [UIImage imageNamed:@"1.png"]; [self.view addSubview:opImageView]; }
新增initUI方法到ViewDidLoad裡面
[self initUI];
2、新增點和線 到這裡我們會發現我們要新增很多大量的圖片,因此我們可以新增一個方法,以此來簡化我們的程式碼
//建立一個UIImageView -(void)createImageViewWithFrame:(CGRect)frame name:(NSString *)imageName{ UIImageView *imageView = [[UIImageView alloc]initWithframe:frame]; imageView.image = [UIImage imageNamed:imageName]; [self.view addSubview:imageView]; return imageView; }
因此,第1步新增操作圖片可以改為:
[self createImageViewWithFrame:CGRectMake:((self.view.frame.size.width-320)/2,100,320,460) name:@"1.png"];
3、新增9個點 再寫一個方法
-(void)addLandDot{ //控制行 for(int i = 0; i < 3; i ++){ //控制列 for(int j = 0; j <3 ; j ++){ [self createImageViewWithFrame:CGRectMake:((65+99*j,280+99*i,52,52) name:@"1.png"]; } } }
將addLandDot新增到initUI方法裡面
[self addLandDot];
4、新增橫線
-(void)addLandScapeLine{ for(int i = 0; i < 6; i ++){ [self createImageViewWithFrame:CGRectMake:(90+i%2*99,265+i/2*99,120,37) name:@"1.png"]; } }
將addLandScapeLine新增到initUI方法裡面 在addLandDot前面,保證點在線上面
[self addLandScapeLine];
5、用同樣的方式新增豎線
-(void)addPortraitLine{ for(int i = 0; i < 6; i ++){ [self createImageViewWithFrame:CGRectMake:(70+i%3*99,265+i/3*99,120,37) name:@"1.png"]; } }
將addPortraitLine新增到initUI方法裡面 在addLandDot前面,保證點在線上面
[self addPortraitLine];
6、新增左右斜線
-(void)addDiagonaitLine{ for(int i = 0; i < 4; i ++){ //左斜線 [self createImageViewWithFrame:CGRectMake:(80+i%2*120,265+i/2*100,120,120) name:@"斜.png"]; //右斜線 [self createImageViewWithFrame:CGRectMake:(73+i%2*99,265+i/2*99,120,120) name:@"斜.png"]; } }
將addDiagonaitLine新增到initUI方法裡面 在addLandDot前面,保證點在線上面
[self addDiagonaitLine];
7、給addLandDot設定tag值
int index = 1; UIImageView *dotImageView = [self createImageViewWithFrame:CGRectMake:((65+99*j,280+99*i,52,52) name:@"1.png"]; dotImageView.tag = index; index ++;
建立一個數組,儲存點的tag值
@property(nonatomic,strong) NSMutableArray *dotImageViewArray;
在initUI裡面初始化陣列
self.dotImageViewArray = [NSMutableArray arrayWithCapacity:9];
在addNineDot裡面將建立的物件放到數組裡面去
[self.dotImageViewArray addObject:dotImageView];
點亮點。要將全部圖片都隱藏,而只留下操作圖片
imageView.hidden = YES; UIImageView *opView = [self createImageViewWithFrame:CGRectMake:((self.view.frame.size.width-320)/2,100,320,460) name:@"1.png"]; opView.hidden = NO;
二、點亮點和線 1、點亮點
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ UITouch *touch = [touches anyObject]; CGPoint location = [touch locationInView:self.view]; //判斷這個觸控點有木有在某一個點上 for(UIImageView *dotView in dotImageView){ // CGRectContainsPoint 判斷某一個矩形區域內是否包含某個點 if(CGRectContainsPoint(dotView.frame, location)){ dotImageView.hidden = NO; } } } -(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ UITouch *touch = [touches anyObject]; CGPoint location = [touch locationInView:self.view]; //判斷這個觸控點有木有在某一個點上 for(UIImageView *dotView in dotImageView){ // CGRectContainsPoint 判斷某一個矩形區域內是否包含某個點 if(CGRectContainsPoint(dotView.frame, location)){ dotImageView.hidden = NO; } } }
2、點亮線 觸控點必須在某一個圓點上,當前這個點沒有被點亮過,上一個點和當前這個點得有線路(給每一條線新增一個tag值,最小的兩位數) 1、橫線 12 23 45 56 78 89 在addLandScapeLine裡面:
int index = 12; //得到這條橫線這個物件 UIImageView *LineImageView = [self createImageViewWithFrame:CGRectMake:(90+i%2*99,265+i/2*99,120,37) name:@"1.png"]; LineImageView.tag = index; index += 11; if((i+1)%2 == 0){ index += 11; }
2、豎線:14 25 36 47 58 69
int index = 14; //得到這條橫線這個物件 UIImageView *LineImageView = [self createImageViewWithFrame:CGRectMake:(90+i%2*99,265+i/2*99,120,37) name:@"1.png"]; LineImageView.tag = index; index += 11;
3、左斜線:24 35 57 68 右斜線:15 26 48 59
int indexL = 24; int indexR = 15 //得到這條橫線這個物件 UIImageView *LineImageViewL = [self createImageViewWithFrame:CGRectMake:(80+i%2*120,265+i/2*100,120,120) name:@"斜.png"]; LineImageViewL.tag = indexL; indexL += 11; UIImageView *LineImageViewR = [self createImageViewWithFrame:CGRectMake:(73+i%2*99,265+i/2*99,120,120) name:@"斜.png"]; LineImageView.tag = indexR; indexR += 11; if((i+1) = 2){ indexL += 11; indexR += 11; }
4、建立一個數組,儲存線的tag值 若數組裡面有tag值,證明有這條路徑,就可以顯示這條線
@property(nonatomic,strong) NSMutableArray *LineViewArray;
5、在initUI裡面初始化陣列
self.LineViewArray = [NSMutableArray array];
6、在所有線裡面將建立的物件放到數組裡面去(注意:在index += 11;改變之前加)
[self.dotImageViewArray addObject:@(index)];
7、定義一個變數,記錄上一個被點亮的tag值
@property(nonatomic,assign) NSInteger lastSelectedDotTag;
8、記錄這個點的tag值
lastSelectedDotTag = dotView.tag;
9、在touchMoved裡面判斷是否點亮這個點
//判斷這個點有木有被點亮 if(dotView.hidden = YES){ //沒有被點亮 //判斷是不是第一個點 if(_lastSelectedTag == 0){ //第一個點 直接點亮 dotView.hidden = NO: _lastSelectedTag = dotView.tag; } else{ //判斷上一個點和當前這個點之間有木有路徑 即判斷數組裡面是否包含值 //獲取上一個點和當前點tag組成的最小兩位數 NSInteger lineTag = _lastSelectedDotTag > dotView.tag?dotView.tag*10+_lastSelectedDotTag:_lastSelectedDotTag*10+dotView.tag; //判斷數組裡面是否包含lineTag if(_lineTagArray containsObject:@(lineTag)){ //有這條線 點亮點 點亮線 dotView.hidden = NO; //通過tag得到一個檢視 UIImageView *lineImageView = [self.view viewWithTag:lineTag]; lineImageView.hidden = NO; _lastSelectedDotTag = dotView.tag; } } }
三、一放手讓點和線都消失 1、定義一個數組,用於儲存點亮的點和線
@property(nonatomic,strong) NSMutableArray *allSelectedViewArray;
2.在initUI裡面初始化陣列
self.allSelectedViewArray = [NSMutableArray array];
3.在所有點亮的裡面將建立的物件放到數組裡面去
[_allSelectedViewArray addObject:……];
4.在touchesEnded裡面
[self hideAllView]; -(void)hideAllView{ for(UIImageView *imgView in allSelectedViewArray){ imgView.hidden = YES; } [_allSelectedViewArray reomveAllObjects]; } 5.顯示畫錯的點
- (void)showWrong{ for (ChangeableImageView *imgView in _allSelectedViewsArray) { [imgView changeImageWithStatus:kImageViewStatusWrong]; } [self performSelector:@selector(hideAllView) withObject:nil afterDelay:1]; } 6.touchesBegin
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ //獲取觸控點的座標 UITouch *touch = [touches anyObject]; CGPoint location = [touch locationInView:self.view]; //判斷這個觸控點有沒有在摸一個圓點上 for (UIImageView *dotView in _dotImageViewArray) { if (CGRectContainsPoint(dotView.frame, location)){ //點亮這個點 dotView.hidden = NO; //記錄這個點的tag值 _lastSelectedDotTag = dotView.tag; //儲存點亮的點 [_allSelectedViewsArray addObject:dotView]; //儲存密碼 拼接字串 [self.mPasswordString appendFormat:@"%ld",dotView.tag]; } } } 7.
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ //獲取觸控點的座標 UITouch *touch = [touches anyObject]; CGPoint location = [touch locationInView:self.view]; //判斷這個觸控點有沒有在摸一個圓點上 for (UIImageView *dotView in _dotImageViewArray) { if (CGRectContainsPoint(dotView.frame, location)){ //判斷這個點有沒有被點亮 if (dotView.hidden == YES){ //沒有被點亮 //判斷是不是第一個點 if (_lastSelectedDotTag == 0){ //第一個點 直接點亮 dotView.hidden = NO; //儲存這個tag值 _lastSelectedDotTag = dotView.tag; //儲存點亮的點 [_allSelectedViewsArray addObject:dotView]; //儲存密碼 拼接字串 [self.mPasswordString appendFormat:@"%ld",dotView.tag]; } else{ //判斷上一個點和當前這個點之間有沒有直接的線路 //獲取上一個點和當前點的tag組成的最小兩位數 NSInteger lineTag = _lastSelectedDotTag > dotView.tag ? dotView.tag * 10 + _lastSelectedDotTag : _lastSelectedDotTag * 10 + dotView.tag; //判斷數組裡面是否包含lineTag if ([_lineTagsArray containsObject:@(lineTag)]){ //有這條線 點亮點 dotView.hidden = NO; //點亮線 UIImageView *lineImageView = [self.view viewWithTag:lineTag]; lineImageView.hidden = NO; _lastSelectedDotTag = dotView.tag; //儲存點亮的點 [_allSelectedViewsArray addObject:dotView]; //儲存點亮的線 [_allSelectedViewsArray addObject:lineImageView]; //儲存密碼 拼接字串 [self.mPasswordString appendFormat:@"%ld",dotView.tag]; } } } } } } 8.
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ //判斷是設定還是解鎖 if (_password.length == 0) { //設定或者確認密碼 if (_firstPasswordString.length == 0){ //設定密碼 //儲存剛才輸入的密碼 self.firstPasswordString = [NSString stringWithString:_mPasswordString]; //提示確認密碼 self.alertlabel.text = @"請確認密碼圖案"; } else{ //確認密碼 if ([_firstPasswordString isEqualToString:_mPasswordString]){ self.alertlabel.text = @"設定成功"; //儲存密碼 [[NSUserDefaults standardUserDefaults] setObject:_mPasswordString forKey:@"password"]; } else{ self.alertlabel.text = @"兩次圖案不一致 請重新繪製"; self.firstPasswordString = @""; [self showWrong]; } } } else{ //有過密碼了 if ([self.mPasswordString isEqualToString:_password]){ //密碼成功 self.alertlabel.text = @"解鎖成功"; } else{ //密碼錯誤 self.alertlabel.text = @"密碼錯誤 請重新繪製"; [self showWrong]; } } } 三、建立圖片類
1.建立標頭檔案ChangeableImageView.h
typedef enum{ kImageViewStatusNormal, kImageViewStatusWrong } kImageViewStatus; @interface ChangeableImageView : UIImageView @property (nonatomic, strong) NSString *normalImageName; @property (nonatomic, strong) NSString *wrongImageName; - (void)changeImageWithStatus:(kImageViewStatus)status; + (ChangeableImageView *)imageViewWithNormalImageName:(NSString *)normal andWrongImageName:(NSString *)wrong frame:(CGRect)frame father:(UIView *)contetView; 2.ChangeableImageView.m
@implementation ChangeableImageView - (void)changeImageWithStatus:(kImageViewStatus)status{ if (status == kImageViewStatusNormal){ self.image = [UIImage imageNamed:_normalImageName]; } else{ self.image = [UIImage imageNamed:_wrongImageName]; } } + (ChangeableImageView *)imageViewWithNormalImageName:(NSString *)normal andWrongImageName:(NSString *)wrong frame:(CGRect)frame father:(UIView *)contetView{ ChangeableImageView *img = [[ChangeableImageView alloc] initWithFrame:frame]; img.normalImageName = normal; img.wrongImageName = wrong; img.hidden = YES; img.image = [UIImage imageNamed:normal]; [contetView addSubview:img]; return img; } 四、整體完整程式碼
#import "ViewController.h" #import "ChangeableImageView.h" @interface ViewController () //儲存9個圓點的物件 @property (nonatomic, strong) NSMutableArray *dotImageViewArray; //儲存所有線的tag @property (nonatomic, strong) NSMutableArray *lineTagsArray; //儲存上一次被點亮的點的tag值 @property (nonatomic, assign) NSInteger lastSelectedDotTag; //儲存所有點亮的點或者線 @property (nonatomic, strong) NSMutableArray *allSelectedViewsArray; //記錄密碼 @property (nonatomic, strong) NSMutableString *mPasswordString; //提示使用者操作的label @property (nonatomic, strong) UILabel *alertlabel; //儲存原始的密碼 @property (nonatomic, strong) NSString *password; //儲存設定密碼中第一次輸入的密碼 @property (nonatomic, strong) NSString *firstPasswordString; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //初始化陣列 self.dotImageViewArray = [NSMutableArray arrayWithCapacity:9]; self.lineTagsArray = [NSMutableArray array]; self.allSelectedViewsArray = [NSMutableArray array]; self.mPasswordString = [NSMutableString string]; [self initUI]; } /** 建立一個UIImageView */ - (UIImageView *)createImageViewWithFrame:(CGRect)frame name:(NSString *)imageName{ UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame]; imageView.image = [UIImage imageNamed:imageName]; imageView.hidden = YES; //隱藏 [self.view addSubview:imageView]; return imageView; } //介面佈局 - (void)initUI{ //背景圖片 UIImageView UIImage UIImageView *bg =[self createImageViewWithFrame:self.view.bounds name:@"Main_BG"]; bg.hidden = NO; //新增操作圖片 UIImageView *opView = [self createImageViewWithFrame:CGRectMake((self.view.frame.size.width-320)/2, 100, 320, 460) name:@"Unlock_DotLock1_Normal"]; opView.hidden = NO; //建立label self.alertlabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 180, self.view.frame.size.width, 50)]; _alertlabel.textAlignment = NSTextAlignmentCenter; _alertlabel.textColor = [UIColor whiteColor]; [self.view addSubview:_alertlabel]; //獲取UserDefaults裡面儲存的密碼 self.password = [[NSUserDefaults standardUserDefaults] objectForKey:@"password"]; if (_password.length == 0){ //設定密碼 _alertlabel.text = @"請設定密碼圖案"; } else{ //輸入密碼 _alertlabel.text = @"請繪製解鎖圖案"; } //橫線 [self addLandScapeLine]; //豎線 [self addPortraitLine]; //斜線 [self addDiagonalLine]; //新增9個點 [self addNineDot]; } - (void)addNineDot{ int index = 1; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { ChangeableImageView *dotImageView = [ChangeableImageView imageViewWithNormalImageName:@"Unlock_DotLock1_Selected" andWrongImageName:@"Unlock_DotLock_Wrong1" frame:CGRectMake(63 + 99 * j, 265 + 99*i, 52, 52) father:self.view]; //設定tag值 dotImageView.tag = index; index++; //將建立的這個物件放到數組裡面去 [self.dotImageViewArray addObject:dotImageView]; } } } /* 12 23 45 56 78 89 */ - (void)addLandScapeLine{ int index = 12;//第一條線的tag值 for (int i = 0; i < 6; i++) { ChangeableImageView *lineImageView = [ChangeableImageView imageViewWithNormalImageName:@"Unlock_DotLock1_Normal_Highlight1" andWrongImageName:@"Unlock_DotLock1_Wrong_Highlight1" frame:CGRectMake(70 + i%2*99, 270+i/2*99, 120, 37) father:self.view]; lineImageView.tag = index; //將tag值新增到陣列中 //NSNumber *num = [NSNumber numberWithInt:index]; [self.lineTagsArray addObject:@(index)]; index += 11; if (((i+1) % 2 == 0) && i != 0){ index += 11; } } } /* 14 25 36 47 58 69 */ - (void)addPortraitLine{ int index = 14; for (int i = 0; i < 6; i++) { ChangeableImageView *lineImageView = [ChangeableImageView imageViewWithNormalImageName:@"Unlock_DotLock1_Normal_Highlight2" andWrongImageName:@"Unlock_DotLock1_Wrong_Highlight2" frame:CGRectMake(70 + i%3*99, 270+i/3*99, 37, 120) father:self.view]; lineImageView.tag = index; //將tag值新增到陣列中 [self.lineTagsArray addObject:@(index)]; index += 11; } } /* 24 35 57 68 15 26 48 59 */ - (void)addDiagonalLine{ int indexL = 24; int indexR = 15; for (int i = 0; i < 4; i++) { ChangeableImageView *LLineView = [ChangeableImageView imageViewWithNormalImageName:@"Unlock_DotLock1_Normal_Highlight4" andWrongImageName:@"Unlock_DotLock1_Wrong_Highlight4" frame:CGRectMake(85 + i%2*99, 270+i/2*99, 120, 120) father:self.view]; LLineView.tag = indexL; //將tag值新增到陣列中 [self.lineTagsArray addObject:@(indexL)]; indexL += 11; ChangeableImageView *RLineView = [ChangeableImageView imageViewWithNormalImageName:@"Unlock_DotLock1_Normal_Highlight3" andWrongImageName:@"Unlock_DotLock1_Wrong_Highlight3" frame:CGRectMake(73 + i%2*99, 270+i/2*99, 120, 120) father:self.view]; RLineView.tag = indexR; //將tag值新增到陣列中 [self.lineTagsArray addObject:@(indexR)]; indexR += 11; if ((i+1) == 2){ indexL += 11; indexR += 11; } } } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ //獲取觸控點的座標 UITouch *touch = [touches anyObject]; CGPoint location = [touch locationInView:self.view]; //判斷這個觸控點有沒有在摸一個圓點上 for (UIImageView *dotView in _dotImageViewArray) { if (CGRectContainsPoint(dotView.frame, location)){ //點亮這個點 dotView.hidden = NO; //記錄這個點的tag值 _lastSelectedDotTag = dotView.tag; //儲存點亮的點 [_allSelectedViewsArray addObject:dotView]; //儲存密碼 拼接字串 [self.mPasswordString appendFormat:@"%ld",dotView.tag]; } } } - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ //獲取觸控點的座標 UITouch *touch = [touches anyObject]; CGPoint location = [touch locationInView:self.view]; //判斷這個觸控點有沒有在摸一個圓點上 for (UIImageView *dotView in _dotImageViewArray) { if (CGRectContainsPoint(dotView.frame, location)){ //判斷這個點有沒有被點亮 if (dotView.hidden == YES){ //沒有被點亮 //判斷是不是第一個點 if (_lastSelectedDotTag == 0){ //第一個點 直接點亮 dotView.hidden = NO; //儲存這個tag值 _lastSelectedDotTag = dotView.tag; //儲存點亮的點 [_allSelectedViewsArray addObject:dotView]; //儲存密碼 拼接字串 [self.mPasswordString appendFormat:@"%ld",dotView.tag]; } else{ //判斷上一個點和當前這個點之間有沒有直接的線路 //獲取上一個點和當前點的tag組成的最小兩位數 NSInteger lineTag = _lastSelectedDotTag > dotView.tag ? dotView.tag * 10 + _lastSelectedDotTag : _lastSelectedDotTag * 10 + dotView.tag; //判斷數組裡面是否包含lineTag if ([_lineTagsArray containsObject:@(lineTag)]){ //有這條線 點亮點 dotView.hidden = NO; //點亮線 UIImageView *lineImageView = [self.view viewWithTag:lineTag]; lineImageView.hidden = NO; _lastSelectedDotTag = dotView.tag; //儲存點亮的點 [_allSelectedViewsArray addObject:dotView]; //儲存點亮的線 [_allSelectedViewsArray addObject:lineImageView]; //儲存密碼 拼接字串 [self.mPasswordString appendFormat:@"%ld",dotView.tag]; } } } } } } - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ //判斷是設定還是解鎖 if (_password.length == 0) { //設定或者確認密碼 if (_firstPasswordString.length == 0){ //設定密碼 //儲存剛才輸入的密碼 self.firstPasswordString = [NSString stringWithString:_mPasswordString]; //提示確認密碼 self.alertlabel.text = @"請確認密碼圖案"; } else{ //確認密碼 if ([_firstPasswordString isEqualToString:_mPasswordString]){ self.alertlabel.text = @"設定成功"; //儲存密碼 [[NSUserDefaults standardUserDefaults] setObject:_mPasswordString forKey:@"password"]; } else{ self.alertlabel.text = @"兩次圖案不一致 請重新繪製"; self.firstPasswordString = @""; [self showWrong]; } } } else{ //有過密碼了 if ([self.mPasswordString isEqualToString:_password]){ //密碼成功 self.alertlabel.text = @"解鎖成功"; } else{ //密碼錯誤 self.alertlabel.text = @"密碼錯誤 請重新繪製"; [self showWrong]; } } } - (void)showWrong{ for (ChangeableImageView *imgView in _allSelectedViewsArray) { [imgView changeImageWithStatus:kImageViewStatusWrong]; } [self performSelector:@selector(hideAllView) withObject:nil afterDelay:1]; } - (void)hideAllView{ for (ChangeableImageView *imgView in _allSelectedViewsArray) { imgView.hidden = YES; [imgView changeImageWithStatus:kImageViewStatusNormal]; } //清空 [_allSelectedViewsArray removeAllObjects]; _lastSelectedDotTag = 0; [_mPasswordString setString:@""]; } @end