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

【iOS开发-51】案例学习:动画新写法、删除子视图、视图顺序、延迟方法、按钮多功能用法及icon图标和启动页设置

2014-10-16 16:59 766 查看
案例效果:



(1)导入所需的素材,然后用storyboard把上半截位置和大小相对固定的东西布局起来。当然,这些控件也要定义成相应地IBOutlet和IBAction方便后续使用它们。

注意:本案例在3.5inch设备上显示最佳,所以需要设置一下。



(2)首先实现点击“下一题”的功能

- (IBAction)nextQuestion {
//1、序号增加
self.index++;
//2、根据序号拿到对应的模型(对象)
NSQuestion *question=self.questions[self.index];
//3、设置文本以及图像
self.noLabel.text=[NSString stringWithFormat:@"%d/%d",self.index+1,self.questions.count];
self.titleLabel.text=question.title;
[self.iconBtn setImage:[UIImage imageNamed:question.icon] forState:UIControlStateNormal];
//4、判断按钮是否失效
self.nextQuestionBtn.enabled=self.index!=(self.questions.count-1);
//5、添加正确答案
[self addAnswerBtn:question];
//6、添加option选项
[self addOptionBtn:question];
}

当然,在viewLoad中要让视图显示第一个页面,需要如下:
- (void)viewDidLoad {
self.index=-1;
[self nextQuestion];
[super viewDidLoad];
}

然后一个个实现nextQuestion方法中提到的那些方法。
(3)定义一个数据模型类,就是将字典转化成模型

在NSQuestion.h中:

#import <Foundation/Foundation.h>

@interface NSQuestion : NSObject
@property(nonatomic,copy) NSString *answer;
@property(nonatomic,copy) NSString *title;
@property(nonatomic,copy) NSString *icon;
@property(nonatomic,strong) NSArray *options;

-(instancetype)initWithDic:(NSDictionary *)dict;
+(instancetype)questionWithDic:(NSDictionary *)dict;
@end

在NSQuestion.m中:
#import "NSQuestion.h"

@implementation NSQuestion

-(instancetype)initWithDic:(NSDictionary *)dict{
if ([super init]) {
self.answer=dict[@"answer"];
self.title=dict[@"title"];
self.icon=dict[@"icon"];
self.options=dict[@"options"];
}
return self;
}

+(instancetype)questionWithDic:(NSDictionary *)dict{
return [[self alloc]initWithDic:dict];
}

@end

在ViewController.m中转化成模型:

#import "ViewController.h"
#import "NSQuestion.h"

@interface ViewController ()
@property(nonatomic,strong) NSArray *questions;
@end

@implementation ViewController

-(NSArray *)questions{
if (_questions==nil) {
NSArray *arr1=[NSArray arrayWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"questions.plist" ofType:nil]];
NSMutableArray *questionArray=[[NSMutableArray alloc]init];
for (NSDictionary *dic1 in arr1) {
NSQuestion *question=[[NSQuestion alloc]initWithDic:dic1];
[questionArray addObject:question];
}
_questions=questionArray;
}
return _questions;
}

(4)addAnswerBtn方法
-(void)addAnswerBtn:(NSQuestion *)question{
//5、添加正确答案
//先删除上一题的answer
//让数组中的所有对象都执行同样地方法,用下面这一句代替下面的for循环
[self.answerView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
// for (UIView *subViews in self.answerView.subviews) {
// [subViews removeFromSuperview];
// }
//然后再添加新的answer,根据答案的长度来添加
int 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];
CGFloat answerMargin=10;
CGFloat answerW=35;
CGFloat answerH=35;
CGFloat answerX=(self.view.frame.size.width-length*answerW-(length-1)*answerMargin)/2+i*(answerW+answerMargin);
answerBtn.frame=CGRectMake(answerX, 0, answerW, answerH);
[self.answerView addSubview:answerBtn];

//监听点击事件
[answerBtn addTarget:self action:@selector(answerClick:) forControlEvents:UIControlEventTouchUpInside];
}
}

这个点击事件的方法:
-(void)answerClick:(UIButton *)answerBtn{
//让答案按钮文字对应的按钮显示出来,用for遍历
//获取按钮文字用currentTitle
// NSString *answerTitle=[answerBtn titleForState:UIControlStateNormal];
for (UIButton *optionBtn in self.optionView.subviews) {
// NSString *optionTitle=[optionBtn titleForState:UIControlStateNormal];
//判断哪个option按钮再显示出来,而且这个按钮本身是隐藏的,因为option里可能有相同的文字
if ([answerBtn.currentTitle isEqualToString:optionBtn.currentTitle] && optionBtn.hidden==YES) {
optionBtn.hidden=NO;
break;
}
}
//点击的按钮文字消失,因为这个文字上面需要用到比较,所以比较晚,再把文字去除
[answerBtn setTitle:nil forState:UIControlStateNormal];

//点击任意一个按钮,相当于去除文字,那么答案就不是正确答案,文字颜色回复黑色
for (UIButton *answerBtn in self.answerView.subviews) {
[answerBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
}
}

(4)addOptionBtn方法
-(void)addOptionBtn:(NSQuestion *)question{
//6、添加option选项
//也是先删除再添加,同样用一句代替for循环
[self.optionView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
// for (UIView *subViews in self.optionView.subviews) {
// [subViews removeFromSuperview];
// }
int count=question.options.count;
int totalColumn=7;
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];
CGFloat optionMargin=10;
CGFloat optionW=35;
CGFloat optionH=35;
int row=i/7;
int col=i%7;
CGFloat optionX=(self.view.frame.size.width-totalColumn*optionW-(totalColumn-1)*optionMargin)/2+col*(optionW+optionMargin);
CGFloat optionY=row*(optionH+optionMargin);
optionBtn.frame=CGRectMake(optionX, optionY, optionW, optionH);
[optionBtn setTitle:question.options[i] forState:UIControlStateNormal];
[optionBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[self.optionView addSubview:optionBtn];

//按钮点击
[optionBtn addTarget:self action:@selector(optionClick:) forControlEvents:UIControlEventTouchUpInside];
}
}

这个监听事件方法:
-(void)optionClick:(UIButton *)optionBtn{
//1、被点击的按钮消失
optionBtn.hidden=YES;//不能删除,因为还要显示,所以用隐藏
//2、显示文字到正确答案上去(第一个没有文字的answer按钮)
//这里设置完,无法查看效果,是因为answer的文字默认是白色,于背景相同
for (UIButton *answerBtn in self.answerView.subviews) {
//判断是否有文字
// NSString *answerTitle=[answerBtn titleForState:UIControlStateNormal];
if (answerBtn.currentTitle.length==0) {
[answerBtn setTitle:[optionBtn titleForState:UIControlStateNormal] forState:UIControlStateNormal];
break;//找到后就通知for的遍历
}
}
//每点击一个option按钮就判断这个答案是否已经填满,并判断是否正确
BOOL full=YES;
NSMutableString *tempAnswerTitle=[NSMutableString string];
for (UIButton *answerBtn in self.answerView.subviews){
// NSString *answerTitle=[answerBtn titleForState:UIControlStateNormal];
if (answerBtn.currentTitle.length==0) {//说明答案没有满
full=NO;
}
//拼接文字
if (answerBtn.currentTitle) {
[tempAnswerTitle appendString:answerBtn.currentTitle];
}
}
//如果答案满了,则判断是否正确
if (full) {
NSQuestion *question=self.questions[self.index];
if ([tempAnswerTitle isEqualToString:question.answer]) {
for (UIButton *answerBtn in self.answerView.subviews) {
[answerBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
}
//判断正确后
//先拿到当前分,再加分
[self addScore:100];
// int score=[self.scoreBtn titleForState:UIControlStateNormal].intValue;
// score+=100;
// [self.scoreBtn setTitle:[NSString stringWithFormat:@"%d",score] forState:UIControlStateNormal];
//延迟执行:跳到下一题
//直接用[self nextQuestion];会立即跳转
[self performSelector:@selector(nextQuestion) withObject:nil afterDelay:0.5];
}else{
for (UIButton *answerBtn in self.answerView.subviews) {
[answerBtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
}
}
}
}

这里面用到一个addScore计算分数的方法:
-(void)addScore:(int)dealtScore{
int score=[self.scoreBtn titleForState:UIControlStateNormal].intValue;
score+=dealtScore;
[self.scoreBtn setTitle:[NSString stringWithFormat:@"%d",score] forState:UIControlStateNormal];
}

(5)相应的,点击“提示”产生的效果,是清空answer,给第一个字,并扣分
- (IBAction)tip {
//1、先清空answer,也就是点击answer的按钮,就相当于清空
for (UIButton *answerBtn in self.answerView.subviews) {
[self answerClick:answerBtn];
}
//2、取出正确答案
NSQuestion *question=self.questions[self.index];
//3、取出正确答案的第一个字符
NSString *firstAnswer=[question.answer substringToIndex:1];
//4、判断并从option中取出
for (UIButton *optionBtn in self.optionView.subviews) {
if ([optionBtn.currentTitle isEqualToString:firstAnswer]) {
[self optionClick:optionBtn];
break;
}
}
//5、扣分
[self addScore:-500];
// int score=[self.scoreBtn titleForState:UIControlStateNormal].intValue;
// score-=500;
// [self.scoreBtn setTitle:[NSString stringWithFormat:@"%d",score] forState:UIControlStateNormal];
}

(6)点击“大图”的效果,添加一个阴影,调整图像顺序,并让图片和阴影等动画变动
- (IBAction)bigImg {

//1、添加一个半透明阴影
UIButton *cover=[[UIButton alloc]init];
cover.frame=self.view.bounds;
cover.backgroundColor=[UIColor blackColor];
cover.alpha=0;
[cover addTarget:self action:@selector(smallImg) forControlEvents:UIControlEventTouchUpInside];
self.cover=cover;
[self.view addSubview:cover];

//2、调整阴影和图像顺序
[self.view bringSubviewToFront:self.iconBtn];

//同样,用block改造下面的代码
[UIView animateWithDuration:0.5 animations:^{
cover.alpha=0.7;//阴影逐步出现
//3、改变图像大小frame
CGFloat iconW=self.view.frame.size.width;
CGFloat iconH=iconW;
CGFloat iconY=(self.view.frame.size.height-iconH)/2;
self.iconBtn.frame=CGRectMake(0, iconY, iconW, iconH);
}];

// [UIView beginAnimations:nil context:nil];
// cover.alpha=0.7;//阴影逐步出现
// //3、改变图像大小frame
// CGFloat iconW=self.view.frame.size.width;
// CGFloat iconH=iconW;
// CGFloat iconY=(self.view.frame.size.height-iconH)/2;
// self.iconBtn.frame=CGRectMake(0, iconY, iconW, iconH);
// [UIView commitAnimations];
}

上述代码中得阴影cover有一个事件,就是点击后图片恢复小图,并且阴影消失等等,如下:
-(void)smallImg{
//用block动画改造下面代码以及removeCover方法
[UIView animateWithDuration:0.5 animations:^{
self.cover.alpha=0;//先让阴影逐渐消失,然后删除
self.iconBtn.frame=CGRectMake(85, 86, 150, 150);
} completion:^(BOOL finished) {
[self.cover removeFromSuperview];
self.cover=nil;//便于判断阴影是否还存在
}];

// //1、删除阴影
//
// //2、图像位置恢复frame
// [UIView beginAnimations:nil context:nil];
// //动画结束后,调用self的removeCover方法删除阴影,这样删除阴影才会有个延迟,阴影逐渐消失的动画才能正常
// [UIView setAnimationDelegate:self];
// [UIView setAnimationDidStopSelector:@selector(removeCover)];
// self.cover.alpha=0;//先让阴影逐渐消失,然后删除
// self.iconBtn.frame=CGRectMake(85, 86, 150, 150);//也可以在变大之前记录原有位置
// [UIView commitAnimations];
}

//-(void)removeCover{
// [self.cover removeFromSuperview];
// self.cover=nil;//便于判断阴影是否还存在
//}

(7)而点击图片本身,也会有放大缩小的事件:
- (IBAction)iconClick {
if (self.cover==nil) {
[self bigImg];
}else{
[self smallImg];
}
}

(8)用到的知识点
——获取按钮当前文字用.currentTitle属性。

——实现动画特效,除了[UIView beginAnimations:]这套组合外,推荐使用[UIView animateWithDuration: animations:^{ } completion:^(BOOL finished) { }];如果动画完成后没有需要执行的代码,那么最后面的completion可以去除。

——调整子视图上下叠加顺序可以用bringSubviewToFront之类的方法。

——注意,按钮的文字默认是白色,如果背景也是白色,那么需要格外注意。

——如果图片的frame属性设置没有生效,即没有变大缩小移动等特效,那么一般是Auto Layout没有关闭。

——按钮有一个默认属性:按下时颜色变暗,如果不需要,则取消勾选“Highlighted Adjusts Image”。

——截取某字符串的前某几个字符则用substringToIndex,数字是N,则是0~n-1这几个字符。

——实现透明度,是属性alpha。

——一般要删除某个控件,则需要这个控件自身调用removeFromSuperview方法。但如果要删除某个视图里面的很多子视图,除了用for循环让子视图一个个自己自删,还可以用如下方法:makeObjectsPerformSelector,

[self.answerView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
// for (UIView *subViews in self.answerView.subviews) {
// [subViews removeFromSuperview];
// }——一般我们如果删除某个控件,在删除后,把这个控件设置为nil。而不想删除,只是隐藏,后面还需要再显示,则用控件的hidden属性。
——注意代码顺序。比如用按钮上得文字和其他按钮上的文字相比较,然后在删除这个按钮,这是正确顺序,而不能先删除,否则后面无法获取到这个按钮上得文字。

——判断按钮有没有文字:判断按钮文字的长度是否等于0。

——可变字符串的添加用appendString方法。

——延迟执行某个动作可以用performSelector:@selector() withObject:nil afterDelay:这个方法。如果是[self perform...]那么就是延迟执行self的selector里的方法。

——把一个字符串转换成整型,可以直接在这个字符串后面增加.intValue属性。

(9)如何添加icon图标(iPhone的、AppStore以及spotlight的,当然后续还有ipad的等等)

直接按要求定义好图片大小和命名规范,然后拖到Image.xcassets的AppIcon里即可。

(10)如何添加启动页面?

直接在LaunchScreen.xib里面设置,这个和玩storyboard一样样的。

我们此处设置的大小是3.5inch的,所以设置好设备尺寸后,把原先的删除掉,直接弄一个imageView,在上面添加个图片即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐