一、要先进行页面布局
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