IOS的自定義控件
這里做一個(gè)類似于下面界面的小案例

1.創(chuàng)建一個(gè)空的布局文件 .xib
1 new File -->User Interface -->選擇View 2 創(chuàng)建一個(gè)空的view ,會(huì)自動(dòng)生成一個(gè) .xib的文件
2.設(shè)置我們自己需要經(jīng)常復(fù)用的界面
注意:記得設(shè)置"Custom Class"中的 Class屬性 與我們的代碼文件 .h .m (Cocoa Touch Class文件 )相關(guān)聯(lián)
3.創(chuàng)建我們的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封裝一個(gè)類方法,這個(gè)類方法的作用就是創(chuàng)建一個(gè)view對(duì)象 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創(chuàng)建每一個(gè)應(yīng)用(UIView) 13 //通過動(dòng)態(tài)加載xib文件創(chuàng)建里面的view 14 //1.1>找到應(yīng)用的根目錄 15 NSBundle *rootBundle =[NSBundle mainBundle];//NSLog(@"%@",[mainBundle bundlePath]); 16 //1.2>在應(yīng)用程序根目錄下取搜索對(duì)應(yīng)的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 //解析模型數(shù)據(jù),把模型數(shù)據(jù)賦值給UIView中的各個(gè)子控件 25 self.imgViewIcon.image = [UIImage imageNamed:model.icon]; 26 self.lblName.text=model.name; 27 } 28 //下載按鈕的單擊事件 29 - (IBAction)btnDownloadClick:(UIButton *)sender { 30 //1.禁用當(dāng)前被點(diǎn)擊的按鈕 31 sender.enabled = NO; 32 33 //2.彈出一個(gè)消息提醒框(這個(gè)消息提醒框其實(shí)就是一個(gè)UILable) 34 UILabel *lblMsg = [[UILabel alloc]init]; 35 //2.1 設(shè)置lblMsg的顯示文字 36 lblMsg.text=@"正在下載...."; 37 //2.2 設(shè)置lblMsg的背景色 38 lblMsg.backgroundColor = [UIColor blackColor]; 39 //2.3設(shè)置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設(shè)置label的文字顏色 48 lblMsg.textColor = [UIColor redColor]; 49 //2.5設(shè)置label居中顯示 50 lblMsg.textAlignment = NSTextAlignmentCenter; 51 //2.6設(shè)置文字粗體 52 lblMsg.font = [UIFont boldSystemFontOfSize:17]; 53 //2.7設(shè)置label的透明度 54 lblMsg.alpha = 0.0;//一開始把透明度設(shè)置為0 ,然后通過動(dòng)畫的方式慢慢的改變透明度 55 //2.8 設(shè)置Label為"圓角" 56 //設(shè)置四個(gè)角的"半徑" 57 lblMsg.layer.cornerRadius =10; 58 //把多余的部分裁剪掉 59 lblMsg.layer.masksToBounds =YES; 60 //2.9通過動(dòng)畫的方式來顯示Label 61 // [UIView animateWithDuration:2.0 animations:^{ 62 // lblMsg.alpha =0.6; 63 // }]; 64 65 //開啟一個(gè)動(dòng)畫,這個(gè)動(dòng)畫要執(zhí)行1.5秒 66 [UIView animateWithDuration:1.5 animations:^{ 67 //動(dòng)畫代碼:將透明度變?yōu)?.6 68 lblMsg.alpha = 0.6; 69 } completion:^(BOOL finished) { 70 if(finished) 71 { 72 //這個(gè)代碼的含義是,隔一段時(shí)間后再啟動(dòng)另外一個(gè)動(dòng)畫 73 //這個(gè)動(dòng)畫的執(zhí)行時(shí)間是1.5秒,但是這個(gè)動(dòng)畫會(huì)在1.0秒之后再開始執(zhí)行 74 //UIViewAnimationOptionCurveLinear表示是均速執(zhí)行動(dòng)畫 75 [UIView animateWithDuration:1.5 delay:1.0 options:UIViewAnimationOptionCurveLinear animations:^{ 76 //這個(gè)動(dòng)畫的代碼 77 lblMsg.alpha = 0; 78 } completion:^(BOOL finished) { 79 if(finished){ 80 //當(dāng)Label的透明度變?yōu)?以后,再把這個(gè)Label從view中移除 81 [lblMsg removeFromSuperview]; 82 } 83 }]; 84 } 85 }]; 86 //3.把lblMsg加到控制器所管理的那個(gè)view上 87 [self.superview addSubview:lblMsg]; 88 89 } 90 @end
這樣我們的自定義控件就算完成了,接下來要做得就是引用我們自己所做的界面
4.由于我們加載的圖片和名稱都是來源 .plist文件
所以我們?cè)O(shè)置一個(gè)"模型" 來導(dǎo)入.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 //用來保存所有應(yīng)用的數(shù)據(jù) 8 @property(nonatomic,strong)NSArray *apps; 9 10 @end 11 12 @implementation ViewController 13 14 //重寫apps屬性的get方法,進(jìn)行懶加載數(shù)據(jù) 15 -(NSArray *)apps{ 16 if(_apps == nil){ 17 //加載數(shù)據(jù) 18 //1.獲取app.plist文件在手機(jī)上的路徑 19 NSString *path = [[NSBundle mainBundle]pathForResource:@"app.plist" ofType:nil]; 20 21 //2.根據(jù)路徑加載數(shù)據(jù) 22 NSArray *arrayDict = [NSArray arrayWithContentsOfFile:path]; 23 24 //3.創(chuàng)建一個(gè)可變數(shù)據(jù)用來保存一個(gè)一個(gè)的模型對(duì)象 25 NSMutableArray *arrayModels = [NSMutableArray array]; //一個(gè)空的可變數(shù)組 26 27 //4.循環(huán)字典數(shù)組,把每個(gè)字典對(duì)象轉(zhuǎn)換成一個(gè)模型對(duì)象 28 for(NSDictionary *dict in arrayDict){ 29 //創(chuàng)建一個(gè)模型 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 //假設(shè)每行的應(yīng)用的個(gè)數(shù) 44 int columns = 3; 45 46 //獲取控制器所管理的view的寬度 47 CGFloat viewWidth = self.view.frame.size.width; 48 49 //每個(gè)應(yīng)用的寬和高 50 CGFloat appW = 75; 51 CGFloat appH = 90; 52 CGFloat marginTop =30;//第一行距離頂部的距離 53 CGFloat marginX = (viewWidth - columns *appW)/(columns+1); 54 CGFloat marginY = marginX;//假設(shè)每行之間的間距與marginX相等 55 56 for(int i=0;i<self.apps.count;i++){ 57 //獲取當(dāng)前這個(gè)應(yīng)用的數(shù)據(jù)字典 58 CZApp *appModel = self.apps[i]; 59 60 //創(chuàng)建view 61 CZAppView *appView = [CZAppView appView]; 62 63 //2.2 設(shè)置appView 的fram屬性 64 //計(jì)算每個(gè)單元格所在的列的索引 65 int colIdx = i%columns; 66 //計(jì)算每個(gè)單元格的行索引 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(控制器所管理的那個(gè)view) 74 [self.view addSubview:appView]; 75 76 //設(shè)置數(shù)據(jù) 77 //把模型數(shù)據(jù)設(shè)置給"自定義view"的model屬性 78 //然后重寫model屬性的set方法,在set方法中解析模型對(duì)象中的屬性,并把屬性值設(shè)置給自定義view的各個(gè)子控件 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
再制作一個(gè)自動(dòng)猜圖的小案例
這里主要的是動(dòng)態(tài)生成按鈕,以及修改launchScreen的啟動(dòng)界面
效果圖:

1.修改啟動(dòng)的launchscreen 以及應(yīng)用小圖標(biāo)icon
簡(jiǎn)單來說只需要把我們制作的界面放入Images.xcassets中覆蓋原來系統(tǒng)的LaunchImage和AppIcon就可以
主要注意的是關(guān)于尺寸的選擇:

然后修改項(xiàng)目General中的APP Icons and Launch Image

1.先創(chuàng)建模型用于導(dǎo)入 .plist數(shù)據(jù)
.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 // 所有問題的數(shù)據(jù)都在這個(gè)數(shù)組中 8 @property (nonatomic, strong) NSArray *questions; 9 10 // 控制題目索引, 類型的int類型屬性, 默認(rèn)沒有賦值一開始就是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 // 用來引用那個(gè)“陰影”按鈕的屬性 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 // 懶加載數(shù)據(jù) 47 - (NSArray *)questions 48 { 49 if (_questions == nil) { 50 // 加載數(shù)據(jù) 51 NSString *path = [[NSBundle mainBundle] pathForResource:@"questions.plist" ofType:nil]; 52 NSArray *arrayDict = [NSArray arrayWithContentsOfFile:path]; 53 NSMutableArray *arrayModel = [NSMutableArray array]; 54 55 // 遍歷把字典轉(zhuǎn)模型 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 // 改變狀態(tài)欄的文字顏色為白色 67 - (UIStatusBarStyle)preferredStatusBarStyle 68 { 69 return UIStatusBarStyleLightContent; 70 } 71 72 // 隱藏狀態(tài)欄 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 // 點(diǎn)擊下一題 95 - (IBAction)btnNextClick { 96 97 // 移動(dòng)到下一題 98 [self nextQuestion]; 99 } 100 101 // 顯示大圖 102 - (IBAction)bigImage:(id)sender { 103 104 // 記錄一下頭像按鈕的原始frame 105 self.iconFrame = self.btnIcon.frame; 106 107 // 1.創(chuàng)建大小與self.view一樣的按鈕, 把這個(gè)按鈕作為一個(gè)"陰影" 108 UIButton *btnCover = [[UIButton alloc] init]; 109 // 設(shè)置按鈕大小 110 btnCover.frame = self.view.bounds; 111 // 設(shè)置按鈕背景色 112 btnCover.backgroundColor = [UIColor blackColor]; 113 // 設(shè)置按鈕透明度 114 btnCover.alpha = 0.0; 115 116 // 把按鈕加到self.view中 117 [self.view addSubview:btnCover]; 118 119 // 為陰影按鈕注冊(cè)一個(gè)單擊事件 120 [btnCover addTarget:self action:@selector(samllImage) forControlEvents:UIControlEventTouchUpInside]; 121 122 123 // 2. 把圖片設(shè)置到陰影的上面 124 // 把self.view中的所有子控件中, 只把self.btnIcon顯示到最上層 125 [self.view bringSubviewToFront:self.btnIcon]; 126 127 // 通過self.cover來引用btnCover 128 self.cover = btnCover; 129 130 131 // 3. 通過動(dòng)畫的方式把圖片變大 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 // 設(shè)置按鈕透明度 139 btnCover.alpha = 0.6; 140 141 // 設(shè)置圖片的新的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 // 點(diǎn)擊"提示"按鈕 157 - (IBAction)btnTipClick { 158 // 1. 分?jǐn)?shù)-1000 159 [self addScore:-1000]; 160 161 162 // 2. 把所有的答案按鈕"清空"(其實(shí)這里的"清空"最好是調(diào)用每個(gè)答案按鈕的單擊事件) 163 for (UIButton *btnAnswer in self.answerView.subviews) { 164 // 讓每個(gè)答案按鈕點(diǎn)擊一下 165 [self btnAnswerClick:btnAnswer]; 166 } 167 168 // 3. 根據(jù)當(dāng)前的索引, 從數(shù)據(jù)數(shù)組中(self.questions)中找到對(duì)應(yīng)的數(shù)據(jù)模型 169 // 從數(shù)據(jù)模型中獲取正確答案的第一個(gè)字符, 把待選按鈕中和這個(gè)字符相等的那個(gè)按鈕點(diǎn)擊一下 170 CZQuestion *model = self.questions[self.index]; 171 //截取正確答案中的第一個(gè)字符"字符串" 172 NSString *firstChar = [model.answer substringToIndex:1]; 173 174 // 根據(jù)firstChar在option按鈕中找到對(duì)應(yīng)的option 按鈕, 讓這個(gè)按鈕點(diǎn)擊一下 175 for (UIButton *btnOpt in self.optionsView.subviews) { 176 if ([btnOpt.currentTitle isEqualToString:firstChar]) { 177 [self optionButtonClick:btnOpt]; // 設(shè)置某個(gè)option 按鈕點(diǎn)擊一下 178 break; 179 } 180 } 181 } 182 183 184 // "陰影"的單擊事件 185 - (void)samllImage 186 { 187 [UIView animateWithDuration:0.7 animations:^{ 188 // 1. 設(shè)置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 // 當(dāng)頭像圖片變成小圖以后, 再把self.cover設(shè)置成nil 197 self.cover = nil; 198 } 199 }]; 200 } 201 202 203 // 實(shí)現(xiàn)UIAlertView的代理方法 204 - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 205 { 206 // NSLog(@"%ld", buttonIndex); 207 if (buttonIndex == 0) { 208 // 讓程序在回到第0個(gè)問題 209 self.index = -1; 210 [self nextQuestion]; 211 } 212 } 213 214 215 216 // 下一題 217 - (void)nextQuestion 218 { 219 // 1. 讓索引++ 220 self.index++; 221 222 // 判斷當(dāng)前索引是否越界, 入股索引越界, 則提示用戶 223 if (self.index == self.questions.count) { 224 //NSLog(@"答題完畢!!!!"); 225 226 // 彈出一個(gè)對(duì)話框 227 UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"操作提示" message:@"恭喜通關(guān)!" delegate:self cancelButtonTitle:@"確定" otherButtonTitles:nil]; 228 229 // 顯示對(duì)話框 230 [alertView show]; 231 return; 232 } 233 234 235 // 2. 根據(jù)索引獲取當(dāng)前的模型數(shù)據(jù) 236 CZQuestion *model = self.questions[self.index]; 237 238 239 240 // 3. 根據(jù)模型設(shè)置數(shù)據(jù) 241 [self settingData:model]; 242 243 244 // 4. 動(dòng)態(tài)創(chuàng)建"答案按鈕" 245 [self makeAnswerButtons:model]; 246 247 248 // 5. 動(dòng)態(tài)創(chuàng)建"待選按鈕" 249 [self makeOptionsButton:model]; 250 251 252 } 253 254 255 // 創(chuàng)建待選按鈕 256 - (void)makeOptionsButton:(CZQuestion *)model 257 { 258 // 0. 設(shè)置option view 可以與用戶交互 259 self.optionsView.userInteractionEnabled = YES; 260 261 262 // 1. 清除待選按鈕的view中的所有子控件 263 [self.optionsView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; 264 265 // 2. 獲取當(dāng)前題目的待選文字的數(shù)組 266 NSArray *words = model.options; 267 268 // 3. 根據(jù)待選文字循環(huán)來創(chuàng)建按鈕 269 270 // 指定每個(gè)待選按鈕的大小 271 CGFloat optionW = 35; 272 CGFloat optionH = 35; 273 // 指定每個(gè)按鈕之間的間距 274 CGFloat margin = 10; 275 // 指定每行有多少個(gè)按鈕 276 int columns = 7; 277 // 計(jì)算出每行第一個(gè)按鈕距離左邊的距離 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 // 創(chuàng)建一個(gè)按鈕 283 UIButton *btnOpt = [[UIButton alloc] init]; 284 285 // 給每個(gè)option 按鈕一個(gè)唯一的tag值 286 btnOpt.tag = i; 287 288 // 設(shè)置按鈕背景 289 [btnOpt setBackgroundImage:[UIImage imageNamed:@"btn_option"] forState:UIControlStateNormal]; 290 [btnOpt setBackgroundImage:[UIImage imageNamed:@"btn_option_highlighted"] forState:UIControlStateHighlighted]; 291 292 // 設(shè)置按鈕文字 293 [btnOpt setTitle:words[i] forState:UIControlStateNormal]; 294 295 // 設(shè)置文字顏色為黑色 296 [btnOpt setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 297 298 299 // 計(jì)算當(dāng)前按鈕的列的索引和行的索引 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 // 設(shè)置按鈕frame 307 btnOpt.frame = CGRectMake(optionX, optionY, optionW, optionH); 308 309 // 把按鈕添加到optionsView中 310 [self.optionsView addSubview:btnOpt]; 311 312 // 為待選按鈕注冊(cè)單擊事件 313 [btnOpt addTarget:self action:@selector(optionButtonClick:) forControlEvents:UIControlEventTouchUpInside]; 314 } 315 316 317 } 318 319 // 待選按鈕的單擊事件 320 - (void)optionButtonClick:(UIButton *)sender 321 { 322 // 1. 隱藏當(dāng)前被點(diǎn)擊的按鈕 323 sender.hidden = YES; 324 325 // 2. 把當(dāng)前被點(diǎn)擊的按鈕的文字顯示到第一個(gè)為空的"答案按鈕"上 326 //NSString *text = [sender titleForState:UIControlStateNormal]; // 獲取按鈕指定狀態(tài)下的文字 327 NSString *text = sender.currentTitle; // 獲取按鈕當(dāng)前狀態(tài)下的文字 328 329 330 // 2.1 把文字顯示到答案按鈕上 331 332 // 遍歷每一個(gè)答案按鈕 333 for (UIButton *answerBtn in self.answerView.subviews) { 334 // 判斷每個(gè)"答案按鈕"上的文字是否為nil 335 if (answerBtn.currentTitle == nil) { 336 337 // 把當(dāng)前點(diǎn)擊的待選按鈕的文字設(shè)置給對(duì)應(yīng)的答案按鈕 338 [answerBtn setTitle:text forState:UIControlStateNormal]; 339 // 把當(dāng)前點(diǎn)擊的待選按鈕的tag值也設(shè)置給對(duì)應(yīng)的答案按鈕 340 answerBtn.tag = sender.tag; 341 342 break; 343 } 344 } 345 346 347 348 349 350 351 // 3. 判斷答案按鈕是否已經(jīng)填滿了 352 // 一開始假設(shè)答案按鈕是填滿的 353 BOOL isFull = YES; 354 // 聲明一個(gè)用來保存用戶輸入的答案的字符串 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 // 如果當(dāng)前答案按鈕上面有文字, 那么就把這個(gè)文字拼接起來 363 [userInput appendString:btnAnswer.currentTitle]; 364 } 365 } 366 367 // 如果已經(jīng)填滿, 則禁止option view 控件與用戶的交互 368 if (isFull) { 369 // 禁止"待選按鈕"被點(diǎn)擊 370 self.optionsView.userInteractionEnabled = NO; 371 372 // 獲取當(dāng)前題目的正確答案 373 CZQuestion *model = self.questions[self.index]; 374 375 376 // 4. 如果答案按鈕被填滿了, 那么就判斷用戶點(diǎn)擊輸入的答案是否與標(biāo)準(zhǔn)答案一致, 377 if ([model.answer isEqualToString:userInput]) { 378 // 如果一致, 則設(shè)置答案按鈕的文字顏色為藍(lán)色, 同時(shí)在0.5秒之后跳轉(zhuǎn)下一題 379 // 0. 如果正確+100分 380 [self addScore:100]; 381 //1. 設(shè)置所有的答案按鈕的文字顏色為 藍(lán)色 382 [self setAnswerButtonsTitleColor:[UIColor blueColor]]; 383 384 // 延遲0.5秒后, 跳轉(zhuǎn)到下一題 385 [self performSelector:@selector(nextQuestion) withObject:nil afterDelay:0.5]; 386 387 } else { 388 // 如果答案不一致(答案錯(cuò)誤), 設(shè)置答案按鈕的文字顏色為紅色 389 // 設(shè)置所有的答案按鈕的文字顏色為 紅色 390 [self setAnswerButtonsTitleColor:[UIColor redColor]]; 391 } 392 } 393 } 394 395 // 根據(jù)指定的分?jǐn)?shù), 來對(duì)界面上的按鈕進(jìn)行加分和減分 396 - (void)addScore:(int)score 397 { 398 // 1. 獲取按鈕上現(xiàn)在分值 399 NSString *str = self.btnScore.currentTitle; 400 401 // 2. 把這個(gè)分值轉(zhuǎn)換成數(shù)字類型 402 int currentScore = str.intValue; 403 404 // 3. 對(duì)這個(gè)分?jǐn)?shù)進(jìn)行操作 405 currentScore = currentScore + score; 406 407 // 4. 把新的分?jǐn)?shù)設(shè)置給按鈕 408 [self.btnScore setTitle:[NSString stringWithFormat:@"%d", currentScore] forState:UIControlStateNormal]; 409 } 410 411 412 // 統(tǒng)一設(shè)置答案按鈕的文字顏色 413 - (void)setAnswerButtonsTitleColor:(UIColor *)color 414 { 415 // 遍歷每一個(gè)答案按鈕, 設(shè)置文字顏色 416 for (UIButton *btnAnswer in self.answerView.subviews) { 417 [btnAnswer setTitleColor:color forState:UIControlStateNormal]; 418 } 419 } 420 421 422 423 // 加載數(shù)據(jù), 把模型數(shù)據(jù)設(shè)置到界面的控件上 424 - (void)settingData:(CZQuestion *)model 425 { 426 // 3. 把模型數(shù)據(jù)設(shè)置到界面對(duì)應(yīng)的控件上 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. 設(shè)置到達(dá)最后一題以后, 禁用"下一題按"鈕 432 self.btnNext.enabled = (self.index != self.questions.count - 1); 433 } 434 435 436 // 創(chuàng)建答案按鈕 437 - (void)makeAnswerButtons:(CZQuestion *)model 438 { 439 // 這句話的意思:讓subviews這個(gè)數(shù)組中的每個(gè)對(duì)象, 分別調(diào)用一次removeFromSuperview方法, 內(nèi)部執(zhí)行了循環(huán),無需我們自己來些循環(huán) 440 [self.answerView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; 441 442 // 5.1 獲取當(dāng)前答案的文字的個(gè)數(shù) 443 NSInteger len = model.answer.length; 444 // 設(shè)置按鈕的frame 445 CGFloat margin = 10; // 假設(shè)每個(gè)按鈕之間的間距都是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 循環(huán)創(chuàng)建答案按鈕, 有幾個(gè)文字就創(chuàng)建幾個(gè)按鈕 452 for (int i = 0; i < len; i++) { 453 // 創(chuàng)建按鈕 454 UIButton *btnAnswer = [[UIButton alloc] init]; 455 // 設(shè)置按鈕的背景圖 456 [btnAnswer setBackgroundImage:[UIImage imageNamed:@"btn_answer"] forState:UIControlStateNormal]; 457 [btnAnswer setBackgroundImage:[UIImage imageNamed:@"btn_answer_highlighted"] forState:UIControlStateHighlighted]; 458 459 // 計(jì)算按鈕的x值 460 CGFloat answerX = marginLeft + i * (answerW + margin); 461 btnAnswer.frame = CGRectMake(answerX, answerY, answerW, answerH); 462 463 // 設(shè)置答案按鈕的文字顏色 464 [btnAnswer setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 465 466 // 把按鈕加到answerView中 467 [self.answerView addSubview:btnAnswer]; 468 469 470 // 為答案按鈕注冊(cè)單擊事件 471 [btnAnswer addTarget:self action:@selector(btnAnswerClick:) forControlEvents:UIControlEventTouchUpInside]; 472 473 } 474 } 475 476 // 參數(shù)sender, 就表示當(dāng)前點(diǎn)擊的答案按鈕 477 - (void)btnAnswerClick:(UIButton *)sender 478 { 479 // 0. 啟用option view與用戶的交互 480 self.optionsView.userInteractionEnabled = YES; 481 482 // 1. 設(shè)置所有的答案按鈕的文字顏色為黑色 483 [self setAnswerButtonsTitleColor:[UIColor blackColor]]; 484 485 486 // 2. 在"待選按鈕"中找到與當(dāng)前被點(diǎn)擊的答案按鈕文字相同待選按鈕,設(shè)置該按鈕顯示出來。 487 for (UIButton *optBtn in self.optionsView.subviews) { 488 // 比較判斷待選按鈕的文字是否與當(dāng)前被點(diǎn)擊的答案按鈕的文字一致 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. 清空當(dāng)前被點(diǎn)擊的答案按鈕的文字 501 [sender setTitle:nil forState:UIControlStateNormal]; 502 503 504 } 505 @end

浙公網(wǎng)安備 33010602011771號(hào)