您的位置:首页 > 移动开发 > IOS开发

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. 改变状态栏的样式

-(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吧,想了好久,还是解决不了。尝试过,如果答案按钮文字满后,将待选项按钮设置为不可用,但是一旦设置成不可用后,就不能再设置回可点击状态了。最后,就是求助功能还没有实现,待以后学习到,再回来完善这个项目。

——爱分享,一起学,共成长。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: