• iOS自定义控件


    这里做一个类似于下面界面的小案例

    1.创建一个空的布局文件 .xib

    1 new File -->User Interface -->选择View
    2 创建一个空的view ,会自动生成一个 .xib的文件

    2.设置我们自己需要经常复用的界面

       注意:记得设置"Custom Class"中的 Class属性 与我们的代码文件 .h .m (Cocoa Touch Class文件 )相关联

    3.创建我们的Cocoa文件(Cocoa Touch Class文件)

      继承 <UIKit/UIKit.h> 包种的 UIView类

    .h文件

    复制代码
     1 #import <UIKit/UIKit.h>
     2 @class CZApp;
     3 
     4 
     5 @interface CZAppView : UIView
     6 
     7 @property (nonatomic,strong) CZApp *model;
     8 
     9 //为自定义view封装一个类方法,这个类方法的作用就是创建一个view对象
    10 +(instancetype) appView;
    11 
    12 @end
    复制代码

    .m文件

    复制代码
     1 #import "CZAppView.h"
     2 #import "CZApp.h"
     3 @interface CZAppView()
     4 @property (weak, nonatomic) IBOutlet UIImageView *imgViewIcon;
     5 @property (weak, nonatomic) IBOutlet UILabel *lblName;
     6 @property (weak, nonatomic) IBOutlet UIButton *btnDownload;
     7 - (IBAction)btnDownloadClick:(UIButton *)sender;
     8 
     9 @end
    10 @implementation CZAppView
    11 +(instancetype) appView{
    12     //1.通过xib创建每一个应用(UIView)
    13     //通过动态加载xib文件创建里面的view
    14     //1.1>找到应用的根目录
    15     NSBundle *rootBundle =[NSBundle mainBundle];//NSLog(@"%@",[mainBundle bundlePath]);
    16     //1.2>在应用程序根目录下取搜索对应的Xib(nib)文件
    17     return [[rootBundle loadNibNamed:@"CZAppView" owner:nil options:nil]lastObject];
    18 }
    19 //重写model属性的set方法
    20 -(void)setModel:(CZApp *)model{
    21     //先赋值
    22     _model = model;
    23     
    24     //解析模型数据,把模型数据赋值给UIView中的各个子控件
    25     self.imgViewIcon.image = [UIImage imageNamed:model.icon];
    26     self.lblName.text=model.name;
    27 }
    28 //下载按钮的单击事件
    29 - (IBAction)btnDownloadClick:(UIButton *)sender {
    30     //1.禁用当前被点击的按钮
    31     sender.enabled = NO;
    32     
    33     //2.弹出一个消息提醒框(这个消息提醒框其实就是一个UILable)
    34     UILabel *lblMsg = [[UILabel alloc]init];
    35     //2.1 设置lblMsg的显示文字
    36     lblMsg.text=@"正在下载....";
    37     //2.2 设置lblMsg的背景色
    38     lblMsg.backgroundColor = [UIColor blackColor];
    39     //2.3设置lblMsg的frame
    40     CGFloat viewW = self.superview.frame.size.width;
    41     CGFloat viewH = self.superview.frame.size.height;
    42     CGFloat msgW = 200;
    43     CGFloat msgH = 30;
    44     CGFloat msgX= (viewW -msgW)/2;
    45     CGFloat msgY = (viewH - msgH)*0.5;
    46     lblMsg.frame=CGRectMake(msgX, msgY, msgW, msgH);
    47     //2.4设置label的文字颜色
    48     lblMsg.textColor = [UIColor redColor];
    49     //2.5设置label居中显示
    50     lblMsg.textAlignment = NSTextAlignmentCenter;
    51     //2.6设置文字粗体
    52     lblMsg.font = [UIFont boldSystemFontOfSize:17];
    53     //2.7设置label的透明度
    54     lblMsg.alpha = 0.0;//一开始把透明度设置为0 ,然后通过动画的方式慢慢的改变透明度
    55     //2.8 设置Label为"圆角"
    56     //设置四个角的"半径"
    57     lblMsg.layer.cornerRadius =10;
    58     //把多余的部分裁剪掉
    59     lblMsg.layer.masksToBounds =YES;
    60     //2.9通过动画的方式来显示Label
    61 //    [UIView animateWithDuration:2.0 animations:^{
    62 //        lblMsg.alpha =0.6;
    63 //    }];
    64     
    65     //开启一个动画,这个动画要执行1.5秒
    66     [UIView animateWithDuration:1.5 animations:^{
    67         //动画代码:将透明度变为0.6
    68         lblMsg.alpha = 0.6;
    69     } completion:^(BOOL finished) {
    70         if(finished)
    71         {
    72             //这个代码的含义是,隔一段时间后再启动另外一个动画
    73             //这个动画的执行时间是1.5秒,但是这个动画会在1.0秒之后再开始执行
    74             //UIViewAnimationOptionCurveLinear表示是均速执行动画
    75             [UIView animateWithDuration:1.5 delay:1.0 options:UIViewAnimationOptionCurveLinear animations:^{
    76                 //这个动画的代码
    77                 lblMsg.alpha = 0;
    78             } completion:^(BOOL finished) {
    79                 if(finished){
    80                     //当Label的透明度变为0以后,再把这个Label从view中移除
    81                     [lblMsg removeFromSuperview];
    82                 }
    83             }];
    84         }
    85     }];
    86     //3.把lblMsg加到控制器所管理的那个view上
    87     [self.superview addSubview:lblMsg];
    88     
    89 }
    90 @end
    复制代码

    这样我们的自定义控件就算完成了,接下来要做得就是引用我们自己所做的界面

    4.由于我们加载的图片和名称都是来源 .plist文件

       所以我们设置一个"模型" 来导入.plist文件

    .h文件

    复制代码
    1 #import <Foundation/Foundation.h>
    2 
    3 @interface CZApp : NSObject
    4 @property(nonatomic,copy) NSString *name;
    5 @property(nonatomic,copy) NSString *icon;
    6 
    7 -(instancetype)initWithDict:(NSDictionary *)dict;
    8 +(instancetype)appWithDict:(NSDictionary *)dict;
    9 @end
    复制代码

    .m文件

    复制代码
     1 #import "CZApp.h"
     2 
     3 @implementation CZApp
     4 -(instancetype)initWithDict:(NSDictionary *)dict{
     5     if(self=[super init]){
     6         self.name=dict[@"name"];
     7         self.icon=dict[@"icon"];
     8     }
     9     return self;
    10 }
    11 +(instancetype)appWithDict:(NSDictionary *)dict{
    12     return [[self alloc]initWithDict:dict];
    13 }
    14 @end
    复制代码

    5.接下来我们就在控制器ViewController中开始使用我们自定义的控件

    复制代码
     1 #import "ViewController.h"
     2 #import "CZApp.h"
     3 #import "CZAppView.h"
     4 
     5 @interface ViewController ()
     6 
     7 //用来保存所有应用的数据
     8 @property(nonatomic,strong)NSArray *apps;
     9 
    10 @end
    11 
    12 @implementation ViewController
    13 
    14 //重写apps属性的get方法,进行懒加载数据
    15 -(NSArray *)apps{
    16     if(_apps == nil){
    17         //加载数据
    18         //1.获取app.plist文件在手机上的路径
    19         NSString *path = [[NSBundle mainBundle]pathForResource:@"app.plist" ofType:nil];
    20         
    21         //2.根据路径加载数据
    22         NSArray *arrayDict = [NSArray arrayWithContentsOfFile:path];
    23         
    24         //3.创建一个可变数据用来保存一个一个的模型对象
    25         NSMutableArray *arrayModels = [NSMutableArray array]; //一个空的可变数组
    26         
    27         //4.循环字典数组,把每个字典对象转换成一个模型对象
    28         for(NSDictionary *dict in arrayDict){
    29             //创建一个模型
    30             CZApp *model = [CZApp appWithDict:dict];
    31             
    32             //把模型加到arrayModels中
    33             [arrayModels addObject:model];
    34         }
    35         _apps = arrayModels;
    36     }
    37     return _apps;
    38 }
    39 
    40 - (void)viewDidLoad {
    41     [super viewDidLoad];
    42     
    43     //假设每行的应用的个数
    44     int columns = 3;
    45     
    46     //获取控制器所管理的view的宽度
    47     CGFloat viewWidth = self.view.frame.size.width;
    48     
    49     //每个应用的宽和高
    50     CGFloat appW = 75;
    51     CGFloat appH = 90;
    52     CGFloat marginTop =30;//第一行距离顶部的距离
    53     CGFloat marginX = (viewWidth - columns *appW)/(columns+1);
    54     CGFloat marginY = marginX;//假设每行之间的间距与marginX相等
    55     
    56     for(int i=0;i<self.apps.count;i++){
    57         //获取当前这个应用的数据字典
    58         CZApp *appModel = self.apps[i];
    59         
    60         //创建view
    61         CZAppView *appView = [CZAppView appView];
    62         
    63         //2.2 设置appView 的fram属性
    64         //计算每个单元格所在的列的索引
    65         int colIdx = i%columns;
    66         //计算每个单元格的行索引
    67         int rowIdx = i/columns;
    68         
    69         CGFloat appX = marginX + colIdx *(appW +marginX);
    70         CGFloat appY = marginTop + rowIdx *(appH + marginY);
    71         appView.frame = CGRectMake(appX, appY, appW, appH);
    72         
    73         //3.将appView加到self.view(控制器所管理的那个view)
    74         [self.view addSubview:appView];
    75         
    76         //设置数据
    77         //把模型数据设置给"自定义view"的model属性
    78         //然后重写model属性的set方法,在set方法中解析模型对象中的属性,并把属性值设置给自定义view的各个子控件
    79         appView.model = appModel;
    80         
    81         
    82     }
    83     
    84     
    85 }
    86 
    87 - (void)didReceiveMemoryWarning {
    88     [super didReceiveMemoryWarning];
    89     // Dispose of any resources that can be recreated.
    90 }
    91 
    92 @end
    复制代码

    再制作一个自动猜图的小案例

    这里主要的是动态生成按钮,以及修改launchScreen的启动界面

    效果图:

    1.修改启动的launchscreen 以及应用小图标icon

    简单来说只需要把我们制作的界面放入Images.xcassets中覆盖原来系统的LaunchImage和AppIcon就可以

    主要注意的是关于尺寸的选择:

    然后修改项目General中的APP Icons and Launch Image

    1.先创建模型用于导入 .plist数据

    .h

    复制代码
     1 #import <Foundation/Foundation.h>
     2 
     3 @interface CZQuestion : NSObject
     4 
     5 @property (nonatomic, copy) NSString *answer;
     6 @property (nonatomic, copy) NSString *icon;
     7 @property (nonatomic, copy) NSString *title;
     8 @property (nonatomic, strong) NSArray *options;
     9 
    10 
    11 - (instancetype)initWithDict:(NSDictionary *)dict;
    12 + (instancetype)questionWithDict:(NSDictionary *)dict;
    13 
    14 
    15 @end
    复制代码

    .m

    复制代码
     1 #import "CZQuestion.h"
     2 
     3 @implementation CZQuestion
     4 
     5 - (instancetype)initWithDict:(NSDictionary *)dict
     6 {
     7     if (self = [super init]) {
     8         self.answer = dict[@"answer"];
     9         self.title = dict[@"title"];
    10         self.icon = dict[@"icon"];
    11         self.options = dict[@"options"];
    12     }
    13     return self;
    14 }
    15 
    16 + (instancetype)questionWithDict:(NSDictionary *)dict
    17 {
    18     return  [[self alloc]initWithDict:dict];
    19 }
    20 @end
    复制代码

    2.控制器ViewController.m

    复制代码
      1 #import "ViewController.h"
      2 #import "CZQuestion.h"
      3 
      4 
      5 @interface ViewController () <UIAlertViewDelegate>
      6 
      7 // 所有问题的数据都在这个数组中
      8 @property (nonatomic, strong) NSArray *questions;
      9 
     10 // 控制题目索引, 类型的int类型属性, 默认没有赋值一开始就是0
     11 @property (nonatomic, assign) int index;
     12 
     13 // 记录头像按钮原始的frame
     14 @property (nonatomic, assign) CGRect iconFrame;
     15 
     16 
     17 @property (weak, nonatomic) IBOutlet UILabel *lblIndex;
     18 @property (weak, nonatomic) IBOutlet UIButton *btnScore;
     19 @property (weak, nonatomic) IBOutlet UILabel *lblTitle;
     20 @property (weak, nonatomic) IBOutlet UIButton *btnIcon;
     21 @property (weak, nonatomic) IBOutlet UIButton *btnNext;
     22 @property (weak, nonatomic) IBOutlet UIView *answerView;
     23 @property (weak, nonatomic) IBOutlet UIView *optionsView;
     24 
     25 
     26 
     27 // 用来引用那个“阴影”按钮的属性
     28 @property (weak, nonatomic) UIButton *cover;
     29 
     30 - (IBAction)btnNextClick;
     31 
     32 - (IBAction)bigImage:(id)sender;
     33 
     34 // 头像按钮的单击事件
     35 - (IBAction)btnIconClick:(id)sender;
     36 
     37 // 提示
     38 - (IBAction)btnTipClick;
     39 
     40 
     41 @end
     42 
     43 @implementation ViewController
     44 
     45 
     46 // 懒加载数据
     47 - (NSArray *)questions
     48 {
     49     if (_questions == nil) {
     50         // 加载数据
     51         NSString *path = [[NSBundle mainBundle] pathForResource:@"questions.plist" ofType:nil];
     52         NSArray *arrayDict = [NSArray arrayWithContentsOfFile:path];
     53         NSMutableArray *arrayModel = [NSMutableArray array];
     54         
     55         // 遍历把字典转模型
     56         for (NSDictionary *dict in arrayDict) {
     57             CZQuestion *model = [CZQuestion questionWithDict:dict];
     58             [arrayModel addObject:model];
     59         }
     60         _questions = arrayModel;
     61     }
     62     return _questions;
     63 }
     64 
     65 
     66 // 改变状态栏的文字颜色为白色
     67 - (UIStatusBarStyle)preferredStatusBarStyle
     68 {
     69     return UIStatusBarStyleLightContent;
     70 }
     71 
     72 // 隐藏状态栏
     73 - (BOOL)prefersStatusBarHidden
     74 {
     75     return YES;
     76 }
     77 
     78 
     79 - (void)viewDidLoad {
     80     [super viewDidLoad];
     81     
     82     
     83     // 初始化显示第一题
     84     self.index = -1;
     85     [self nextQuestion];
     86     
     87 }
     88 
     89 - (void)didReceiveMemoryWarning {
     90     [super didReceiveMemoryWarning];
     91     // Dispose of any resources that can be recreated.
     92 }
     93 
     94 // 点击下一题
     95 - (IBAction)btnNextClick {
     96    
     97     // 移动到下一题
     98     [self nextQuestion];
     99 }
    100 
    101 // 显示大图
    102 - (IBAction)bigImage:(id)sender {
    103     
    104     // 记录一下头像按钮的原始frame
    105     self.iconFrame = self.btnIcon.frame;
    106     
    107     // 1.创建大小与self.view一样的按钮, 把这个按钮作为一个"阴影"
    108     UIButton *btnCover = [[UIButton alloc] init];
    109     // 设置按钮大小
    110     btnCover.frame = self.view.bounds;
    111     // 设置按钮背景色
    112     btnCover.backgroundColor = [UIColor blackColor];
    113     // 设置按钮透明度
    114     btnCover.alpha = 0.0;
    115     
    116     // 把按钮加到self.view中
    117     [self.view addSubview:btnCover];
    118     
    119     // 为阴影按钮注册一个单击事件
    120     [btnCover addTarget:self action:@selector(samllImage) forControlEvents:UIControlEventTouchUpInside];
    121     
    122     
    123     // 2. 把图片设置到阴影的上面
    124     // 把self.view中的所有子控件中, 只把self.btnIcon显示到最上层
    125     [self.view bringSubviewToFront:self.btnIcon];
    126     
    127     // 通过self.cover来引用btnCover
    128     self.cover = btnCover;
    129     
    130     
    131     // 3. 通过动画的方式把图片变大
    132     CGFloat iconW = self.view.frame.size.width;
    133     CGFloat iconH = iconW;
    134     CGFloat iconX = 0;
    135     CGFloat iconY = (self.view.frame.size.height - iconH) * 0.5;
    136     
    137     [UIView animateWithDuration:0.7 animations:^{
    138         // 设置按钮透明度
    139         btnCover.alpha = 0.6;
    140 
    141         // 设置图片的新的frame
    142         self.btnIcon.frame = CGRectMake(iconX, iconY, iconW, iconH);
    143     }];
    144 }
    145 
    146 // 头像按钮的单击事件
    147 - (IBAction)btnIconClick:(id)sender {
    148     if (self.cover == nil) {
    149         // 显示大图
    150         [self bigImage:nil];
    151     } else {
    152         [self samllImage];
    153     }
    154 }
    155 
    156 // 点击"提示"按钮
    157 - (IBAction)btnTipClick {
    158     // 1. 分数-1000
    159     [self addScore:-1000];
    160     
    161     
    162     // 2. 把所有的答案按钮"清空"(其实这里的"清空"最好是调用每个答案按钮的单击事件)
    163     for (UIButton *btnAnswer in self.answerView.subviews) {
    164         // 让每个答案按钮点击一下
    165         [self btnAnswerClick:btnAnswer];
    166     }
    167     
    168     // 3. 根据当前的索引, 从数据数组中(self.questions)中找到对应的数据模型
    169     // 从数据模型中获取正确答案的第一个字符, 把待选按钮中和这个字符相等的那个按钮点击一下
    170     CZQuestion *model = self.questions[self.index];
    171     //截取正确答案中的第一个字符"字符串"
    172     NSString *firstChar = [model.answer substringToIndex:1];
    173     
    174     // 根据firstChar在option按钮中找到对应的option 按钮, 让这个按钮点击一下
    175     for (UIButton *btnOpt in self.optionsView.subviews) {
    176         if ([btnOpt.currentTitle isEqualToString:firstChar]) {
    177             [self optionButtonClick:btnOpt]; // 设置某个option 按钮点击一下
    178             break;
    179         }
    180     }
    181 }
    182 
    183 
    184 // "阴影"的单击事件
    185 - (void)samllImage
    186 {
    187     [UIView animateWithDuration:0.7 animations:^{
    188         // 1. 设置btnIcon(头像)按钮的frame还原
    189         self.btnIcon.frame = self.iconFrame;
    190         // 2. 让"阴影"按钮的透明度变成0
    191         self.cover.alpha = 0.0;
    192     } completion:^(BOOL finished) {
    193         if (finished) {
    194             // 移出"阴影"按钮
    195             [self.cover removeFromSuperview];
    196             // 当头像图片变成小图以后, 再把self.cover设置成nil
    197             self.cover = nil;
    198         }
    199     }];
    200 }
    201 
    202 
    203 // 实现UIAlertView的代理方法
    204 - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
    205 {
    206    // NSLog(@"%ld", buttonIndex);
    207     if (buttonIndex == 0) {
    208         // 让程序在回到第0个问题
    209         self.index = -1;
    210         [self nextQuestion];
    211     }
    212 }
    213 
    214 
    215 
    216 // 下一题
    217 - (void)nextQuestion
    218 {
    219     // 1. 让索引++
    220     self.index++;
    221     
    222     // 判断当前索引是否越界, 入股索引越界, 则提示用户
    223     if (self.index == self.questions.count) {
    224         //NSLog(@"答题完毕!!!!");
    225         
    226         // 弹出一个对话框
    227         UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"操作提示" message:@"恭喜通关!" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil];
    228         
    229         // 显示对话框
    230         [alertView show];
    231         return;
    232     }
    233     
    234     
    235     // 2. 根据索引获取当前的模型数据
    236     CZQuestion *model = self.questions[self.index];
    237     
    238     
    239     
    240     // 3. 根据模型设置数据
    241     [self settingData:model];
    242     
    243     
    244     // 4. 动态创建"答案按钮"
    245     [self makeAnswerButtons:model];
    246     
    247     
    248     // 5. 动态创建"待选按钮"
    249     [self makeOptionsButton:model];
    250     
    251     
    252 }
    253 
    254 
    255 // 创建待选按钮
    256 - (void)makeOptionsButton:(CZQuestion *)model
    257 {
    258     // 0. 设置option view 可以与用户交互
    259     self.optionsView.userInteractionEnabled = YES;
    260     
    261     
    262     // 1. 清除待选按钮的view中的所有子控件
    263     [self.optionsView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
    264     
    265     // 2. 获取当前题目的待选文字的数组
    266     NSArray *words = model.options;
    267     
    268     // 3. 根据待选文字循环来创建按钮
    269     
    270     // 指定每个待选按钮的大小
    271     CGFloat optionW = 35;
    272     CGFloat optionH = 35;
    273     // 指定每个按钮之间的间距
    274     CGFloat margin = 10;
    275     // 指定每行有多少个按钮
    276     int columns = 7;
    277     // 计算出每行第一个按钮距离左边的距离
    278     CGFloat marginLeft = (self.optionsView.frame.size.width - columns * optionW - (columns - 1) * margin) / 2;
    279     
    280     
    281     for (int i = 0; i < words.count; i++) {
    282         // 创建一个按钮
    283         UIButton *btnOpt = [[UIButton alloc] init];
    284         
    285         // 给每个option 按钮一个唯一的tag值
    286         btnOpt.tag = i;
    287         
    288         // 设置按钮背景
    289         [btnOpt setBackgroundImage:[UIImage imageNamed:@"btn_option"] forState:UIControlStateNormal];
    290         [btnOpt setBackgroundImage:[UIImage imageNamed:@"btn_option_highlighted"] forState:UIControlStateHighlighted];
    291         
    292         // 设置按钮文字
    293         [btnOpt setTitle:words[i] forState:UIControlStateNormal];
    294         
    295         // 设置文字颜色为黑色
    296         [btnOpt setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    297         
    298         
    299         // 计算当前按钮的列的索引和行的索引
    300         int colIdx = i % columns;
    301         int rowIdx = i / columns;
    302         
    303         CGFloat optionX = marginLeft + colIdx * (optionW + margin);
    304         CGFloat optionY = 0 + rowIdx * (optionH + margin);
    305         
    306         // 设置按钮frame
    307         btnOpt.frame = CGRectMake(optionX, optionY, optionW, optionH);
    308         
    309         // 把按钮添加到optionsView中
    310         [self.optionsView addSubview:btnOpt];
    311         
    312         // 为待选按钮注册单击事件
    313         [btnOpt addTarget:self action:@selector(optionButtonClick:) forControlEvents:UIControlEventTouchUpInside];
    314     }
    315     
    316     
    317 }
    318 
    319 // 待选按钮的单击事件
    320 - (void)optionButtonClick:(UIButton *)sender
    321 {
    322     // 1. 隐藏当前被点击的按钮
    323     sender.hidden = YES;
    324     
    325     // 2. 把当前被点击的按钮的文字显示到第一个为空的"答案按钮"上
    326     //NSString *text = [sender titleForState:UIControlStateNormal]; // 获取按钮指定状态下的文字
    327     NSString *text = sender.currentTitle; // 获取按钮当前状态下的文字
    328     
    329     
    330     // 2.1 把文字显示到答案按钮上
    331     
    332     // 遍历每一个答案按钮
    333     for (UIButton *answerBtn in self.answerView.subviews) {
    334         // 判断每个"答案按钮"上的文字是否为nil
    335         if (answerBtn.currentTitle == nil) {
    336             
    337             // 把当前点击的待选按钮的文字设置给对应的答案按钮
    338             [answerBtn setTitle:text forState:UIControlStateNormal];
    339             // 把当前点击的待选按钮的tag值也设置给对应的答案按钮
    340             answerBtn.tag = sender.tag;
    341             
    342             break;
    343         }
    344     }
    345     
    346     
    347     
    348     
    349     
    350     
    351     // 3. 判断答案按钮是否已经填满了
    352     // 一开始假设答案按钮是填满的
    353     BOOL isFull = YES;
    354     // 声明一个用来保存用户输入的答案的字符串
    355     NSMutableString *userInput = [NSMutableString string];
    356     
    357     for (UIButton *btnAnswer in self.answerView.subviews) {
    358         if (btnAnswer.currentTitle == nil) {
    359             isFull = NO;
    360             break;
    361         } else {
    362             // 如果当前答案按钮上面有文字, 那么就把这个文字拼接起来
    363             [userInput appendString:btnAnswer.currentTitle];
    364         }
    365     }
    366     
    367     // 如果已经填满, 则禁止option view 控件与用户的交互
    368     if (isFull) {
    369         // 禁止"待选按钮"被点击
    370         self.optionsView.userInteractionEnabled = NO;
    371         
    372         // 获取当前题目的正确答案
    373         CZQuestion *model = self.questions[self.index];
    374         
    375         
    376         // 4. 如果答案按钮被填满了, 那么就判断用户点击输入的答案是否与标准答案一致,
    377         if ([model.answer isEqualToString:userInput]) {
    378              // 如果一致, 则设置答案按钮的文字颜色为蓝色, 同时在0.5秒之后跳转下一题
    379             // 0. 如果正确+100分
    380             [self addScore:100];
    381             //1. 设置所有的答案按钮的文字颜色为 蓝色
    382             [self setAnswerButtonsTitleColor:[UIColor blueColor]];
    383             
    384             // 延迟0.5秒后, 跳转到下一题
    385             [self performSelector:@selector(nextQuestion) withObject:nil afterDelay:0.5];
    386             
    387         } else {
    388             // 如果答案不一致(答案错误), 设置答案按钮的文字颜色为红色
    389             // 设置所有的答案按钮的文字颜色为 红色
    390             [self setAnswerButtonsTitleColor:[UIColor redColor]];
    391         }
    392     }
    393 }
    394 
    395 // 根据指定的分数, 来对界面上的按钮进行加分和减分
    396 - (void)addScore:(int)score
    397 {
    398     // 1. 获取按钮上现在分值
    399     NSString *str = self.btnScore.currentTitle;
    400     
    401     // 2. 把这个分值转换成数字类型
    402     int currentScore = str.intValue;
    403     
    404     // 3. 对这个分数进行操作
    405     currentScore = currentScore + score;
    406     
    407     // 4. 把新的分数设置给按钮
    408     [self.btnScore setTitle:[NSString stringWithFormat:@"%d", currentScore] forState:UIControlStateNormal];
    409 }
    410 
    411 
    412 // 统一设置答案按钮的文字颜色
    413 - (void)setAnswerButtonsTitleColor:(UIColor *)color
    414 {
    415     // 遍历每一个答案按钮, 设置文字颜色
    416     for (UIButton *btnAnswer in self.answerView.subviews) {
    417         [btnAnswer setTitleColor:color forState:UIControlStateNormal];
    418     }
    419 }
    420 
    421 
    422 
    423 // 加载数据, 把模型数据设置到界面的控件上
    424 - (void)settingData:(CZQuestion *)model
    425 {
    426     // 3. 把模型数据设置到界面对应的控件上
    427     self.lblIndex.text = [NSString stringWithFormat:@"%d / %ld", (self.index + 1), self.questions.count];
    428     self.lblTitle.text = model.title;
    429     [self.btnIcon setImage:[UIImage imageNamed:model.icon] forState:UIControlStateNormal];
    430     
    431     // 4. 设置到达最后一题以后, 禁用"下一题按"钮
    432     self.btnNext.enabled = (self.index != self.questions.count - 1);
    433 }
    434 
    435 
    436 // 创建答案按钮
    437 - (void)makeAnswerButtons:(CZQuestion *)model
    438 {
    439     // 这句话的意思:让subviews这个数组中的每个对象, 分别调用一次removeFromSuperview方法, 内部执行了循环,无需我们自己来些循环
    440     [self.answerView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
    441     
    442     // 5.1 获取当前答案的文字的个数
    443     NSInteger len = model.answer.length;
    444     // 设置按钮的frame
    445     CGFloat margin = 10; // 假设每个按钮之间的间距都是10
    446     CGFloat answerW = 35;
    447     CGFloat answerH = 35;
    448     CGFloat answerY = 0;
    449     CGFloat marginLeft = (self.answerView.frame.size.width - (len * answerW) - (len - 1) * margin) / 2;
    450     
    451     // 5.2 循环创建答案按钮, 有几个文字就创建几个按钮
    452     for (int i = 0; i < len; i++) {
    453         // 创建按钮
    454         UIButton *btnAnswer = [[UIButton alloc] init];
    455         // 设置按钮的背景图
    456         [btnAnswer setBackgroundImage:[UIImage imageNamed:@"btn_answer"] forState:UIControlStateNormal];
    457         [btnAnswer setBackgroundImage:[UIImage imageNamed:@"btn_answer_highlighted"] forState:UIControlStateHighlighted];
    458         
    459         // 计算按钮的x值
    460         CGFloat answerX = marginLeft + i * (answerW + margin);
    461         btnAnswer.frame = CGRectMake(answerX, answerY, answerW, answerH);
    462         
    463         // 设置答案按钮的文字颜色
    464         [btnAnswer setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    465         
    466         // 把按钮加到answerView中
    467         [self.answerView addSubview:btnAnswer];
    468         
    469         
    470         // 为答案按钮注册单击事件
    471         [btnAnswer addTarget:self action:@selector(btnAnswerClick:) forControlEvents:UIControlEventTouchUpInside];
    472         
    473     }
    474 }
    475 
    476 // 参数sender, 就表示当前点击的答案按钮
    477 - (void)btnAnswerClick:(UIButton *)sender
    478 {
    479     // 0. 启用option view与用户的交互
    480     self.optionsView.userInteractionEnabled = YES;
    481     
    482     // 1. 设置所有的答案按钮的文字颜色为黑色
    483     [self setAnswerButtonsTitleColor:[UIColor blackColor]];
    484     
    485     
    486     // 2. 在"待选按钮"中找到与当前被点击的答案按钮文字相同待选按钮,设置该按钮显示出来。
    487     for (UIButton *optBtn in self.optionsView.subviews) {
    488         // 比较判断待选按钮的文字是否与当前被点击的答案按钮的文字一致
    489 //        if ([sender.currentTitle isEqualToString:optBtn.currentTitle]) {
    490 //            optBtn.hidden = NO;
    491 //            break;
    492 //        }
    493         
    494         if (sender.tag == optBtn.tag) {
    495             optBtn.hidden = NO;
    496             break;
    497         }
    498     }
    499     
    500     // 1. 清空当前被点击的答案按钮的文字
    501    [sender setTitle:nil forState:UIControlStateNormal];
    502     
    503     
    504 }
    505 @end
  • 相关阅读:
    三十秒读懂混合云管平台的功用
    大家好,我是UCMP云管家,这是我的自我介绍
    唐门暗器之私有云排名
    SpringBoot集成Knife4j
    Spring的全局(统一)异常处理
    SpringBoot集成MybatisPlus
    Spring之拦截器和过滤器
    Spring注解之构建器@Builder的用法
    Java获取客户端请求信息
    Spring注解之生命周期@PostConstruct和@PreDestroy
  • 原文地址:https://www.cnblogs.com/harderAndLuckier/p/5365339.html
Copyright © 2020-2023  润新知