【iOS開發-51】案例學習:動畫新寫法、刪除子視圖、視圖順序、延遲方法、button多功能使用方法及icon圖標和啟動頁設置
案例效果:
(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、推斷button是否失效 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{ //讓答案button文字相應的button顯示出來,用for遍歷 //獲取button文字用currentTitle // NSString *answerTitle=[answerBtn titleForState:UIControlStateNormal]; for (UIButton *optionBtn in self.optionView.subviews) { // NSString *optionTitle=[optionBtn titleForState:UIControlStateNormal]; //推斷哪個optionbutton再顯示出來。並且這個button本身是隱藏的,由於option裏可能有同樣的文字 if ([answerBtn.currentTitle isEqualToString:optionBtn.currentTitle] && optionBtn.hidden==YES) { optionBtn.hidden=NO; break; } } //點擊的button文字消失,由於這個文字上面須要用到比較,所以比較晚,再把文字去除 [answerBtn setTitle:nil forState:UIControlStateNormal]; //點擊隨意一個button。相當於去除文字,那麽答案就不是正確答案,文字顏色回復黑色 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]; //button點擊 [optionBtn addTarget:self action:@selector(optionClick:) forControlEvents:UIControlEventTouchUpInside]; } }
這個監聽事件方法:
-(void)optionClick:(UIButton *)optionBtn{ //1、被點擊的button消失 optionBtn.hidden=YES;//不能刪除,由於還要顯示,所以用隱藏 //2、顯示文字到正確答案上去(第一個沒有文字的answerbutton) //這裏設置完,無法查看效果,是由於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的遍歷 } } //每點擊一個optionbutton就推斷這個答案是否已經填滿,並推斷是否正確 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的button。就相當於清空 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)用到的知識點
——獲取button當前文字用.currentTitle屬性。
——實現動畫特效,除了[UIView beginAnimations:]這套組合外,推薦使用[UIView animateWithDuration: animations:^{ } completion:^(BOOL finished) { }];假設動畫完畢後沒有須要運行的代碼。那麽最後面的completion能夠去除。
——調整子視圖上下疊加順序能夠用bringSubviewToFront之類的方法。
——註意,button的文字默認是白色,假設背景也是白色,那麽須要格外註意。
——假設圖片的frame屬性設置沒有生效,即沒有變大縮小移動等特效。那麽通常是Auto Layout沒有關閉。
——button有一個默認屬性:按下時顏色變暗,假設不須要,則取消勾選“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屬性。
——註意代碼順序。比方用button上得文字和其它button上的文字相比較,然後在刪除這個button,這是正確順序,而不能先刪除,否則後面無法獲取到這個button上得文字。
——推斷button有沒有文字:推斷button文字的長度是否等於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。在上面加入個圖片就可以。
【iOS開發-51】案例學習:動畫新寫法、刪除子視圖、視圖順序、延遲方法、button多功能使用方法及icon圖標和啟動頁設置