本項目是取自傳智播客的教學項目,加入筆者的修改和潤飾。
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface Question : NSObjec
@property (nonatomic, copy) NSString *answer;
@property (nonatomic, copy) NSString *icon;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, strong) NSArray *options;
- (instancetype)initWithDict:(NSDictionary *)dict;
+ (instancetype)questionWithDict:(NSDictionary *)dict;
@property (nonatomic, strong, readonly) UIImage *image;
/** 返回所有題目數組 */
+ (NSArray *)questions;
/** 打亂備選文字的數組 */
- (void)randamOptions;
@end
#import "Question.h"
@implementation Question
@synthesize image = _image;
- (UIImage *)image
{
if (_image == nil) {
_image = [UIImage imageNamed:self.icon];
}
return _image;
}
- (instancetype)initWithDict:(NSDictionary *)dict
{
self = [super init];
if (self) {
[self setValuesForKeysWithDictionary:dict];
// 對備選按鈕進行亂序,只在加載的時候,做一次亂序
[self randamOptions];
}
return self;
}
+ (instancetype)questionWithDict:(NSDictionary *)dict
{
return [[self alloc] initWithDict:dict];
}
+ (NSArray *)questions
{
NSArray *array = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"questions.plist" ofType:nil]];
NSMutableArray *arrayM = [NSMutableArray array];
for (NSDictionary *dict in array) {
[arrayM addObject:[self questionWithDict:dict]];
}
return arrayM;
}
- (void)randamOptions
{
// 對options數組亂序
self.options = [self.options sortedArrayUsingComparator:^NSComparisonResult(NSString *str1, NSString *str2) {
int seed = arc4random_uniform(2);
if (seed) {
return [str1 compare:str2];
} else {
return [str2 compare:str1];
}
}];
NSLog(@"%@", self.options);
}
@end
#import "ViewController.h"
#import "Question.h"
#define kButtonWidth 35
#define kButtonHeight 35
#define kButtonMargin 10
#define kTotolCol 7
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIButton *iconButton;//中間圖像
@property (weak, nonatomic) IBOutlet UIButton *scoreButton;//分數
@property (weak, nonatomic) IBOutlet UILabel *noLabel;
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
@property (weak, nonatomic) IBOutlet UIButton *nextQuestionButton;
@property (nonatomic, strong) NSArray *questions;//模型數組
@property (weak, nonatomic) IBOutlet UIView *answerView;//擺放答案按鈕的答案區
@property (weak, nonatomic) IBOutlet UIView *optionsView;//擺放備選答案的備選答案區
@property (nonatomic, assign) int index;//題目索引
@property (nonatomic, strong) UIButton *cover;//蒙板
@end
@implementation ViewController
//getter方法懶加載問題數組
- (NSArray *)questions
{
if (_questions == nil) {
_questions = [Question questions];
}
return _questions;
}
//getter方法懶加載蒙板
- (UIButton *)cover
{
if (_cover == nil) {
//1. 設置蒙板大小:與窗口大小一致
_cover = [[UIButton alloc] initWithFrame:self.view.bounds];
//2. 設置蒙板顏色:灰色
_cover.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.5];
//3. 添加模版到view
[self.view addSubview:_cover];
//4. 使蒙板無法響應事件(alpha<0.01無法接受到消息)
_cover.alpha = 0.0;
//設定蒙板的監聽事件:點擊蒙板觸發bigImage方法
[_cover addTarget:self action:@selector(bigImage) forControlEvents:UIControlEventTouchUpInside];
}
return _cover;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//初始界面
self.index = -1;
[self nextQuestion];
}
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
#pragma mark - 大圖小圖切換
/**
* 大圖小圖顯示切換
*/
- (IBAction)bigImage
{
// 如果沒有放大,就放大,否則就縮小
// 1. 通過蒙板的alpha來判斷按鈕是否已經被放大:當蒙板無法響應時間的時候即圖片被點擊放大
if (self.cover.alpha == 0.0) { // 放大
// 2. 將圖像按鈕弄到最前面
// bringSubviewToFront將子視圖前置
[self.view bringSubviewToFront:self.iconButton];
// 3. 動畫放大圖像按鈕
CGFloat w = self.view.bounds.size.width;
CGFloat h = w;
CGFloat y = (self.view.bounds.size.height - h) * 0.5;
[UIView animateWithDuration:1.0f animations:^{
//圖片放大后的大小
self.iconButton.frame = CGRectMake(0, y, w, h);
//蒙板的alpha
self.cover.alpha = 1.0;
}];
} else { // 縮小
[UIView animateWithDuration:1.0 animations:^{
// 將圖像恢復初始位置和大小
self.iconButton.frame = CGRectMake(90, 90, 150, 150);
// 蒙板不可用
self.cover.alpha = 0.0;
}];
}
}
#pragma mark - 下一題
/**
* 下一題目(主要的方法,盡量保留簡潔的代碼,主要體現思路和流程即可)
*/
- (IBAction)nextQuestion
{
// 1. 當前答題的索引,索引遞增
self.index++;
// 2. 從數組中按照索引取出題目模型數據,取出某一數組元素
Question *question = self.questions[self.index];
// 3. 設置基本信息
[self setupBasicInfo:question];
// 4. 設置答案按鈕
[self creatAnswerButtons:question];
// 5. 設置備選按鈕
[self creatOptionsButtons:question];
}
//設置基本信息
- (void)setupBasicInfo:(Question *)question
{
//1. 序號
self.noLabel.text = [NSString stringWithFormat:@"%d/%d", self.index + 1, self.questions.count];
//2. 問題名稱
self.titleLabel.text = question.title;
//3. 圖像
[self.iconButton setImage:[UIImage imageNamed:question.icon] forState:UIControlStateNormal];
// 如果到達最后一題,禁用下一題按鈕
self.nextQuestionButton.enabled = (self.index < self.questions.count - 1);
}
//設置答案按鈕
- (void)creatAnswerButtons:(Question *)question
{
// 首先清除掉答題區內的所有按鈕
// 所有的控件都繼承自UIView,多態的應用
for (UIView *btn in self.answerView.subviews) {
[btn removeFromSuperview];
}
//按鈕的總寬度
CGFloat answerW = self.answerView.bounds.size.width;
//按鈕的個數等於答案的字數
int length = question.answer.length;
//最左邊的按鈕的x坐標
CGFloat answerX = (answerW - kButtonWidth * length - kButtonMargin * (length - 1)) * 0.5;
// 創建所有答案的按鈕
for (int i = 0; i < length; i++) {
//第i個按鈕的x坐標
CGFloat x = answerX + i * (kButtonMargin + kButtonWidth);
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(x, 0, kButtonWidth, kButtonHeight)];
//默認情況下白色;點擊之后黑色
[btn setBackgroundImage:[UIImage imageNamed:@"btn_answer"] forState:UIControlStateNormal];
[btn setBackgroundImage:[UIImage imageNamed:@"btn_answer_highlighted"] forState:UIControlStateHighlighted];
//按鈕中文字黑色
[btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[self.answerView addSubview:btn];
// 添加按鈕監聽方法:answerClick:
[btn addTarget:self action:@selector(answerClick:) forControlEvents:UIControlEventTouchUpInside];
}
}
// 設置備選按鈕
- (void)creatOptionsButtons:(Question *)question
{
// 問題:每次調用下一題方法時,都會重新創建21個按鈕
// 解決:如果按鈕已經存在,並且是21個,只需要更改按鈕標題即可
if (self.optionsView.subviews.count != question.options.count) {
// 清楚所有按鈕
for (UIView *view in self.optionsView.subviews) {
[view removeFromSuperview];
}
//備選按鈕區寬度
CGFloat optionW = self.optionsView.bounds.size.width;
CGFloat optionX = (optionW - kTotolCol * kButtonWidth - (kTotolCol - 1) * kButtonMargin) * 0.5;
for (int i = 0; i < question.options.count; i++) {
int row = i / kTotolCol;
int col = i % kTotolCol;
CGFloat x = optionX + col * (kButtonMargin + kButtonWidth);
CGFloat y = row * (kButtonMargin + kButtonHeight);
UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(x, y, kButtonWidth, kButtonHeight)];
[btn setBackgroundImage:[UIImage imageNamed:@"btn_option"] forState:UIControlStateNormal];
[btn setBackgroundImage:[UIImage imageNamed:@"btn_option_highlighted"] forState:UIControlStateHighlighted];
[btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[self.optionsView addSubview:btn];
// 添加按鈕監聽方法:optionClick:
[btn addTarget:self action:@selector(optionClick:) forControlEvents:UIControlEventTouchUpInside];
}
NSLog(@"創建候選按鈕");
}
// 如果按鈕已經存在,在點擊下一題的時候,只需要設置標題即可
int i = 0;
for (UIButton *btn in self.optionsView.subviews) {
// 設置備選答案
[btn setTitle:question.options[i++] forState:UIControlStateNormal];
// 回復所有按鈕的隱藏狀態
btn.hidden = NO;
}
}
#pragma mark - 候選按鈕點擊方法
/** 點擊候選按鈕:文字移動到答案按鈕 */
- (void)optionClick:(UIButton *)button
{
// 1. 在答案區找到第一個文字為空的按鈕
UIButton *btn = [self firstAnswerButton];
// 如果沒有找到按鈕,直接返回
if (btn == nil) return;
// 2. 將button的標題設置給答案區的按鈕
[btn setTitle:button.currentTitle forState:UIControlStateNormal];
// 3. 將button隱藏
button.hidden = YES;
// 4. 判斷結果
[self judge];
}
/** 判斷結果 */
- (void)judge
{
// 如果四個按鈕都有文字,才需要判斷結果
// 遍歷所有答題區的按鈕
BOOL isFull = YES;
NSMutableString *strM = [NSMutableString string];
for (UIButton *btn in self.answerView.subviews) {
if (btn.currentTitle.length == 0) {
// 只要有一個按鈕沒有字
isFull = NO;
break;
} else {
// 有字,拼接臨時字符串
[strM appendString:btn.currentTitle];
}
}
if (isFull) {
// 判斷是否和答案一致
// 根據self.index獲得當前的question
Question *question = self.questions[self.index];
// 如果一致,進入下一題
if ([strM isEqualToString:question.answer]) {
[self setAnswerButtonsColor:[UIColor blueColor]];
// 增加分數
[self changeScore:800];
// 等待0.5秒,進入下一題
[self performSelector:@selector(nextQuestion) withObject:nil afterDelay:0.5];
} else {
// 如果不一致,修改按鈕文字顏色,提示用戶
[self setAnswerButtonsColor:[UIColor redColor]];
}
}
}
/** 修改答題區按鈕的顏色 */
- (void)setAnswerButtonsColor:(UIColor *)color
{
for (UIButton *btn in self.answerView.subviews) {
[btn setTitleColor:color forState:UIControlStateNormal];
}
}
// 在答案區找到第一個文字為空的按鈕
- (UIButton *)firstAnswerButton
{
// 取按鈕的標題
// 遍歷答題區所有按鈕
for (UIButton *btn in self.answerView.subviews) {
if (btn.currentTitle.length == 0) {//當前按鈕上的文字長度為0
return btn;
}
}
return nil;
}
#pragma mark - 答題區按鈕點擊方法
- (void)answerClick:(UIButton *)button
{
// 1. 如果按鈕沒有字,直接返回
if (button.currentTitle.length == 0) return;
// 2. 如果有字,清除文字,候選區按鈕顯示
// 1> 使用button的title去查找候選區中對應的按鈕
UIButton *btn = [self optionButtonWithTilte:button.currentTitle isHidden:YES];
// 2> 在備選答案區顯示對應按鈕
btn.hidden = NO;
// 3> 在答案區清除button的文字
[button setTitle:@"" forState:UIControlStateNormal];
// 4> 只要點擊了按鈕上的文字,意味着答題區的內容不完整
[self setAnswerButtonsColor:[UIColor blackColor]];
}
- (UIButton *)optionButtonWithTilte:(NSString *)title isHidden:(BOOL)isHidden
{
// 遍歷候選區中的所有按鈕
for (UIButton *btn in self.optionsView.subviews) {
if ([btn.currentTitle isEqualToString:title] && btn.isHidden == isHidden) {
return btn;
}
}
return nil;
}
#pragma mark - 提示功能
- (IBAction)tipClick
{
// 1. 把答題區中所有的按鈕清空
for (UIButton *btn in self.answerView.subviews) {
// 用代碼執行點擊答題按鈕的操作
[self answerClick:btn];
}
// 2. 把正確答案的第一個字,設置到答題區中
// 1> 知道答案的第一個字
Question *question = self.questions[self.index];
NSString *first = [question.answer substringToIndex:1];
UIButton *btn = [self optionButtonWithTilte:first isHidden:NO];
[self optionClick:btn];
// 扣分
[self changeScore:-1000];
}
#pragma mark - 分數處理
- (void)changeScore:(int)score
{
// 取出當前的分數
int currentScore = self.scoreButton.currentTitle.intValue;
// 使用score調整分數
currentScore += score;
// 重新設置分數
[self.scoreButton setTitle:[NSString stringWithFormat:@"%d", currentScore] forState:UIControlStateNormal];
}
@end
_cover.alpha = 0.0;
[self.view bringSubviewToFront:self.iconButton];
[UIView animateWithDuration:1.0f animations:^{
//圖片放大后的大小
self.iconButton.frame = CGRectMake(0, y, w, h);
//蒙板的alpha
self.cover.alpha = 1.0;
}];
for (UIView *btn in self.answerView.subviews) {
[btn removeFromSuperview];
}
self.optionsView.subviews.count
- (UIButton *)firstAnswerButton
{
for (UIButton *btn in self.answerView.subviews) {
if (btn.currentTitle.length == 0) {
return btn;
}
}
return nil;
}
[self performSelector:@selector(nextQuestion) withObject:nil afterDelay:0.5];
@property(nonatomic,readonly,retain) NSString *currentTitle;
@property(nonatomic,readonly,retain) UIColor *currentTitleColor;
@property(nonatomic,readonly,retain) UIImage *currentImage;
@property(nonatomic,readonly,retain) UIImage *currentBackgroundImage;
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。