[iOS基礎控件-4.5]猜圖游戲
11/23/2015來源:iOS開發人氣:17478
A.需要掌握的
1.添加圖片資源(暫時認為@2x跟非@2x代表同一張圖片)
2.搭建UI界面
* 文本標簽
* 4個按鈕
* 中間的圖片
3.設置狀態欄樣式
4.監聽下一題按鈕的點擊
5.延遲加載數據
* 加載plist
* 字典轉模型
* KVC的引入
6.切換下一題的序號、圖片、標題,下一題按鈕的可用性
7.默認顯示第1條題目
8.顯示大圖
* 監聽中間圖片點擊
* 添加遮蓋
* 移動圖片(注意頭像圖片的層級順序)
* 監聽“大圖按鈕”
9.展示答案的個數
10.展示待選答案
11.答案處理
12.提示功能
2.搭建UI界面
* 文本標簽
* 4個按鈕
* 中間的圖片
3.設置狀態欄樣式
4.監聽下一題按鈕的點擊
5.延遲加載數據
* 加載plist
* 字典轉模型
* KVC的引入
6.切換下一題的序號、圖片、標題,下一題按鈕的可用性
7.默認顯示第1條題目
8.顯示大圖
* 監聽中間圖片點擊
* 添加遮蓋
* 移動圖片(注意頭像圖片的層級順序)
* 監聽“大圖按鈕”
9.展示答案的個數
10.展示待選答案
11.答案處理
12.提示功能
13.Icon和Launch、@2x
B.實現思路
1.構建基本UI:
(1)背景
(2)按鈕
(3)圖片
(4)選項
2.數據存儲與加載
(1)標題數據
(2)圖片數據
(3)可選項數據
(4)答案數據
(5)得分數據
3.大圖功能 (點擊圖片或者按鈕)
(1)放大并調整圖片位置
(2)虛化背景,使用半透明全覆蓋的button
(3)點擊背景或者圖片,刪除半透明背景、恢復圖片
a.動畫效果, 使用帶block參數方法
b.播放完動畫再移除陰影元素
4.下一題功能
其調用的功能是整個APP的核心,包含了初始化控件、加載文件數據、刪除舊控件、加入新控件、刷新界面
5.提示功能
給出一定的答案
6.幫助功能
(在線分享功能,沒有實現)
C.知識點
1.設置狀態欄 (iOS7開始)
(1)設置樣式
在Controller中重寫eferredStateBarStyle方法,返回要設置的值
1 // 設置狀態欄是否隱藏 2 - (BOOL)prefersstatusBarHidden { 3 return NO; 4 } 5 6 // 設置狀態欄 7 - (UIStatusBarStyle)preferredStatusBarStyle { 8 // 設置狀態欄為白色 9 return UIStatusBarStyleLightContent; 10 }
狀態欄是顯示黑色字體:
修改之后:
2.APP圖標
只要文件名為 “Icon.png”,就會被設置為APP圖標
3.啟動畫面
一個app在啟動過程中會全屏顯示叫做Default.png的圖片
不用規格Default的使用場合
- Default.png:非retina-hone屏幕,320x480
- Default@2x.png:retina-iPhone屏幕,640x960
- Default-568h@2x.png:4inch的retina-iPhone屏幕,640x1136
- Default-Portrait~ipad.png:非retain-iPad豎屏屏幕,768x1024
- Default-Portrait~ipad@2x.png:retain-iPad豎屏屏幕,1536x2048
- Default-Landscape~ipad.png:非retain-iPad橫屏屏幕,1024x768
- Default-Landscape~ipad@2x.png:retain-iPad橫屏屏幕,2048x1536
4.背景圖和前景元素之間的層次關系
一般按照storyboard中的順序排列
使用代碼把某個元素提到最前
// 2.更換陰影和圖片的位置
[self.view bringSubviewToFront:self.icon];
5.使用Button做出中間的圖片
為了做出有白邊效果的圖片,使用了白色圖片作為背景,然后設置圖片的邊距Inset,露出白色背景圖
6.延遲加載數據
改寫controller中的題目數組questions 的get方法,在調用get方法的時候檢測questions是否已經存在,否則才開始加載
7.“大圖”功能
虛化背景:使用一張半透明的圖片遮擋
圖片放大:使用形變轉換
動畫效果:使用帶block參數的動畫方法,設置動畫事件、完成動畫后消除遮蓋回收內存
8.恢復圖片
點擊遮蓋 / 點擊放大后的圖片:消除遮蓋,恢復圖片
9.消除button被點擊的時候變灰
取消勾選 “Highlighted Adjusts Image”
10.顯示答案
使用button, 動態生成相應數量的button
使用UIView作為父控件包含多個答案button
在storyboard中創建一個UIView,放到合適位置,調整尺寸
點擊 "下一題” 按鈕:
刪除舊答案,自己控制自己從父視圖刪除
1 // 5.1 刪除全部舊答案的button 2 [self.answerView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
添加新答案
11.加入選項
原理同答案模塊,多了在行上面的位置計算
刪除舊的所有選項,添加新的選項
1 // 6.1 刪除舊選項 2 [self.optionsView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
12.點擊選項
(1)被點擊的選項按鈕消失(hidden = YES)
(2)將選中選項的文字放到答案區的按鈕上
(3)把文字放到第一個沒有文字的答案按鈕上
(4)點擊有文字的答案按鈕,文字恢復到選項
(5)答案填滿后,阻止事件觸發
13.點擊有文字的答案按鈕
(1)被點擊的答案按鈕文字消失
(2)讓答案文字對應的選項重新出現
遍歷所有選項,找到對應的選項進行設置
14.判斷答案正確
(1)遍歷答案區,判斷每個答案按鈕是否有文字,如果都有文字,證明已經完成,檢查答案
(2)答錯答案文字變紅,退選答案恢復文字顏色為黑色
(3)答對了給出提示,延遲1秒后跳入下一題
17.分數計算
答對加分
18.提示功能
取消現有的所有答案,給出正確答案的第一個字,扣一定分數
19.更改圖標
圖標有命名規范,最好使用 “icon.png"
把所有圖標文件拖放到 “Images.xcassets” 的”AppIcon” 里面
20.修改啟動畫面
注意:
在現時最新版Xcode6.1中,默認使用 LaunchScreen.xib 作為啟動畫面
現在有兩種方式設置啟動圖片
- 使用 xib (LaunchScreen)
- 使用 LaunchImage
啟動頁面配置:
項目 ==> general ==> App Icons and Launch Images
(1)使用 xib
a.默認狀態就是使用 xib
b.如果現狀態是使用LaunchImage, 設置 “Launch Images Source” 為 “Don’t use asset catalogs”
c.設置 xib 的文件名
d.在 xib 中設計
e.效果
(2)使用 LaunchImage
a.更改配置
項目 ==> general ==> App Icons and Launch Images ==> Launch Images Source 中選擇 images,再把Launch Screen File 選項設置為空
b.會發現Images.xcassets 下自動生成了一個 LaunchImage 的Imageset
c.拖入畫面
d.效果
主要代碼:
ViewController.m:
1 // 2 // ViewController.m 3 // CrazyGuessGame 4 // 5 // Created by hellovoidworld on 14/11/26. 6 // Copyright (c) 2014年 hellovoidworld. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 #import "Question.h" 11 12 @interface ViewController () 13 14 @property (weak, nonatomic) IBOutlet UILabel *noLabel; // 序號 15 @property (weak, nonatomic) IBOutlet UILabel *titleLabel; // 標題 16 @property (weak, nonatomic) IBOutlet UIButton *icon; 17 @property (weak, nonatomic) IBOutlet UIButton *nextImageButton; 18 @property (weak, nonatomic) IBOutlet UIView *answerView; 19 @property (weak, nonatomic) IBOutlet UIView *optionsView; 20 @property (weak, nonatomic) IBOutlet UIButton *scoreButton; 21 22 - (IBAction)onTipsButtonClicked; 23 - (IBAction)onHelpButtonClicked; 24 - (IBAction)onEnlargeImgButtonClicked; 25 - (IBAction)onNextImgButtonClicked; 26 - (IBAction)onImageClicked; 27 28 /** 所有題目 */ 29 @property(nonatomic, strong) NSArray *questions; 30 31 /** 當前題目序號 */ 32 @property(nonatomic, assign) int index; 33 34 /** 遮蓋陰影 */ 35 @property(nonatomic, weak) UIButton *cover; 36 37 /** 原始圖片位置、尺寸 */ 38 @property(nonatomic, assign) CGRect imageOriginalFrame; 39 40 /** 答案是否已經填滿標識 */ 41 @property(nonatomic, assign) BOOL isAnswerCompleted; 42 43 /** 得分 */ 44 @property(nonatomic, assign) int score; 45 46 @end 47 48 @implementation ViewController 49 50 - (void)viewDidLoad { 51 [super viewDidLoad]; 52 // Do any additional setup after loading the view, typically from a nib. 53 54 //存儲原始圖片的位置、尺寸信息 55 self.imageOriginalFrame = self.icon.frame; 56 57 self.index = -1; 58 [self onNextImgButtonClicked]; // 初次加載,index是0 59 } 60 61 - (void)didReceiveMemoryWarning { 62 [super didReceiveMemoryWarning]; 63 // Dispose of any resources that can be recreated. 64 } 65 66 // 改寫getter, 延遲加載,此處不要使用self.questions來取得questions,否則陷入死循環 67 - (NSArray *)questions { 68 if (nil == _questions) { 69 // 1.加載plist數據 70 NSArray *questionDictArray = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"questions" ofType:@"plist"]]; 71 72 NSMutableArray *questionsArray = [NSMutableArray array]; 73 for (NSDictionary *questionDict in questionDictArray) { 74 // 2.將數據封裝到Model "Question" 75 Question *question = [Question initWithDictionary:questionDict]; 76 [questionsArray addObject:question]; 77 } 78 79 // 3.賦值 80 _questions = questionsArray; 81 } 82 83 return _questions; 84 } 85 86 // 設置狀態欄是否隱藏 87 - (BOOL)prefersStatusBarHidden { 88 return NO; 89 } 90 91 92 // 設置狀態欄 93 - (UIStatusBarStyle)preferredStatusBarStyle { 94 // 設置狀態欄字體為白色 95 return UIStatusBarStyleLightContent; 96 } 97 98 99 // 點擊“提示”按鈕 100 - (IBAction)onTipsButtonClicked { 101 // 1.清除現有的答案 102 for (UIButton *currentAnswerButton in self.answerView.subviews) { 103 [self onAnswerClicked:currentAnswerButton]; 104 } 105 106 // 2.取出正確答案片段 107 Question *question = self.questions[self.index]; 108 NSString *partOfCorrectAnswer = [question.answer substringToIndex:1]; 109 110 // 3.填充到答案區 111 for (UIButton *optionButton in self.optionsView.subviews) { 112 if ([partOfCorrectAnswer isEqualToString:optionButton.currentTitle]) { 113 [self onOptionClicked:optionButton]; 114 } 115 } 116 117 // 5.扣取相應分數 118 [self calScore:-500]; 119 } 120 121 // 點擊“幫助”按鈕 122 - (IBAction)onHelpButtonClicked { 123 } 124 125 // 點擊“大圖”按鈕 126 - (IBAction)onEnlargeImgButtonClicked { 127 // 1.1添加陰影 128 UIButton *cover = [[UIButton alloc] init]; 129 cover.frame = self.view.bounds; 130 cover.backgroundColor = [UIColor blackColor]; 131 cover.alpha = 0; 132 133 // 1.2給陰影添加變回小圖的觸發事件 134 [cover addTarget:self action:@selector(smallImg) forControlEvents:UIControlEventTouchUpInside]; 135 136 self.cover = cover; 137 [self.view addSubview:cover]; 138 139 // 2.更換陰影和圖片的位置 140 [self.view bringSubviewToFront:self.icon]; 141 142 // 3.更改圖像大小,顯示陰影 143 [UIView animateWithDuration:1 animations:^{ 144 cover.alpha = 0.7; 145 146 CGFloat iconWidth = self.view.frame.size.width; 147 CGFloat iconHeight = iconWidth; 148 CGFloat iconX = 0; 149 CGFloat iconY = (self.view.frame.size.height / 2) - (iconHeight / 2); 150 self.icon.frame = CGRectMake(iconX, iconY, iconWidth, iconHeight); 151 }]; 152 } 153 154 /** 縮小圖片 */ 155 - (void) smallImg { 156 [UIView animateWithDuration:1 animations:^{ 157 // 1.刪除陰影 158 self.cover.alpha = 0; 159 160 // 2.恢復圖片 161 self.icon.frame = self.imageOriginalFrame; 162 163 } completion:^(BOOL finished) { 164 // 動畫執行完成后 165 166 [self.cover removeFromSuperview]; 167 self.cover = nil; 168 }]; 169 170 } 171 172 // 點擊“下一題”按鈕 173 - (IBAction)onNextImgButtonClicked { 174 self.index++; 175 176 // 1.取出相應地Model數據 177 Question *question = self.questions[self.index]; 178 179 // 2.設置控件 180 [self setControls:question]; 181 182 // 3.設置答案 183 [self addAnswer:question]; 184 185 // 4.設置選項 186 [self addOptions:question]; 187 188 189 } 190 191 /** 設置控件 */ 192 - (void) setControls:(Question *) question { 193 // 1.答案是否已經填滿 194 self.isAnswerCompleted = NO; 195 196 // 2.得分 197 [self.scoreButton setTitle:[NSString stringWithFormat:@"%d", self.score] forState:UIControlStateNormal]; 198 199 // 2.設置序號 200 self.noLabel.text = [NSString stringWithFormat:@"%d/%d", self.index + 1, self.questions.count]; 201 202 // 3.設置標題 203 self.titleLabel.text = question.title; 204 205 // 4.設置圖片 206 [self.icon setImage:[UIImage imageNamed:question.icon] forState:UIControlStateNormal]; 207 208 // 5.設置“下一題”按鈕 209 self.nextImageButton.enabled = (self.index + 1) != self.questions.count; 210 } 211 212 /** 加入答案區 */ 213 - (void) addAnswer:(Question *) question { 214 // 5.1 刪除全部舊答案的button 215 [self.answerView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; 216 217 // 5.1 加入新答案 218 int answerCount = question.answer.length; // 答案字數 219 220 // 初始化尺寸信息 221 CGFloat answerWidth = 35; 222 CGFloat answerHeight = self.answerView.frame.size.height; 223 CGFloat answerMargin = 10; 224 CGFloat answerMarginLeft = (self.answerView.frame.size.width - answerWidth * answerCount - answerMargin * (answerCount - 1) ) / 2; 225 226 for (int i=0; i<question.answer.length; i++) { 227 // 計算位置 228 CGFloat answerX = answerMarginLeft + i * (answerWidth + answerMargin); 229 CGFloat answerY = 0; 230 231 UIButton *answerButton = [[UIButton alloc] initWithFrame:CGRectMake(answerX, answerY, answerWidth, answerHeight)]; 232 233 // 設置背景 234 [answerButton setBackgroundImage:[UIImage imageNamed:@"btn_answer"] forState: UIControlStateNormal]; 235 [answerButton setBackgroundImage:[UIImage imageNamed:@"btn_answer_highlighted"] forState: UIControlStateHighlighted]; 236 237 // 設置按鈕點擊事件,讓按鈕文字消失,相應的選項恢復 238 [answerButton addTarget:self action:@selector(onAnswerClicked:) forControlEvents:UIControlEventTouchUpInside]; 239 240 [self.answerView addSubview:answerButton]; 241 } 242 243 [self.view addSubview:self.answerView]; 244 } 245 246 /** 247 設置按鈕點擊事件,讓按鈕文字消失,相應的選項恢復 248 */ 249 - (void) onAnswerClicked:(UIButton *) answerButton { 250 // 1.設置答案標識 251 self.isAnswerCompleted = NO; 252 253 // 2.恢復相應的選項 254 NSString *answerTitle = [answerButton titleForState:UIControlStateNormal]; 255 for (UIButton *optionButton in self.optionsView.subviews) { 256 if ([answerTitle isEqualToString:[optionButton titleForState:UIControlStateNormal]] 257 && optionButton.isHidden) { 258 optionButton.hidden = NO; 259 break; 260 } 261 } 262 263 // 3.清除按鈕上的文字 264 [answerButton setTitle:nil forState:UIControlStateNormal]; 265 266 // 4.恢復答案文字顏色 267 for (UIButton *answerButton in self.answerView.subviews) { 268 [answerButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 269 } 270 } 271 272 /** 加入選項區 */ 273 - (void) addOptions:(Question *) question { 274 // 6.1 刪除舊選項 275 [self.optionsView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; 276 277 // 6.2 加入新選項 278 int optionsCount = question.options.count; 279 CGFloat optionWidth = 35; 280 CGFloat optionHeight = 35; 281 int columnCount = 7; 282 CGFloat optionMargin = 10; 283 CGFloat optionMarginLeft = (self.optionsView.frame.size.width - optionWidth * columnCount - optionMargin * (columnCount - 1)) / 2; 284 285 for (int i=0; i<optionsCount; i++) { 286 int rowNo = i / columnCount; // 當前行號,從0開始 287 int columnNo = i % columnCount; // 當前列號,從0開始 288 CGFloat optionX = optionMarginLeft + columnNo * (optionWidth + optionMargin); 289 CGFloat optionY = rowNo * (optionHeight + optionMargin); 290 291 UIButton *optionButton = [[UIButton alloc] initWithFrame:CGRectMake(optionX, optionY, optionWidth, optionHeight)]; 292 293 [optionButton setBackgroundImage:[UIImage imageNamed:@"btn_option"] forState:UIControlStateNormal]; 294 [optionButton setBackgroundImage:[UIImage imageNamed:@"btn_option_highlighted"] forState:UIControlStateHighlighted]; 295 296 [optionButton setTitle:question.options[i] forState:UIControlStateNormal]; 297 298 [optionButton addTarget:self action:@selector(onOptionClicked:) forControlEvents:UIControlEventTouchUpInside]; 299 300 [self.optionsView addSubview:optionButton]; 301 } 302 303 [self.view addSubview:self.optionsView]; 304 } 305 306 // 使點擊到的選項消失 307 - (void) onOptionClicked:(UIButton *) optionButton { 308 // 1.如果答案尚未填滿,使選中的選項消失 309 if (self.isAnswerCompleted) { 310 return; 311 } 312 313 optionButton.hidden = YES; 314 315 // 2.使消失的文字出現在答案區上,判斷是否已經完成 316 NSString *optionTitle = [optionButton titleForState:UIControlStateNormal]; 317 318 // 遍歷答案按鈕 319 for (int i=0; i<self.answerView.subviews.count; i++) { 320 // 已經遍歷到了最后一個答案按鈕,證明已經完成了所有答案 321 if (i == self.answerView.subviews.count - 1) { 322 self.isAnswerCompleted = YES; 323 } 324 325 UIButton *answerButton = self.answerView.subviews[i]; 326 NSString *answerTitle = [answerButton titleForState:UIControlStateNormal]; 327 328 // 如果該答案按鈕上沒有文字,則是空,填入文字 329 if (answerTitle.length == 0) { 330 // 按鈕默認的字體顏色是白色, 手動設為黑色 331 [answerButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 332 [answerButton setTitle:optionTitle forState:UIControlStateNormal]; 333 334 break; 335 } 336 } 337 338 [self dealWithAnswer]; 339 } 340 341 /** 處理答案 */ 342 - (void) dealWithAnswer { 343 if (self.isAnswerCompleted) { 344 Question *question = self.questions[self.index]; 345 NSMutableString *answerStr = [NSMutableString string]; 346 347 // 拼接已經完成的答案 348 for (UIButton *completedAnswerButton in self.answerView.subviews) { 349 [answerStr appendString:[completedAnswerButton titleForState:UIControlStateNormal]]; 350 } 351 352 // 如果答對了 353 if ([answerStr isEqualToString:question.answer]) { 354 // 答案字體轉換稱為藍色 355 for (UIButton *correctAnswerButton in self.answerView.subviews) { 356 [correctAnswerButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; 357 } 358 359 // 延遲指定時間后跳入下一題 360 [self performSelector:@selector(onNextImgButtonClicked) withObject:nil afterDelay:0.5]; 361 362 // 加分 363 [self calScore:1000]; 364 } 365 else { 366 for (UIButton *correctAnswerButton in self.answerView.subviews) { 367 // 答案字體轉換稱為紅色 368 [correctAnswerButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; 369 } 370 } 371 } 372 } 373 374 /** 原圖狀態點擊放大,大圖狀態點擊恢復原狀 */ 375 - (IBAction)onImageClicked { 376 // 使用遮蓋是否存在判斷圖片狀態 377 378 // 1.遮蓋不存在,放大圖片 379 if (nil == self.cover) { 380 [self onEnlargeImgButtonClicked]; 381 } 382 else { 383 // 2.遮蓋存在,恢復圖片 384 [self smallImg]; 385 } 386 } 387 388 /** 計算分數 */ 389 - (void) calScore:(int) score { 390 self.score += score; 391 [self.scoreButton setTitle:[NSString stringWithFormat:@"%d", self.score] forState:UIControlStateNormal]; 392 } 393 394 @end
Question.h:
1 // 2 // Question.h 3 // CrazyGuessGame 4 // 5 // Created by hellovoidworld on 14/11/26. 6 // Copyright (c) 2014年 hellovoidworld. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 11 @interface Question : NSObject 12 13 @property(nonatomic, copy) NSString *answer; 14 @property(nonatomic, copy) NSString *title; 15 @property(nonatomic, copy) NSString *icon; 16 @property(nonatomic, strong) NSArray *options; 17 18 - (instancetype) initWithDictionary:(NSDictionary *) dictionary; 19 + (instancetype) initWithDictionary:(NSDictionary *) dictionary; 20 21 @end
Question.m
1 // 2 // Question.m 3 // CrazyGuessGame 4 // 5 // Created by hellovoidworld on 14/11/26. 6 // Copyright (c) 2014年 hellovoidworld. All rights reserved. 7 // 8 9 #import "Question.h" 10 11 @implementation Question 12 13 - (instancetype) initWithDictionary:(NSDictionary *) dictionary { 14 if (self = [super init]) { 15 self.title = dictionary[@"title"]; 16 self.icon = dictionary[@"icon"]; 17 self.answer = dictionary[@"answer"]; 18 self.options = dictionary[@"options"]; 19 } 20 21 return self; 22 } 23 24 + (instancetype) initWithDictionary:(NSDictionary *) dictionary { 25 return [[self alloc] initWithDictionary:dictionary]; 26 } 27 28 @end
優質網站模板
- 1
- 2
- 3
最新文章推薦