• 【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。在上面加入个图片就可以。


  • 相关阅读:
    Jmeter请求头中添加了Authorization,但是在结果树里面的headers中显示没有获取到token
    linux(1):VMware虚拟软件下安装centos6.8
    Appium+python自动化环境搭建(小白适用)
    面试题:get和post的本质区别
    用python实现不同格式99乘法表输出
    冒泡排序:从数学逻辑到代码呈现
    给你一句话的需求,如何拆分测试点来设计测试案例
    Linux下基于Xampp的TestLink的安装部署
    linux环境下完成jenkins的环境搭建
    工作中遇到的小问题总结
  • 原文地址:https://www.cnblogs.com/lxjshuju/p/6846901.html
Copyright © 2020-2023  润新知