功能分析
步驟分析
應(yīng)用截圖:
這個(gè)小的綜合實(shí)例涉及到的知識(shí)點(diǎn):
九宮格分析:
搭建九宮格的步驟
//顯示的文字@PRoperty(nonatomic,copy) NSString *text;//字體@property(nonatomic,retain) UIFont *font;//文字顏色@property(nonatomic,retain) UIColor *textColor;//對(duì)齊模式(比如左對(duì)齊、居中對(duì)齊、右對(duì)齊)@property(nonatomic) NSTextAlignment textAlignment;
//系統(tǒng)默認(rèn)字體+ (UIFont *)systemFontOfSize:(CGFloat)fontSize;//粗體+ (UIFont *)boldSystemFontOfSize:(CGFloat)fontSize;//斜體+ (UIFont *)italicSystemFontOfSize:(CGFloat)fontSize;
//設(shè)置按鈕的文字- (void)setTitle:(NSString *)title forState:(UIControlState)state;//設(shè)置按鈕的文字顏色- (void)setTitleColor:(UIColor *)color forState:(UIControlState)state;//設(shè)置按鈕內(nèi)部的小圖片- (void)setImage:(UIImage *)image forState:(UIControlState)state;//設(shè)置按鈕的背景圖片- (void)setBackgroundImage:(UIImage *)image forState:(UIControlState)state;//設(shè)置按鈕的文字字體(需要拿到按鈕內(nèi)部的label來(lái)設(shè)置)//btn.titleLabel.font = [UIFont systemFontOfSize:13];
整個(gè)應(yīng)用的思路分析:
1 /************************ "應(yīng)用管理"思路分析************************/ 2 3 1. 功能分析 4 * 以九宮格的方式展示應(yīng)用信息 5 * 點(diǎn)擊"下載"按鈕做出相應(yīng)操作 6 7 8 2. 步驟分析 9 * 從對(duì)應(yīng)的app.plist文件中加載數(shù)據(jù)("應(yīng)用信息") 10 * 根據(jù)加載好的"應(yīng)用信息"的數(shù)據(jù)創(chuàng)建對(duì)應(yīng)的view 11 * 監(jiān)聽(tīng)"下載"按鈕的點(diǎn)擊事件 12 13 14 3. 開始編寫代碼 15 16 1> 根據(jù)apps中的數(shù)據(jù), 創(chuàng)建相應(yīng)的view并展示到屏幕上 17 一、分析: 18 * 在界面一加載完畢就看到應(yīng)用, 所以要在viewDidLoad方法中創(chuàng)建應(yīng)用 19 * 分析每個(gè)一個(gè)應(yīng)用中都包含了一個(gè)UIImageView、UILabel、UIButton 20 * 為了便于統(tǒng)一管理, 為每一個(gè)應(yīng)用封裝一個(gè)UIView, 然后在該UIView內(nèi)部再放上面3個(gè)子控件 21 22 二、創(chuàng)建UIView, 并添加到屏幕上 23 * 通過(guò)代碼實(shí)現(xiàn),一個(gè)一個(gè)的創(chuàng)建UIView 24 * 保證每行的應(yīng)用之間的間距相等, 所以要計(jì)算每行的應(yīng)用之間的間距{間距 = (屏幕寬度 - (3 * 每個(gè)應(yīng)用的寬度)) / 4} 25 26 1. 添加一個(gè)UIView 27 /* // 添加第一個(gè)格子 28 UIView *appView = [[UIView alloc]init];//創(chuàng)建 29 CGFloat appViewX = 20; 30 CGFloat appViewY = 30; 31 CGFloat appViewW = 100; 32 CGFloat appViewH = 120; 33 appView.frame = CGRectMake(appViewX, appViewY, appViewW, appViewH);//設(shè)置frame 34 [self.view addSubview:appView]; 35 appView.backgroundColor = [UIColor redColor];//設(shè)置背景色 36 */ 37 2. 通過(guò)循環(huán)根據(jù)app的個(gè)數(shù)添加多個(gè)UIView, 但是會(huì)覆蓋, 因?yàn)閒rame相同 38 for循環(huán)的次數(shù)取決于應(yīng)用的個(gè)數(shù)(這里讀取plist文件的數(shù)據(jù),根據(jù)數(shù)據(jù)的長(zhǎng)度確定循環(huán)的次數(shù)) 39 40 2> 懶加載數(shù)據(jù) 41 * 通過(guò)懶加載的方式加載app.plist中的數(shù)據(jù)到NSArray中 42 /* - (NSArray *)apps{ 43 44 if (_apps == nil) { 45 //1.獲取plis文件的路徑 46 NSString *path = [[NSBundle mainBundle]pathForResource:@"app.plist" ofType:nil]; 47 //2.讀取文件 48 _apps = [NSArray arrayWithContentsOfFile:path]; 49 50 } 51 return _apps; 52 } 53 54 */ 55 56 3. 計(jì)算第一個(gè)UIView的x和y(注意將里面的具體數(shù)字提取出來(lái),便于后面使用和擴(kuò)展)leftMargin ,topMaring,spacexMarign,spaceyMargrin 57 58 4. 然后分析每個(gè)UIView的x和y,找出規(guī)律: 59 x = leftMargin +列號(hào) *(spacexMargin + appViewW); 60 Y = topMargin + 行號(hào)*(spaceyMargin + appViewH); 61 ) 62 63 5. 引入需要基礎(chǔ)每個(gè)UIView所在的行的索引和列的索引 64 int row = i /3;//行號(hào) 65 int col = i % 3;//列號(hào) 66 67 6.設(shè)置view的frame 68 CGFloat appViewX = leftMargin + (appViewW + spaceX)*col; 69 CGFloat appViewY = topMargin + (appViewH + spaceY )*row; 70 // 2.2設(shè)置frame 71 appView.frame = CGRectMake(appViewX, appViewY, appViewW, appViewH); 72 73 74 75 */ 76 77 78 4. 在每個(gè)UIView中創(chuàng)建3個(gè)子元素: UIImageView、UILabel、UIButton 79 * UIImageView: 80 CGFloat iconW = 60; 81 CGFloat iconH = 60; 82 CGFloat iconX = (appView.frame.size.width - iconW) * 0.5; 83 CGFloat iconY = 0;) 84 85 * UILabel: 86 CGFloat titleW = appW; 87 CGFloat titleH = 20; 88 CGFloat titleX = 0; 89 CGFloat titleY = iconY + iconH; 90 91 * UIButton 92 CGFloat downloadW = appViewW - downLoadBtnX *2; 93 CGFloat downloadH = 30; 94 CGFloat downloadX = 10; 95 CGFloat downloadY = nameLabelY + nameLabelH + 10; 96 downloadBtn.frame = CGRectMake(downloadX, downloadY, downloadW, downloadH); 97 98 99 5> 向UIImageView、UILabel、UIButton中添加數(shù)據(jù)100 1.取得字典101 NSDictionary *dict = self.apps[i];102 head.image = [UIImage imageNamed:dict[@"icon"]];//圖片賦值數(shù)據(jù)103 nameLabel.text = dict[@"name"];//名字賦值數(shù)據(jù)104 [downLoadBtn setTitle:@"下載" forState:UIControlStateNormal];//設(shè)置文字105 106 107 108 109 110 6> 修改Label的字體、文字居中顯示、按鈕背景圖片、設(shè)置按鈕的字體大小。111 // 2.5.2設(shè)置文字大小112 nameLabel.font = [UIFont systemFontOfSize:13];113 // 2.5.3設(shè)置文字居中114 nameLabel.textAlignment = NSTextAlignmentCenter;115 downLoadBtn setBackgroundImage:[UIImage imageNamed:@"buttongreen"] forState:UIControlStateNormal];116 [downLoadBtn setBackgroundImage: [UIImage imageNamed:@"buttongreen_highlighted"] forState:UIControlStateHighlighted];117 118 119 120 * 了解按鈕的內(nèi)部結(jié)構(gòu):按鈕至少有兩個(gè)控件,一個(gè)label,一個(gè)imageView;121 *修改按鈕文字的大小直接拿到他的對(duì)應(yīng)的label進(jìn)行設(shè)置即可122 downLoadBtn.titleLabel.font = [UIFont systemFontOfSize:14];123 124 125 * 注意: 修改按鈕的文字的時(shí)候還是通過(guò)setTitle:來(lái)修改(這個(gè)方法可以設(shè)置不同狀態(tài)), 不要直接通過(guò)titleLabel來(lái)修改文字。126 //* UIImageView設(shè)置圖片居中:contentMode屬性127 128 129 130 7. 字典轉(zhuǎn)模型131 0> 字典:用來(lái)存儲(chǔ)數(shù)據(jù)的,用鍵值對(duì)存儲(chǔ)數(shù)據(jù),是一個(gè)nsdictionary ,(不好處:key值容易寫錯(cuò))132 模型: 用來(lái)存儲(chǔ)數(shù)據(jù)的,一個(gè)字典對(duì)應(yīng)一個(gè)模型,模型用屬性來(lái)存儲(chǔ)數(shù)據(jù),是以純潔的object對(duì)象133 @property(nonatomic,copy)NSString *name;134 @property(nonatomic,copy)NSString *icon;135 136 字典轉(zhuǎn)模型:一個(gè)字典對(duì)應(yīng)一個(gè)模型,把鍵值對(duì)轉(zhuǎn)化模型的屬性,就是把鍵值對(duì)的value賦值給模型的屬性137 // appViewModel.name = dict[@"name"];138 // appViewModel.icon = dict[@"icon"];139 140 屬性的類型和名稱:屬性的類型和鍵值對(duì)的key值的類型是一樣,最好名稱也和key值的名稱一樣141 1> 為什么要把字典轉(zhuǎn)成模型?142 * 字典缺陷:143 0> 寫代碼的時(shí)候字典的鍵沒(méi)有智能提示, 但是模型的屬性可以有智能提示144 1> "鍵"是字符串, 如果寫錯(cuò)了, 編譯器不報(bào)錯(cuò)(在編譯的時(shí)候不報(bào)錯(cuò)), 運(yùn)行時(shí)可能出錯(cuò), 出錯(cuò)了很難找錯(cuò)。145 146 147 148 149 150 151 152 * 把字典轉(zhuǎn)模型的過(guò)程封裝到"模型"內(nèi)部153 * 原因: 將來(lái)的這個(gè)"模型"可能會(huì)在很多地方被用到(比如有很多個(gè)控制器都會(huì)使用這個(gè)模型), 那么每次用到模型的地方都需要寫一次把字典中的數(shù)據(jù)賦給模型屬性的代碼, 此時(shí)如果把這些賦值語(yǔ)句封裝到模型內(nèi)部, 會(huì)大大簡(jiǎn)化了使用復(fù)雜度與代碼量。154 * 思路:155 1> 在模型中接收一個(gè)NSDictionary的參數(shù), 然后在模型內(nèi)部把NSDictioanry中的鍵值對(duì)數(shù)據(jù)賦值給模型的屬性。156 2> 封裝一個(gè)initWithDict方法和一個(gè)appWithDict方法(規(guī)范)157 - (id)initWithDict:(NSDictionary *)dict{158 159 160 161 if (self = [super init]) {162 self.name = dict[@"name"];163 self.icon = dict[@"icon"];164 165 }166 return self;167 168 169 }170 171 + (id)appViewWithDict:(NSDictionary *)dict{172 // AppViewModel *appViewModel = [[AppViewModel alloc]initWithDict:dict];173 //174 // return appViewModel;175 return [[self alloc ]initWithDict:dict];//必須用self,因?yàn)檫@樣創(chuàng)建出來(lái)的對(duì)象才是真實(shí)我們需要的對(duì)象,176 回憶:GoodApp;177 }178 179 180 181 * id與instancetype的介紹182 1. 使用id作為方法返回值的問(wèn)題:183 1> 在接收方法的返回值的時(shí)候可以使用任何類型來(lái)接收, 編譯都不報(bào)錯(cuò), 但是運(yùn)行時(shí)可能出錯(cuò)。184 185 2. instancetype需要注意的點(diǎn)186 1> instancetype在類型表示上, 與id意思一樣, 都表示任何對(duì)象類型187 2> instancetype只能用作返回值類型, 不能向id一樣聲明變量、用作參數(shù)等188 3> 使用instancetype, 編譯器會(huì)檢測(cè)instancetype的真實(shí)類型, 如果類型不匹配, 編譯時(shí)就警告了。(instancetype出現(xiàn)在哪個(gè)類型中就表示對(duì)應(yīng)的類型)189 190 2> xib與storyboard既然都是描述軟件界面的, 有什么區(qū)別嗎?191 * xib 一般只用來(lái)描述一個(gè)界面中的某部分內(nèi)容(用來(lái)描述局部UI界面)。192 193 * storyboard 一般用來(lái)描述軟件的多個(gè)界面, 以及不同界面之間的跳轉(zhuǎn)關(guān)系。194 195 196 7.使用xib精簡(jiǎn)代碼。197 1> 什么是xib? xib能做什么?198 * 用來(lái)描述軟件的局部界面的文件。199 * 如果沒(méi)有xib, 所有的界面都需要通過(guò)代碼來(lái)手動(dòng)創(chuàng)建。200 * 進(jìn)行創(chuàng)建xib,command +n ->user interface -> view;201 * 有了xib以后, 可以在xib中進(jìn)行可視化開發(fā),進(jìn)行拖拽三個(gè)小的控件202 * 然后加載xib文件的.203 UIView *appView = [[NSBundle mainBundle]loadNibNamed:@"appView" owner:nil options:nil][0];204 205 8. 自定義View。創(chuàng)建屬性、傳遞Model進(jìn)去。206 *自定義一個(gè)appview用來(lái)描述xib,然后我們需要把xib的真實(shí)類型改變?yōu)閍ppview(必須有這一步)207 *用拖線的方式拿到里面的三個(gè)小的控件208 *給這些控件進(jìn)行賦數(shù)據(jù),數(shù)據(jù)在模型中,我們擁有一個(gè)模型屬性,為了從控制器中拿到模型,我們重寫模型的set方法,209 這樣我們就可以通過(guò)set方法把控制器中的模型數(shù)據(jù)賦值給我們內(nèi)部的模型,拿到模型后我們進(jìn)行控件的賦值,210 //重寫模型的set方法211 - (void)setAppViewModel:(AppViewModel *)appViewModel{212 _appViewModel = appViewModel;213 214 215 self.head.image = [UIImage imageNamed:appViewModel.icon];216 self.nameLabel.text = appViewModel.name;217 218 219 }220 *這樣我們就可以在控制器中直接賦值模型,然后顯示數(shù)據(jù)221 // 2.4賦值222 AppViewModel *appViewModel = self.apps[i];223 224 225 appOldView.appViewModel = appViewModel;226 227 228 229 230 231 9. 封裝創(chuàng)建View的代碼, 讓用戶不知道是通過(guò)xib創(chuàng)建的還是通過(guò)代碼創(chuàng)建的,安全,擴(kuò)展性比較好。232 * 封裝一個(gè)類方法233 + (instancetype )loadNib{234 return [[NSBundle mainBundle]loadNibNamed:@"appView" owner:nil options:nil][0];235 236 237 238 }239 240 10.下載按鈕的操作241 // 1.讓按鈕不能點(diǎn)擊242 243 btn.enabled = NO;244 // 2.添加一個(gè)label245 // 2.1創(chuàng)建一個(gè)label246 UILabel *msgLabel = [[UILabel alloc]init];247 // 2.2設(shè)中l(wèi)abel的frame248 CGFloat msgLabelW = 150;249 CGFloat msgLabelH = 30;250 CGFloat msgLabelX = (self.superview.frame.size.width - msgLabelW)*0.5;251 CGFloat msgLabelY = (self.superview.frame.size.height - msgLabelH)*0.5;252 msgLabel.frame = CGRectMake(msgLabelX, msgLabelY, msgLabelW, msgLabelH);253 // 2.3設(shè)置背景色254 msgLabel.backgroundColor = [UIColor blackColor];255 // 2.4添加256 [self.superview addSubview:msgLabel];257 // 2.5設(shè)置文字258 msgLabel.text = @"正在下載";259 // 2.6設(shè)置文字顏色260 msgLabel.textColor = [UIColor redColor];261 // 2.7讓文字居中262 msgLabel.textAlignment = NSTextAlignmentCenter;263 // 2.8設(shè)置label為圓角264 // 2.8.1設(shè)置圓角的半徑265 msgLabel.layer.cornerRadius = 8;266 // 2.8.2多余的部分切掉267 msgLabel.layer.masksToBounds = YES;268 // 2.9設(shè)置透明度,0~1,0代表完全透明,1代表完全不透明269 msgLabel.alpha = 0.0;270 // 2.10設(shè)置動(dòng)畫,(block式動(dòng)畫)271 // animateWithDuration:動(dòng)畫執(zhí)行的時(shí)間272 // animations:執(zhí)行動(dòng)畫的代碼273 // completion:動(dòng)畫完成后執(zhí)行的代碼274 [UIView animateWithDuration:3 animations:^{275 276 msgLabel.alpha = 0.5;277 } completion:^(BOOL finished) {278 if (finished) {279 // delay:延遲:表示動(dòng)畫動(dòng)畫延遲多長(zhǎng)時(shí)間以后執(zhí)行280 [UIView animateWithDuration:3 delay:0.5 options:UIViewAnimationOptionCurveLinear animations:^{281 msgLabel.alpha = 0.0;282 } completion:^(BOOL finished) {283 // 讓msgLabel這個(gè)控件從父類中移除284 [msgLabel removeFromSuperview];285 }];286 }287 }];288 *注意動(dòng)畫的使用:不是頭尾式,用的是block,block可以在動(dòng)畫執(zhí)行后做一些事情.289 290 11.xib文件的加載過(guò)程。291 0> 根據(jù)路徑, 搜索對(duì)應(yīng)的xib文件(nib文件)292 1> 加載xib文件的時(shí)候, 會(huì)按順序加載xib文件中的每個(gè)控件。293 2> 對(duì)于每個(gè)控件, 創(chuàng)建的時(shí)候都會(huì)查找對(duì)應(yīng)的Class屬性中配置的是那個(gè)類, 那么就創(chuàng)建對(duì)應(yīng)的類的對(duì)象。294 3> 獲取到某個(gè)視圖以后, 按照在xib中配置的屬性的值, 放在數(shù)組中,295 4> 最后返回一個(gè)數(shù)組, 這個(gè)數(shù)組中包含創(chuàng)建的所有元素對(duì)象。296 297 12.使用xib封裝一個(gè)自定義view的步驟298 1> 新建一個(gè)AppView.xib文件來(lái)描述AppView內(nèi)部的結(jié)構(gòu)299 2> 新建一個(gè)繼承UIView的自定義view,假設(shè)類名叫做(appView)300 3> 修改UIView的類型為appView真實(shí)類型301 4> 將內(nèi)部的子控件跟appView進(jìn)行屬性連線302 5> appView提供一個(gè)模型屬性303 6> 重寫模型屬性的set方法,因?yàn)樵趕et方法中可以拿到外界控制器傳遞的模型數(shù)據(jù)304 7> 把模型數(shù)據(jù)拆開,分別設(shè)置數(shù)據(jù)到對(duì)應(yīng)的子控件中305 8> 補(bǔ)充:提供一個(gè)創(chuàng)建AppView的類方法,將讀取xib文件的代碼屏蔽起來(lái)306 307 308 309 310 311 312 313 ------------ 補(bǔ)充兩個(gè)知識(shí)點(diǎn)------------314 1. 根據(jù)subViews[index]獲取子元素315 2. 通過(guò)[appView viewWithTag:10]根據(jù)tag的值來(lái)獲取對(duì)應(yīng)的子元素。316 以上兩種方式返回值都是UIView將來(lái)還需要強(qiáng)制類型轉(zhuǎn)換。317 318 319 320 3. 設(shè)置Label的圓角效果321 // 4. 設(shè)置Label為圓角322 // 設(shè)置四周圓角的半徑323 lblMsg.layer.cornerRadius = 5;324 // 把多余的部分裁剪掉。325 lblMsg.layer.masksToBounds = YES;
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注