iOS学习之路-超级猜图
2016-01-16 21:06
471 查看
超级猜图,这个项目的代码敲完的时候,发现已经超过了400行,代码量已经远远超出了之前所学的了 。虽然代码量很多,但是知识点却都是之前学的,纵观整个项目,都没有新的知识点,可以这样说。在这个项目中,比较难理解的,就是添加答案按钮和待选项按钮的计算,以及对应的X轴和Y轴的计算了,也是比较繁琐的,还包括各种按钮的监听事件吧,要使用for循环遍历,使每个按钮都要注册监听器。整体情况完成的差不多,还有点bug吧,就看有没有大牛看到帮我解决了。
一、功能分析
1. 主要功能有提示、大图、下一题,回答问题。当用户点击提示时,会自动扣取相应的分数,并且将答案的第一个字填写到答案按钮中;当用户点击大图按钮或者图片时,将图片放大后放到屏幕的中央,并且屏幕的后面有一层阴影效果,当用户点击图片或者后面的阴影时,图片就会自动缩小会原来的位置,并且阴影消失。当用户点击下一题按钮时,图片会更换自下一题,对应的答案按钮的数量和待选项按钮和文字也会相对应的更改。
2. 当用户点击待选项按钮时,待选项按钮会被隐藏,而对应的文字则会显示在答案按钮中。当用户点击的答案正确时,字会变成蓝色,分数会增加,并且0.5秒后,自动跳到下一题 ;若答案不正确,则字体颜色变成红色。
3. 当进行到最后一道题时,用户再次点击了正确的答案后,答案按钮的字体仍变成蓝色,但是不会跳转道下一题,因为没有了下一题。
二、步骤分析
1. 先用storyboard搭建出基本的界面。显示题号的UILabel,显示题目的UILabel,显示图片的UIImageView,显示金币的UIButton,4个功能按钮UIButton。
2. 用for循环,创建出答案相对应个数的答案按钮以及待选项个数的待选项按钮。
3. 分别监听答案按钮、待选项按钮以及各种UIButton和UILabel等。
4. 完成答题的逻辑处理。
三、用户界面的设置和更改
1. 改变状态栏的样式
2. 更还图片的内边距。为了美观,我们在UIImageView的Background设置成一张白色的图片,将Image设置成我们要的图片。然后在UIImageView的Attributes inspectors一栏中,将inset的四个数值分别设置成自己想要的边距就可以了。
3. 分数按钮的设置。为了让分数按钮失去点击的作用。我们一般将其Attributes inspectors一栏中user Interaction Enabled勾去掉。当然,将Control下的Content的Enabled的勾去掉也行,不过一般以去掉前者为主。
4.为了能让图片的大小可以被我们所更改,我们需要将File inspectors 下的use Auto Layout的选项取消打勾。不然,当我们点击图片和大图按钮的时候,图片的尺寸不会更改。
四、添加答案按钮和待选项按钮的算法分析
(1)每一行的y值相同,行号决定y的值。计算行号:int row = i / totalColumns;
(2)每一行的x值相同,列号觉得x的值。计算列号:int col = i % totalColumns;
(3)待选项按钮和答案按钮距离view的间距以及答案按钮的X值和待选项按钮的X值和Y值的计算,如下图所示。
这是计算答案按钮的leftMargin和X值。其中,answerW的值和margin的值需要我们自己定义。
这是计算待选项按钮的leftMargin和X的值以及Y的值。其中,optionW的值、optionH的值需要我们定义。
4. 相关代码
①添加存放答案的按钮
②添加待选项的按钮
五、部分代码及说明
(1)监听答案按钮的点击。
①当待选项按钮optionBtn的hidden属性 = NO时,显示之前被隐藏的optionBtn。
② optionBtn.currentTitle 和answerBtn.currentTitle 是获取当前待选项按钮和答案按钮的Title。
③ 想让用户点击的答案按钮的文字消失时,只需要将其Title设置成nil即可。
① 当optionBtn的hidden属性 = YES时,对应点击的optionBtn将会暂时被隐藏。
② 调用的titleForState方法。传的参数一般设置为UIControlStateNormal,即普通状态下的文字。
① 先判断答案按钮是否有文字,当有文字时,调用appendString方法,将其答案按钮的文字进行拼接,并保存到tempAnswerTitle数组中。
② 当答案按钮被填满字时,取出模型类的答案数据,与tempAnswerTitle进行比较。若两者相同,则将答案文字设置为蓝色,分数增加相应分值,并且跳到下一题。
(4)监听放大按钮事件
① alloc一个按钮对象,设置frame,背景颜色及透明度alpha = 0.0。
② 为阴影注册缩小图片的监听器。
③ 交换图片和阴影的层顺序
④ 用block动画更改阴影的透明度以图片的大小。
① 先把用户点击的答案按钮的文字去掉,for循环为answerBtn注册answerClick监听器即可。相当于用户点击了答案按钮。
② 取出模型答案的第一个字,循环遍历待选项按钮的文字,若遍历到待选项按钮的文字与答案的第一个字相符时,停止遍历,并将该待选项按钮的文字添加到第一个答案按钮中,对应的待选项按钮隐藏,即相当于点击了待选项按钮事件。最后,分数减少对应的数值。
六、运行结果
由运行结果可知,当输入的答案不正确时,答案按钮的字体颜色就会变成红色。但输入的答案正确时,答案按钮的颜色就会变成蓝色,但由于是最后一道题,所以不会跳转到下一题此时,下一题按钮也变成了灰色,不可点击的状态。
七、总结
都实现了基本的功能,但还存在着不少问题。首先第一次在真机测试的时,到了最后一道题,在输入正确的答案后,程序闪退了。之后,在模拟器测试也是这样,分析了下,原来是数组越界了。因为到了最后的一道题,当再次调用next下一题方法时,就会导致数组越界的错误。解决方法时,只要加一个判断标志就可以了。其次,当用户输入了不正确的答案时,答案按钮上的字就会变成红色,但此时,当用户继续点击待选项按钮时,待选项按钮还是会消失,但答案按钮因为文字满了,所以不会继续显示。点击答案按钮时,之前点击的文字会重新显示,但后来点击的待选项按钮却不会再次显示出来,这是一个bug吧,想了好久,还是解决不了。尝试过,如果答案按钮文字满后,将待选项按钮设置为不可用,但是一旦设置成不可用后,就不能再设置回可点击状态了。最后,就是求助功能还没有实现,待以后学习到,再回来完善这个项目。
——爱分享,一起学,共成长。
一、功能分析
1. 主要功能有提示、大图、下一题,回答问题。当用户点击提示时,会自动扣取相应的分数,并且将答案的第一个字填写到答案按钮中;当用户点击大图按钮或者图片时,将图片放大后放到屏幕的中央,并且屏幕的后面有一层阴影效果,当用户点击图片或者后面的阴影时,图片就会自动缩小会原来的位置,并且阴影消失。当用户点击下一题按钮时,图片会更换自下一题,对应的答案按钮的数量和待选项按钮和文字也会相对应的更改。
2. 当用户点击待选项按钮时,待选项按钮会被隐藏,而对应的文字则会显示在答案按钮中。当用户点击的答案正确时,字会变成蓝色,分数会增加,并且0.5秒后,自动跳到下一题 ;若答案不正确,则字体颜色变成红色。
3. 当进行到最后一道题时,用户再次点击了正确的答案后,答案按钮的字体仍变成蓝色,但是不会跳转道下一题,因为没有了下一题。
二、步骤分析
1. 先用storyboard搭建出基本的界面。显示题号的UILabel,显示题目的UILabel,显示图片的UIImageView,显示金币的UIButton,4个功能按钮UIButton。
2. 用for循环,创建出答案相对应个数的答案按钮以及待选项个数的待选项按钮。
3. 分别监听答案按钮、待选项按钮以及各种UIButton和UILabel等。
4. 完成答题的逻辑处理。
三、用户界面的设置和更改
1. 改变状态栏的样式
-(UIStatusBarStyle)perferredStatusBarStyle{ return UIStatusBarStyleLightContent; }如果不添加该段代码的话,状态栏的颜色为黑色。添加这段代码后,状态栏颜色则变为白色。
2. 更还图片的内边距。为了美观,我们在UIImageView的Background设置成一张白色的图片,将Image设置成我们要的图片。然后在UIImageView的Attributes inspectors一栏中,将inset的四个数值分别设置成自己想要的边距就可以了。
3. 分数按钮的设置。为了让分数按钮失去点击的作用。我们一般将其Attributes inspectors一栏中user Interaction Enabled勾去掉。当然,将Control下的Content的Enabled的勾去掉也行,不过一般以去掉前者为主。
4.为了能让图片的大小可以被我们所更改,我们需要将File inspectors 下的use Auto Layout的选项取消打勾。不然,当我们点击图片和大图按钮的时候,图片的尺寸不会更改。
四、添加答案按钮和待选项按钮的算法分析
(1)每一行的y值相同,行号决定y的值。计算行号:int row = i / totalColumns;
(2)每一行的x值相同,列号觉得x的值。计算列号:int col = i % totalColumns;
(3)待选项按钮和答案按钮距离view的间距以及答案按钮的X值和待选项按钮的X值和Y值的计算,如下图所示。
这是计算答案按钮的leftMargin和X值。其中,answerW的值和margin的值需要我们自己定义。
这是计算待选项按钮的leftMargin和X的值以及Y的值。其中,optionW的值、optionH的值需要我们定义。
4. 相关代码
①添加存放答案的按钮
- (void)addAnswerBtn: (KIMQuestion *)question{ //5.1 删除之前的答案框 [self.answerView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; //5.2 添加新的答案框 unsigned long length = question.answer.length; for (int i = 0; i < length; i++) { UIButton *answerBtn = [[UIButton alloc]init]; [answerBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; // 设置背景 [answerBtn setBackgroundImage:[UIImage imageNamed:@"btn_answer"] forState:UIControlStateNormal]; [answerBtn setBackgroundImage:[UIImage imageNamed:@"btn_answer_highlighted"] forState:UIControlStateHighlighted]; // 设置frame CGFloat margin = 10; CGFloat answerW = 35; CGFloat answerH = 35; // 存放答案按钮的view的width = 当前view的width CGFloat viewW = self.view.frame.size.width; // 第一个按钮距离view的间距 = (viewW - 答案的长度 * 按钮的width - 每个按钮间距 *(个数 -1 ) )*0.5 CGFloat leftMargin = (viewW - length * answerW - margin * (length - 1) )* 0.5; CGFloat answerX = leftMargin + i * (answerW + margin); answerBtn.frame = CGRectMake(answerX, 0, answerW, answerH); // 将answerBtn添加到answerView [self.answerView addSubview:answerBtn]; // 监听点击 [answerBtn addTarget:self action:@selector(answerClick:) forControlEvents:UIControlEventTouchUpInside]; } }
②添加待选项的按钮
- (void)addOptionBtn: (KIMQuestion *)question{ //6.1 删除之前的待选项 [self.optionView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; //6.2 添加新的待选按钮 unsigned long count = question.options.count; for (int i = 0; i < count; i++) { UIButton *optionBtn = [[UIButton alloc]init]; // 设置背景 [optionBtn setBackgroundImage:[UIImage imageNamed:@"btn_option"] forState:UIControlStateNormal]; [optionBtn setBackgroundImage:[UIImage imageNamed:@"btn_option_highlighted"] forState:UIControlStateHighlighted]; // 设置frame CGFloat optionW = 35; CGFloat optionH = 35; CGFloat margin = 10; int totalColumns = 8; CGFloat viewW = self.view.frame.size.width; CGFloat leftMargin = (viewW - totalColumns * optionW - margin * (totalColumns - 1)) * 0.5; int col = i % totalColumns; CGFloat optionX = leftMargin + col * (optionW + margin); int row = i / totalColumns; CGFloat optionY = row * (optionH + margin); optionBtn.frame = CGRectMake(optionX, optionY, optionW, optionH); // 设置文字 [optionBtn setTitle:question.options[i] forState:UIControlStateNormal]; [optionBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; // 将optionBtn添加到optionView [self.optionView addSubview:optionBtn]; // 监听点击 [optionBtn addTarget:self action:@selector(optionClick:) forControlEvents:UIControlEventTouchUpInside]; } }
五、部分代码及说明
(1)监听答案按钮的点击。
①当待选项按钮optionBtn的hidden属性 = NO时,显示之前被隐藏的optionBtn。
② optionBtn.currentTitle 和answerBtn.currentTitle 是获取当前待选项按钮和答案按钮的Title。
③ 想让用户点击的答案按钮的文字消失时,只需要将其Title设置成nil即可。
- (void)answerClick:(UIButton *)answerBtn{ // 1.让答案按钮文字对应的待选按钮显示(hidden = NO) for (UIButton *optionBtn in self.optionView.subviews) { if ([optionBtn.currentTitle isEqualToString:answerBtn.currentTitle]) { optionBtn.hidden = NO; break; // 停止遍历 } } // 2.让被点击的答案按钮的文字消失 [answerBtn setTitle:nil forState:UIControlStateNormal]; // 3.让所有的答案按钮变为黑色 for (UIButton *answerBtn in self.answerView.subviews) { [answerBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; } }(2)监听待选项按钮的点击
① 当optionBtn的hidden属性 = YES时,对应点击的optionBtn将会暂时被隐藏。
② 调用的titleForState方法。传的参数一般设置为UIControlStateNormal,即普通状态下的文字。
- (void)optionClick:(UIButton *)optionBtn{ // 1.让被点击的待选按钮消失 optionBtn.hidden = YES; // 2.把文件显示到答案按钮上 for (UIButton *answerBtn in self.answerView.subviews) { // 判断按钮是否有文字 NSString *answerTitle = [answerBtn titleForState:UIControlStateNormal]; if (answerTitle.length == 0) { // 没有文字 // 设置答案按钮的文字为被点击待选项按钮的文字 NSString *optionTitle = [optionBtn titleForState:UIControlStateNormal]; [answerBtn setTitle:optionTitle forState:UIControlStateNormal]; break; } } // 3.判断答案的正确性 [self chickAnswer]; }(3)判断答案的正确性
① 先判断答案按钮是否有文字,当有文字时,调用appendString方法,将其答案按钮的文字进行拼接,并保存到tempAnswerTitle数组中。
② 当答案按钮被填满字时,取出模型类的答案数据,与tempAnswerTitle进行比较。若两者相同,则将答案文字设置为蓝色,分数增加相应分值,并且跳到下一题。
- (void)chickAnswer{ BOOL full = YES; NSMutableString *tempAnswerTitle = [NSMutableString string]; for (UIButton *answerBtn in self.answerView.subviews) { if (answerBtn.currentTitle.length == 0) { //没有文字 full = NO; } // 拼接按钮文字 if(answerBtn.currentTitle){ [tempAnswerTitle appendString:answerBtn.currentTitle]; } } if(full){ KIMQuestion *question = self.questions[self.index]; if ([tempAnswerTitle isEqualToString:question.answer]) { // 答案正确,将文字的颜色更改为蓝色 for (UIButton *answerBtn in self.answerView.subviews){ [answerBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; } // 分数增加100 [self addScore:100]; // 0.5秒后跳到下一题 // 必须加一个判断标志,如果没有判断,进行到最后一道题,再答对的话,程序会闪退 if(self.index != self.questions.count - 1){ [self performSelector:@selector(next) withObject:nil afterDelay:0.5]; } }else{ // 答案错误,将文字的颜色更改为红色 for (UIButton *answerBtn in self.answerView.subviews) { [answerBtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; } } } }
(4)监听放大按钮事件
① alloc一个按钮对象,设置frame,背景颜色及透明度alpha = 0.0。
② 为阴影注册缩小图片的监听器。
③ 交换图片和阴影的层顺序
④ 用block动画更改阴影的透明度以图片的大小。
- (IBAction)bigImage { //1. 添加阴影 UIButton *shadow = [[UIButton alloc]init]; shadow.frame = self.view.bounds; shadow.backgroundColor = [UIColor blackColor]; shadow.alpha = 0.0; [shadow addTarget:self action:@selector(smallImag) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:shadow]; self.shadow = shadow; //2. 调整图片和阴影的先后顺序 [self.view bringSubviewToFront:self.iconBtn]; [UIView animateWithDuration:0.25 animations:^{ shadow.alpha = 0.7; //3. 更改图片的frame CGFloat iconW = self.view.frame.size.width; CGFloat iconH = iconW; CGFloat iconY = (self.view.frame.size.height - iconH) * 0.5; self.iconBtn.frame = CGRectMake(0, iconY, iconW, iconH); }]; }(5)监听点击提示按钮事件
① 先把用户点击的答案按钮的文字去掉,for循环为answerBtn注册answerClick监听器即可。相当于用户点击了答案按钮。
② 取出模型答案的第一个字,循环遍历待选项按钮的文字,若遍历到待选项按钮的文字与答案的第一个字相符时,停止遍历,并将该待选项按钮的文字添加到第一个答案按钮中,对应的待选项按钮隐藏,即相当于点击了待选项按钮事件。最后,分数减少对应的数值。
- (IBAction)tip { // 1.把所有答案按钮的文字去掉,并将隐藏的待选项按钮显示 for (UIButton *answerBtn in self.answerView.subviews) { [self answerClick:answerBtn]; } // 2.取出模型的答案 KIMQuestion *question =self.questions[self.index]; // 2.1取出答案的第一个字 NSString *firstAnswer = [question.answer substringToIndex:1]; for (UIButton *optionBtn in self.optionView.subviews) { if ([optionBtn.currentTitle isEqualToString:firstAnswer]) { [self optionClick:optionBtn]; [self addScore:-200]; break; } } }
六、运行结果
由运行结果可知,当输入的答案不正确时,答案按钮的字体颜色就会变成红色。但输入的答案正确时,答案按钮的颜色就会变成蓝色,但由于是最后一道题,所以不会跳转到下一题此时,下一题按钮也变成了灰色,不可点击的状态。
七、总结
都实现了基本的功能,但还存在着不少问题。首先第一次在真机测试的时,到了最后一道题,在输入正确的答案后,程序闪退了。之后,在模拟器测试也是这样,分析了下,原来是数组越界了。因为到了最后的一道题,当再次调用next下一题方法时,就会导致数组越界的错误。解决方法时,只要加一个判断标志就可以了。其次,当用户输入了不正确的答案时,答案按钮上的字就会变成红色,但此时,当用户继续点击待选项按钮时,待选项按钮还是会消失,但答案按钮因为文字满了,所以不会继续显示。点击答案按钮时,之前点击的文字会重新显示,但后来点击的待选项按钮却不会再次显示出来,这是一个bug吧,想了好久,还是解决不了。尝试过,如果答案按钮文字满后,将待选项按钮设置为不可用,但是一旦设置成不可用后,就不能再设置回可点击状态了。最后,就是求助功能还没有实现,待以后学习到,再回来完善这个项目。
——爱分享,一起学,共成长。
相关文章推荐
- iOS 【Multithreading-GCD 同步/异步函数 和 串行/并发队列 的6种搭配使用及介绍】
- iOS盲人模式小结
- iOS调试Bug方式之——NSZombieEnabled(僵尸模式)
- GLKit Framework 浅析
- iOS:获取图片Alpha图片
- ios之TableViewCell重用机制避免反复显示问题
- ios 常见错误整理 持续更新
- ios nsnumber怎么转换成nsstring
- 苹果审核通过后包体大了200多MB!都是Xcode 7的错?
- iOS之 json数据解析
- 更新Windows ActiveX,Ios
- iOS--错误集锦--****is missing a [super ViewDidLoad]call
- iOS 8 自适应 Cell
- ios开发笔记
- 基于SnapKit写的自动计算行高开源库
- iOS 异常处理@try,catch
- IOS级联(省份和城市)
- iOS Xcode编译报错问题解决办法汇总
- ios下,对于position:fixed支持不完美的额解决方案
- iOS开发~CocoaPods使用详细说明