ios开发-UI基础-超级猜图

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

[注意]转载时请注明出处博客园-吃唐僧肉的小悟空http://www.cnblogs.com/hukezhu/

本篇文章介绍一个比较综合的小应用----超级猜图.

功能分析:

根据显示的图片,在下面的待选项按钮中选中正确答案按钮,选中的按钮会显示在正确答案按钮中答案错误,答案颜色变为红色,分数减小答案正确,答案颜色变为蓝色,两秒自动跳入下一题,分数增加点击"下一题"可以进入下一个题目点击"大图",可以放大显示图片,再次点击图片或者背景,图片缩小至原来大小点击"提示",自动情况答案选项,并显示正确答案的第一个字,并且分数减小应用截图:

下面附上完成这个小应用的思路:

11. 通过storyboard设计"超级猜图"的上半部分界面。21>使用UIImageView做背景(最后面的背景图片,首先添加这个)32>分析界面上的控件,显示图片的也使用button,显示内容的使用label,4下面显示答案按钮和最下面显示待选项按钮的位置使用view5中间的图片可以点击:用button,button有一个inset:分别设置内部内容距离上左下右有多少不能显示6782. 实现点击"下一题"功能.(最开始状态是没有数据的,首先点击下一题,我们家在数据之后,才能做其他的功能,所以最开始先完成"下一题"的功能)9*声明一个index属性来记录当前显示的题目的索引。1011* 当我们点击"下一题"的时候, 从数组中获取对应的题目, 并显示到对应的界面控件上。121314* 解决:最后一题之后再次点击"下一题"索引越界问题。(此处进行判断)1516/*0.判断索引值是否越界,并且弹框17if (self.index == self.questions.count - 1) {18// UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"恭喜" message:@"过关了" delegate:nil19// cancelButtonTitle:@"取消" otherButtonTitles:@"A", nil];20// [alert show];21UIActionSheet *acionsheet = [[UIActionSheet alloc]initWithTitle:@"恭喜" delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:@"确定" otherButtonTitles:@"A",@"B", nil];22[acionsheet showInView:self.view];2324return;25}2627*/2829303. 在viewDidLoad中初始化第一个问题(显示第一个问题到界面上)。31* 设置self.index = -132* 手动调用"下一题"按钮的点击事件33[self next];343536374. 实现"查看大图"功能(点击右侧"大图"按钮, 显示大图)3839*实现思路(步骤):401> 添加一个"阴影"按钮, 因为该"阴影"要实现点击, 所以用"按钮"412> 然后再把"头像按钮"显示在"阴影"上面。423> 通过动画的方式改变"头像按钮"的frame(位置和尺寸)变成大图效果。43** 注意: 取消"自动布局(Auto Layout)"4445** 点击"遮罩阴影", 回到小图461> 通过动画慢慢将"遮罩阴影"的透明度变为0472> 通过动画慢慢将"头像图片"的frame修改为原来的位置483> 在动画执行完毕后, 移除"遮罩阴影"4950**点击图片本身显示大图, 再次点击图片本身显示小图5152535455565. 动态生成"答案按钮"。57*思路:580> 在点击"下一题"按钮中实现该功能591> 创建一个UIView来存放所有的"答案按钮"602>根据每个问题的答案的文字个数来创建按钮613>每次创建按钮之前, 先把旧的按钮都删除62此处有两种方案:631-循环便利数组,执行removefromsuperview642-使用makeObjectsPerformSelector:@selector(removeFromSuperview)654> 指定每个"答案按钮"的尺寸和中间的margin, 然后计算第一个按钮的x值(marginLeft)。665>在循环中, 计算每个按钮的x值(y值都是0)。676869706. 动态生成"待选项按钮"。71*思路:720> 在点击"下一题"按钮中实现该功能731> 创建一个UIView来存放所有的"待选项按钮"742>根据待选项按钮的个数来创建753>清除之前的待选项按钮764>利用九宫格的算法创建待选项按钮77787. 实现"待选按钮"的单击事件79* 隐藏当前被点击的"待选按钮"80* 将当前被点击的"待选按钮"的文字显示到"答案按钮"的左起第一个为空的按钮上81* 如果"答案按钮"已经全部填满了, 不允许再点击"待选按钮"8283**注意: 只要父控件不能处理事件, 那么子控件也无法处理事件(另外一种解决方案)。841> 如果"答案按钮"文字填满了, 则设置option view禁止与用户交互85self.optionsView.userInteractionEnabled =NO;86872> 当用户再次点击"答案按钮"时 或 点击"下一题"后在创建"待选按钮"的时候再次启用option view与用户的交互功能88self.optionsView.userInteractionEnabled =YES;89909192938. 实现"答案按钮"的单击事件94* 设置被点击的"答案按钮"文字为空(nil)95* 设置与当前被点击的"答案按钮"相对应的"待选按钮"显示出来96(97**注意:当答案按钮中有两个相同的文字的option按钮时的问题98**解决方案一:991>为每个option按钮设置一个唯一的tag1002>在点击某个option按钮的时候, 把option按钮的text和tag都设置到answer按钮上1013>在点击answer按钮的时候, 判断answer按钮的文字与tag同时都与某个option按钮匹配时, 再显示这个option按钮102**解决方案二:103执行判断的时候,并且判断字体的hidden属性为YES104)105* 设置所有"答案按钮"的文字颜色为黑色1061071089. 在"待选按钮"的单击事件中, 判断当前的答案的正确性109* 每次点击"待选按钮"都需要做判断, 如果答案按钮"满了", 再去判断正确性110*如果正确:1111> 那么设置"答案按钮"的文字颜色为蓝色1122>加分1133>2秒钟后自动跳转到下一题114115*如果错误:1161>答案按钮的文字设置为红色11711811910. 点击"提示"按钮120*加分121* 清空所有"答案按钮"的文字(相当于点击了每一个"答案按钮", 不是简单的设置"答案按钮"的文字为nil)122* 并将正确答案的第一个文字设置到第一个"答案按钮"上(相当于正确答案的option按钮被点击了), 通过调用字符串的substringToIndex:来截取第一个字符的字符串

[注意]转载时请注明出处博客园-吃唐僧肉的小悟空http://www.cnblogs.com/hukezhu/

[注意]转载时请注明出处博客园-吃唐僧肉的小悟空http://www.cnblogs.com/hukezhu/

附上应用代码结构图:

storyboard拖线图:

附上源代码:

KZAppModel.h

1//2//KZAppModel.h3//UI基础-04-05-164//5//Created by hukezhu on 15/5/16.6//7//89#import<Foundation/Foundation.h>1011@interfaceKZAppModel : NSObject12@PRoperty (nonatomic,copy) NSString *answer;13@property (nonatomic,copy) NSString *icon;14@property (nonatomic,copy) NSString *title;15@property (nonatomic,strong)NSArray *options;1617- (instancetype)initWithDict:(NSDictionary *)dict;1819+ (instancetype)appWithDict:(NSDictionary *)dict;20@end

KZAppModel.m

1//2//KZAppModel.m3//UI基础-04-05-164//5//Created by hukezhu on 15/5/16.6//7//89#import"KZAppModel.h"1011@implementationKZAppModel12-(instancetype)initWithDict:(NSDictionary *)dict{1314if(self =[super init]) {15self.answer = dict[@"answer"];16self.icon = dict[@"icon"];17self.title = dict[@"title"];18self.options = dict[@"options"];19}20returnself;21}2223+ (instancetype)appWithDict:(NSDictionary *)dict{2425return[[self alloc]initWithDict:dict];26}27@end

ViewController.m

1//2//ViewController.m3//01-超级猜图4//5//Created by hukezhu on 15/5/16.6// [注意]转载时请注明出处博客园-吃唐僧肉的小悟空http://www.cnblogs.com/hukezhu/7//89#import"ViewController.h"10#import"KZAppModel.h"1112@interfaceViewController ()13@property (nonatomic,assign)intindex;14@property (weak, nonatomic) IBOutlet UIButton *big;15@property (weak, nonatomic) IBOutlet UIButton *head;16@property (weak, nonatomic) IBOutlet UILabel *noLabel;17@property (weak, nonatomic) IBOutlet UILabel *titleLabel;18-(IBAction)nextClick;19@property (weak, nonatomic) IBOutlet UIView *answerView;20@property (weak, nonatomic) IBOutlet UIView *optionView;21@property (weak, nonatomic) IBOutlet UIButton *coinBtn;22-(IBAction)tipClick;2324-(IBAction)bigImg;25-(IBAction)headClick;2627@property (nonatomic,strong) UIButton *cover;28@property (nonatomic,strong)NSArray *questions;29@end3031@implementationViewController3233- (void)viewDidLoad {34[super viewDidLoad];35self.index = -1;36[self nextClick];3738}3940/**41* 懒记载42*/43-(IBAction)nextClick {44//判断当前索引,如果到达数据数组长度减145if(self.index == self.questions.count -1) {46UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示"message:@"已经到达最后一张图片"delegate:nil cancelButtonTitle:@"取消"otherButtonTitles:@"好的", nil];47[alert show];48return;49}5051self.index++;5253//创建一个模型,存储数据54KZAppModel *appModel =self.questions[self.index];5556//添加数据57[self addData:appModel];5859//添加答案按钮60[self addAnswerBtn:appModel];6162//添加待选项按钮63[self addOptionBtn:appModel];64}65666768/**69* 添加待选项按钮70*71* @param appModel 数据模型72*/73- (void)addOptionBtn:(KZAppModel *)appModel{7475//清除之前的待选项按钮76[self.optionView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];77//定义每行显示的待选项按钮的个数78inttotalCol =7;79CGFloat optionW =40;80CGFloat optionH =40;81CGFloat optionMargin =10;82//左边距83CGFloat leftOptionMargin = (self.optionView.frame.size.width - totalCol * optionW - (totalCol -1)*optionMargin)*0.5;84//遍历数组,创建待选项按钮(九宫格的创建方法)85for(inti =0; i < appModel.options.count; i++) {8687UIButton *optionBtn =[[UIButton alloc]init];88//行号89introw = i /totalCol;90//列号91intcol = i %totalCol;92CGFloat optionX = leftOptionMargin + col * (optionMargin +optionW);93CGFloat optionY = optionMargin + row * (optionMargin +optionH);94optionBtn.frame =CGRectMake(optionX, optionY, optionW, optionH);95//设置两种状态下的背景图片96[optionBtn setBackgroundImage:[UIImage imageNamed:@"btn_option"] forState:UIControlStateNormal];97[optionBtn setBackgroundImage:[UIImage imageNamed:@"btn_option_highlighted"] forState:UIControlStateHighlighted];98//给这些待选项按钮添加文字99[optionBtn setTitle:appModel.options[i] forState:UIControlStateNormal];100//设置字体颜色101[optionBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];102//将按钮添加到optionView中103[self.optionView addSubview:optionBtn];104105//创建待选项按钮的点击方法106[optionBtn addTarget:self action:@selector(optionClick:) forControlEvents:UIControlEventTouchUpInside];107108}109110}111112113/**114* 添加答案按钮115*116* @param appModel 模型数据117*/118- (void)addAnswerBtn:(KZAppModel *)appModel{119120//清除之前的答案按钮121[self.answerView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];122123124125CGFloat answerW =30;126CGFloat answerH =30;127CGFloat answerY =0;128CGFloat margin =10;129CGFloat leftMargin = (self.answerView.frame.size.width - appModel.answer.length *(margin + answerW))*0.5;130//循环遍历数组,创建答案按钮131for(inti =0; i < appModel.answer.length; i++){132133UIButton *answerBtn =[[UIButton alloc]init];134135CGFloat answerX =leftMargin + i *(margin +answerW);136answerBtn.frame =CGRectMake(answerX, answerY, answerW, answerH);137//设置背景图片138[answerBtn setBackgroundImage:[UIImage imageNamed:@"btn_answer"] forState:UIControlStateNormal];139140//设置显示文字的颜色141[answerBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];142[self.answerView addSubview:answerBtn];143144//创建点击按钮的点击响应方法145[answerBtn addTarget:self action:@selector(answerClick:) forControlEvents:UIControlEventTouchUpInside];146}147148}149150151152153/**154* 添加数据155*156* @param appModel 数据模型157*/158-(void)addData:(KZAppModel *)appModel{159160161162self.noLabel.text = [NSString stringWithFormat:@"%d/%ld",self.index +1,self.questions.count];163164self.titleLabel.text =appModel.title;165166[self.head setImage:[UIImage imageNamed:appModel.icon] forState:UIControlStateNormal];167}168169170- (void)optionClick:(UIButton *)optionBtn{171172//首先将被点击的待选项按钮的文字取到(后面会讲这个文字隐藏)173NSString *title =[optionBtn currentTitle];174optionBtn.hidden =YES;175176//循环遍历答案按钮,遇到第一个不为空的按钮,显示被点击的待选项按钮的文字177for(UIButton *answerBtninself.answerView.subviews) {178if([answerBtn currentTitle] ==nil ) {179[answerBtn setTitle:title forState:UIControlStateNormal];180

break;181}182}183184//判断答案是否为满,如果满了,就去判断对不对185//定义一个可变的字符串,用来拼接循环得到的答案,得到这个答案,去和正确答案比较186NSMutableString *tempString = [NSMutableStringstring];187BOOL full =YES;188189//遍历数组,如果遇到按钮为空的话,就赋值full标记为no,表明没有满,否则的话就去拼接190for(UIButton *answerBtninself.answerView.subviews) {191if([answerBtn currentTitle] ==nil ) {192full =NO;193}else{194195[tempString appendString:[answerBtn currentTitle]];196}197198}199if(full) {200201//NSLog(@"满了");202KZAppModel *appModel =self.questions[self.index];203for(UIButton *optionBtninself.optionView.subviews) {204optionBtn.enabled =NO;205}206207208if([tempString isEqualToString:appModel.answer]) {209NSLog(@"答对了");210for(UIButton *answerBtninself.answerView.subviews){211[answerBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];212213}214//int score = [self.coinBtn currentTitle].intValue ;215//score += 50;216//[self.coinBtn setTitle:[NSString stringWithFormat:@"%d",score] forState:UIControlStateNormal];217[self score:50];218219[self performSelector:@selector(nextClick) withObject:nil afterDelay:2.0];220221222223}else{224225NSLog(@"没答对");226for(UIButton *answerBtninself.answerView.subviews){227[answerBtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];228[self score:-200];229}230}231}232}233234/**235* 答案选线点击的方法236*237*/238- (void)answerClick:(UIButton *)answerBtn{239240//循环遍历待选项按钮,找到与答案相同的文字,删除答案文字,显示待选项文字241for(UIButton *optionBtninself.optionView.subviews) {242if([[optionBtn currentTitle] isEqualToString:[answerBtn currentTitle]] && optionBtn.hidden ==YES) {243[answerBtn setTitle:nil forState:UIControlStateNormal];244optionBtn.hidden =NO;245for(UIButton *optionBtninself.optionView.subviews) {246optionBtn.enabled =YES;247}248}249}250251for(UIButton *answerBtninself.answerView.subviews) {252[answerBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];253}254}255256257/**258* 点击提示的响应方法259*/260-(IBAction)tipClick {261//清除所有的答案按钮262for(UIButton *answerBtninself.answerView.subviews) {263[self answerClick:answerBtn];264}265//取出正确答案,显示出来266KZAppModel *appModel =self.questions[self.index];267NSString *str = [appModel.answer substringToIndex:1];268269270///**271//* 最开始想的是这种方法,但是发现更好的办法,,就相当于点击了对应的待选项按钮272//*/273//[self.answerView.subviews[0] setTitle:str forState:UIControlStateNormal];274//[self.answerView.subviews[0] setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];275276for(UIButton *optionBtninself.optionView.subviews) {277if([[optionBtn currentTitle] isEqualToString:str]) {278[self optionClick:optionBtn];279}280}281282[self score:-100];283284285}286287-(IBAction)bigImg {288//点击大图之后,先创建一个阴影(button),289UIButton *cover =[[UIButton alloc]init];290self.cover =cover;291cover.frame =self.view.bounds;292[cover setBackgroundColor:[UIColor blackColor]];293cover.alpha =0.0;294[self.view addSubview:cover];295//调整图片和阴影位置296[self.view bringSubviewToFront:self.head];297298[cover addTarget:self action:@selector(coverClick) forControlEvents:UIControlEventTouchUpInside];299[UIView animateWithDuration:2.0animations:^{300cover.alpha =0.6;301//放大图片302303CGFloat headW =self.view.frame.size.width;304CGFloat headH =headW;305CGFloat headX =0;306CGFloat headY =0.5* (self.view.frame.size.height-headH);307self.head.frame =CGRectMake(headX, headY, headW, headH);308309}];310311}312313314/**315* 计算分数方法316*317* @param score 传入需要增加或者减少的分数(减为负)318*/319- (void)score:(int)score{320321inttempScore =[self.coinBtn currentTitle].intValue ;322tempScore +=score;323[self.coinBtn setTitle:[NSString stringWithFormat:@"%d",tempScore] forState:UIControlStateNormal];324325}326327/**328* 图片放大状态下,点击阴影缩小图片329*/330-(void)coverClick{331332if(self.cover !=nil) {333[self smallImg];334335}336}337/**338* 点击头像图片,放大或缩小339*/340-(IBAction)headClick {341if(self.cover ==nil) {342[self bigImg];343}else{344345[self smallImg];346}347}348/**349* 缩小图片的方法350*/351- (void)smallImg{352353354[UIView animateWithDuration:2.0animations:^{355self.cover.alpha =0.0;356self.head.frame = CGRectMake(97,120,180,180);357self.cover =nil;358}];359360}361362363364/**365* 懒加载数据366*367* @return 返回数据368*/369-(NSArray *)questions{370371if(_questions ==nil){372NSString *path = [[NSBundle mainBundle]pathForResource:@"questions"ofType:@"plist"];373NSArray *dictArray =[NSArray arrayWithContentsOfFile:path];374NSMutableArray *tempArray =[NSMutableArray array];375for(NSDictionary *dictindictArray) {376KZAppModel *appModel =[KZAppModel appWithDict:dict];377[tempArray addObject:appModel];378}379_questions =tempArray;380381}382return_questions;383}384385@end

KVC大体介绍:

1KVC(Key Value Coding)2介绍: 通过给定一个对象的属性名称(以字符串方式), 然后找到对象的相应属性进行赋值。34*setValue:forKeyPath:5** 示例: [self setValue:dict[@"icon"] forKeyPath:@"icon"]6** 含义: 表示根据forKeyPath:@"icon"提供的@"icon"去self对象中查找名字叫icon的属性, 找到以后把dict[@"icon"]中获取到的值赋值给self的icon属性。789*setValuesForKyesWithDictionary:10**含义: 更简便的调用方式。内部相当于调用了多次setValue:forKeyPath:1112**注意:131>必须保证字典中的key与模型的属性名称一致。142>必须保证模型的属性个数与字典一致或者模型的属性个数要大于等于字典的个数。1516*演示KVC:171>新建一个model类。182>演示对字符串类型、数字类型进行KVC赋值193>通过KVC取值。20idv = [对象 valueForKeyPath:@"key"];21intv1 = [[对象 valueForKeyPath:@"key"] intValue];22234>把模型转成字典, 把对象中指定的属性转换为字典。24NSDictioanry *dict = [对象 dictionaryWithValuesForKeys:@[@"name",@"age"]];25265>把一个person数组中的每个person对象的name都获取出来然后放到一个新的数组中。27(28NSArray *names = [person数组 valueForKeyPath:@"name"];29)30316>keyPath介绍, 人拥有一本书, 通过kvc获取人所拥有的书的名称32(33NSString *bkName = [person valueForKeyPath:@"book.name"];3435等价于3637NSString *bkName =person.book.name;38)3940* KVO (Key Value Observing), 监听对象的属性值变化。

[注意]转载时请注明出处博客园-吃唐僧肉的小悟空http://www.cnblogs.com/hukezhu/

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航