1. 程式人生 > >【iOS開發-51】案例學習:動畫新寫法、刪除子視圖、視圖順序、延遲方法、button多功能使用方法及icon圖標和啟動頁設置

【iOS開發-51】案例學習:動畫新寫法、刪除子視圖、視圖順序、延遲方法、button多功能使用方法及icon圖標和啟動頁設置

無法查看 font targe 技術 value lstat tostring sta dict

案例效果:

技術分享


(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圖標和啟動頁設置