此篇為針對ios中的UI基礎知識,為了能讓大家更清楚的理解,此整理中編寫了採用知識點+案例的方式,配有非常詳細的截圖和代碼註釋,添加了許多大白話進行解釋,如有錯誤之處,望指正,願與您相互交流學習,共同進步!---"會飛的猴子_阿新"本篇案例修改圖為(後面會逐步優化細節問題)主要內容從支付寶案例開始,... ...
此篇為針對ios中的UI基礎知識,為了能讓大家更清楚的理解,此整理中編寫了採用知識點+案例的方式,配有非常詳細的截圖和代碼註釋,添加了許多大白話進行解釋,如有錯誤之處,望指正,願與您相互交流學習,共同進步!---"會飛的猴子_阿新"
本篇案例修改圖為(後面會逐步優化細節問題)
主要內容從支付寶案例開始,重點在後面哦!
使用UITableViewControler控制器實現支付寶口碑案例
UITableViewControler 缺陷: 現階段只適合全屏的..
01-UITableViewController體驗
- 相當於一個控制器自帶tableView
- viewController管理的是view
- tableViewController管理的是tableView
- 也就是在tableViewController下,self.view = self.tableView
02-tableView的HeaderView和FooterView
- tableView的header - (x, y, width) 可以隨便指定,(height) 實際數值
- tableView的footer - (y, width) 可以隨便指定,(x, height) 實際數值
創建一個demo體驗一下:
1.準備:新建文件-->把預設的的viewController刪掉-->新建LJXTableViewController-->把Main.storyboard中預設的控制器刪掉-->重寫拖拽一個UITableViewController-->指定初始箭頭,指定class.
2.添加頭部視圖
- (void)viewDidLoad {
[super viewDidLoad];
UIView *headerView = [[UIView alloc]init];
headerView.backgroundColor =[UIColor redColor];
//把某個控制項設置到tableHeaderView上時,只有高度需要我們自己設置,前面 X , Y ,Width都可以直接給個0
headerView.frame = CGRectMake(0, 0, 0, 100);
//設置tableView的最頂部視圖
self.tableView.tableHeaderView = headerView;
//-->這裡只需要headerView賦值給tableHeaderView 這個屬性,內部就在添加到父控制項上我們就不用addSubview:
}
3.添加數據驗證一下頭部視圖跟 "一組和多組" 沒有關係
//
// LJXTableViewController.m
// LJX_tableView的頭部和尾部視圖
#import "LJXTableViewController.h"
@interface LJXTableViewController ()
@end
//重用標識
static NSString *ID = @"cell";
@implementation LJXTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIView *headerView = [[UIView alloc]init];
headerView.backgroundColor =[UIColor redColor];
//把某個控制項設置到tableHeaderView上時,只有高度需要我們自己設置,前面 X , Y ,Width都可以直接給個0
headerView.frame = CGRectMake(0, 0, 0, 100);
//設置tableView的最頂部視圖 註意:跟一組和多組沒有關係
self.tableView.tableHeaderView = headerView;
//-->這裡只需要headerView賦值給tableHeaderView 這個屬性,內部就在添加到父控制項上我們就不用addSubview:
//註冊cell
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:ID];
}
//2組
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 2;
}
//每組4行
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 4;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID forIndexPath:indexPath];
cell.textLabel.text =@(indexPath.row).description;//簡單設置數據,每個cell顯示一個行數
return cell;
}
@end
4.添加底部視圖
UIButton *footerBtn = [[UIButton alloc]init];
footerBtn.backgroundColor = [UIColor purpleColor]; //紫色背景
//把某個控制項設置到tableHeaderView上時,只有高度需要我們自己設置,前面 X , Y ,Width都可以直接給個0,但是x是可以改的,改了會有影響但不建議去改
footerBtn.frame = CGRectMake(0, 0, 0, 100);
//設置tableView的最底部視圖
self.tableView.tableFooterView = footerBtn;
03-星級評價-需求分析
1.滿星個數 "分數強轉成整形,如4.5轉成整形是4 那就表示有4顆滿星"
2.半星個數 "分數 - 整星個數如果不為0那說明就有一個半星"
3.空心個數 "for(NSInteger i = 已添加星星個數; i < 5; i++)"
每一個商家的評分不一樣,所以分值要動態傳入,去動態設置星星樣子
04-星級評價
4.1星級評價實現
創建實體文件夾,方便日後移植
為了方便最後整合代碼時的移植,不直接在控制器中實現,而是單獨創建繼承UIView的類,
//
// ZFBLeverStar.h
// LJX_星級評價
#import <UIKit/UIKit.h>
@interface ZFBLeverStar : UIView
///接收評分
@property (nonatomic, assign) CGFloat lever;
@end
//
// ZFBLeverStar.m
// LJX_星級評價
#import "ZFBLeverStar.h"
@implementation ZFBLeverStar
//重寫set方法在裡面處理顯示星星圖片的細節
-(void)setLever:(CGFloat)lever{
_lever = lever;
//1.滿星
//把傳過來的分數強轉為整型,整數值就是滿星的個數
NSInteger fullStartCount = (NSInteger)lever;
for(NSInteger i = 0 ; i < fullStartCount ; i++){
[self makeLeverStarWithImageName:@"full_star" andPosition:i];
}
//2.半星
// (取傳過來的個數) - (強轉後的整數),如果 > 0 就表示有半星
if((lever - fullStartCount)>0){
[self makeLeverStarWithImageName:@"half_star" andPosition:fullStartCount];
//如果添加了一個半星那把滿星個數的值做加1 用它當做 目前已經添加星星的總個數了
fullStartCount++;
}
//3.空星 "如果到這來還不夠5顆星 那剩下的就是空星的個數了"
for (NSInteger i = fullStartCount; i < 5; i++) {
[self makeLeverStarWithImageName:@"empty_star" andPosition:i];
}
}
/**
創建星星imageView
@param imageName 星星圖片
@param position 星星位置 從0開始
*/
-(void)makeLeverStarWithImageName:(NSString *)imageName andPosition:(NSInteger)position{
//1.創建imageView設置圖片,那麼imageView創建出來的就有尺寸
UIImageView *imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:imageName]];
//2.設置圖片的x
CGFloat imageViewX = position * imageView.image.size.width;
imageView.frame = CGRectMake(imageViewX, 0, imageView.image.size.width, imageView.image.size.height);
[self addSubview:imageView];
}
@end
//
// ViewController.m
// LJX_星級評價
#import "ViewController.h"
#import "ZFBLeverStar.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
ZFBLeverStar *leverStar = [[ZFBLeverStar alloc]init];
leverStar.frame = CGRectMake(100, 100, 60, 12);//素材中圖片2X的是大小24*24,高24/2=12, 寬為5顆*12=60
leverStar.backgroundColor = [UIColor purpleColor];
leverStar.lever = 2.5;//先傳一個2.5分驗證一下
[self.view addSubview:leverStar];
}
@end
4.2解決星星重覆創建問題
我們只創建添加,沒有管過移除啥的,顧導致傳一次分,創建一次....
解決重覆創建的問題
重寫初始化方法(初始化方法它只會調一次),那樣一創建leverStar這個控制項,裡面就自帶5顆星星imageView,
即對ZFBLeverStar.m做了修改
//
// ZFBLeverStar.m
// LJX_星級評價
#import "ZFBLeverStar.h"
@implementation ZFBLeverStar
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
//來了 直接把5個imageView創建添加好
for (NSInteger i = 0; i < 5; i++) {
UIImageView *imageView =[[UIImageView alloc]initWithImage:[UIImage imageNamed:@"full_star"]];//這個目的不是拿圖片,目的是隨便拿一張圖片,圖片就有了大小了
//設置圖片的x
CGFloat imageViewX = i * imageView.image.size.width;
imageView.frame = CGRectMake(imageViewX, 0, imageView.image.size.width, imageView.image.size.height);
[self addSubview:imageView];
}
}
return self;
}
//重寫set方法在裡面處理顯示星星圖片的細節
-(void)setLever:(CGFloat)lever{
_lever = lever;
//1.滿星
//把傳過來的分數強轉為整型,整數值就是滿星的個數
NSInteger fullStartCount = (NSInteger)lever;
for(NSInteger i = 0 ; i < fullStartCount ; i++){
[self makeLeverStarWithImageName:@"full_star" andPosition:i];
}
//2.半星
// (取傳過來的個數) - (強轉後的整數),如果 > 0 就表示有半星
if((lever - fullStartCount)>0){
[self makeLeverStarWithImageName:@"half_star" andPosition:fullStartCount];
//如果添加了一個半星那把滿星個數的值做加1 用它當做 目前已經添加星星的總個數了
fullStartCount++;
}
//3.空星 "如果到這來還不夠5顆星 那剩下的就是空星的個數了"
for (NSInteger i = fullStartCount; i < 5; i++) {
[self makeLeverStarWithImageName:@"empty_star" andPosition:i];
}
}
/**
創建星星imageView
@param imageName 星星圖片
@param position 星星位置 從0開始
*/
-(void)makeLeverStarWithImageName:(NSString *)imageName andPosition:(NSInteger)position{
//獲取相應位置的子控制項
UIImageView *imageView = self.subviews[position];
//設置圖片
imageView.image = [UIImage imageNamed:imageName];
}
@end
4.3 最後深入的優化
這次優化的目的是:日後星級評價更加的方便.--->外部不管用純代碼還有用xib還是用storyboard都比較方便.
如何不想使用代碼方式
使用storyboard
運行ok
支付寶口碑案例開始
自定義cell有3種方式,分別是storyboard,xib,手寫代碼.
我們都使用一遍.這裡我們先使用第一種方式使用-->storyboard方式
需求分析
1.頂部是一個TableViewHeaderView
2.組的頭部標題可以停留,說明tableView是plain樣式
3.cell中的數據比較多,系統無法滿足,自定義cell
1.項目準備:
指定類首碼(例如ZFB),分文件夾(目的是為了後面集成到一個項目中),刪除原有Main.storyboard 自己創建一個storyboard(指定class進行關聯,設置為啟動界面),並別忘指定 Main interface
創建控制器: 註意繼承UITableViewController(因為storyboard中我們拖拽的UITableViewControler,所以創建的類也要繼承UITableViewControler)
如果運行後,是白色面板. 排錯方法:打斷點
------>給數據源方法打斷點------->(沒執到時)-往上打斷點
------->[super viewDidLoad]----->(也沒有執行到時)
------>查看有沒有指定控制器class;
把準備好的plist文件和圖片素材拖入案例中
使用了UITableViewController後,指定數據源和遵守協議都不用我們管了.下一步我們來實現相應的數據源方法
2.實現相應的數據源方法
需要的數據,通過第4步會得到.
3.有多少行應該根據數據來
4.載入plist字典轉換模型
去modal文件夾中,創建模型類
//--------------------ZFBBusinessModel.h------------------------
#import <Foundation/Foundation.h>
@interface ZFBBusinessModel : NSObject
///頭像
@property (nonatomic, copy) NSString *icon;
///優惠信息
@property (nonatomic, copy) NSString *discount;
///人均消費
@property (nonatomic, strong) NSNumber *averagePrice;
///距離
@property (nonatomic, strong) NSNumber *distance;
///打折
@property (nonatomic, strong) NSNumber *offNum;
///評分
@property (nonatomic, strong) NSNumber *level;
///店名
@property (nonatomic, copy) NSString *name;
+ (instancetype)businessWithDict:(NSDictionary *)dict;
@end
//--------------------ZFBBusinessModel.m------------------------
#import "ZFBBusinessModel.h"
@implementation ZFBBusinessModel
+(instancetype)businessWithDict:(NSDictionary *)dict{
id obj = [[self alloc]init];
[obj setValuesForKeysWithDictionary:dict];
//--->註意使用KVC編碼,屬性名和字典中的key的名字一定要相同.
return obj;
}
@end
5.在storyboard中給自帶的UITableViewCell指定重用標識 一定要和返回cell的數據源方法是的標識要一樣
UITableView *cell = [tableView dequeueReusableCellWithIdentifier:@"business" forIndexPath:indexPath];
6.在storyboard中給cell添加拖拽相應的控制項,並添加約束
6.1拖拽imageView
(plus是3X的在這除以3
工作中一般都2x的,到時候除以2)
因為各個商家圖片不一樣大,顧為了統一
Scale:拉伸圖片
Aspect:圖片長寬的比例,保持圖形的長寬比,保持圖片不變形。
Aspect Fill:在保持長寬比的前提下,縮放圖片,使圖片充滿容器。
Aspect Fit:在保持長寬比的前提下,縮放圖片,使得圖片在容器內完整顯示出來。
Scale to Fill: 縮放圖片,使圖片充滿容器。圖片未必保持長寬比例協調,有可能會拉伸至變形。
6.1拖拽lable設置店名
6.3 先拖個view給星星占個位,後面再處理
得
6.4拖拽lable設置評分
設置約束
6.4拖拽lable設置人均消費
設置字體大小,設置約束
運行一下看效果,然後再繼續
6.5拖拽lable設置折扣
設置約束
6.6拖拽lable設置距離
設置約束 x和Y
6.7拖拽lable設置減字
設置約束(上邊距8,與上面左邊對齊,)略
減字外面的是正方形,我們設置一下寬高比為1:1,文字居中就ok了
6.8拖拽lable設置隨機立減...
(設置字體及顏色,設置約束,略..)
6.9 修改一下cell的高度
上面修改了business中的高度,只是修改了模型的大小,運行起來還得看 table View的高度大小,所以還得修改table View的高度
6.10 把背景顏色去掉運行一下看看
7.創建一個繼承至UITableViewCell的類,並且指定SB中的UITableViewCell的class為自己創建出來的這個類
8.把SB中Cell內部的子控制項連線到指定class的.m中的延展中
8.1增加一個延展
8.2指定class
8.3 子控制項連線
9.把模型變成屬性定義在自定義cell類的.h中,在.m重寫模型屬性的set方法在此方法設置數據
9.1 把模型變成屬性定義在自定義cell類的.h中
// ZFBBusinessCell.h
#import <UIKit/UIKit.h>
@class ZFBBusinessModel;
@interface ZFBBusinessCell : UITableViewCell
///模型屬性 註意模型是個對象 用strong
@property (nonatomic , strong) ZFBBusinessModel *businessModel;
@end
9.2 在.m重寫模型屬性的set方法在此方法設置數據
//
// ZFBBusinessCell.m
#import "ZFBBusinessCell.h"
#import "ZFBBusinessModel.h"//註意導入頭文件
@interface ZFBBusinessCell ()
///商店的頭像
@property (weak, nonatomic) IBOutlet UIImageView *iconView;
///店名
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
///評分
@property (weak, nonatomic) IBOutlet UILabel *levelLabel;
///人均消費
@property (weak, nonatomic) IBOutlet UILabel *averagePriceLabel;
///打折
@property (weak, nonatomic) IBOutlet UILabel *offNumLabel;
///距離
@property (weak, nonatomic) IBOutlet UILabel *distanceLabel;
///優惠信息
@property (weak, nonatomic) IBOutlet UILabel *discountLabel;
@end
@implementation ZFBBusinessCell
//重寫模型屬性的set方法在此方法中給子控制項設置數據
-(void)setBusinessModel:(ZFBBusinessModel *)businessModel{
_businessModel =businessModel;
_iconView.image = [UIImage imageNamed:businessModel.icon];
_nameLabel.text = businessModel.name;
_levelLabel.text = businessModel.level.description;//level是NSNumber類型的,轉字元串掉description方法
_averagePriceLabel.text = [NSString stringWithFormat:@"人均消費 %@ 元",businessModel.averagePrice]; //plist中只存了個數字,要顯示人均消費**元,顧要拼接字元串
_offNumLabel.text = [NSString stringWithFormat:@"%@ 折",businessModel.offNum];
_distanceLabel.text = [NSString stringWithFormat:@"距離北京石油化工學院 %@ m",businessModel.distance];
_discountLabel.text = businessModel.discount;
}
@end
回到ZFBBusinessController.m中
修改創建的cell類型
設置數據
//2.設置數據 (傳遞模型,這裡是單組數據展示, 當只有一組數據的時候用row,多組的時候才先用section再用row)
cell.businessModel = self.businessData[indexPath.row];
運行看現階段效果
數據類型有點小問題,8.8折和9.8折後面都一大串,接下來修改
10.打折 把模型中的offNum 改float類型,前提要改一下引入系統框架 UIKit
10.1修改ZFBBusinessModel.h文件
10.2修改ZFBBusinessCell.m文件
運行看效果
11.集成星星,把星星的文件拖拽出來後,指定Storyboard中代表星星的那個View的Class
12.把用來表示星星view連線在自定義cell.m中,引入星星類的頭文件
13.在模型屬性的set方法中,給星星view傳level
_leverView.lever = businessModel.level;
上面報錯是因為我們傳的是CGFloat類型導致的
而
顧改一下
這是這裡又報錯
還要改一下
把星星後面黃色背景顏色去掉,運行看效果
14.創建了一個xib 把xib中的view 寬361 高960
15.在裡面拖入一個imageView並且設置好圖片, 註意先 com + = 自適應下 為了後面使用Aspect ratio後圖片不會變形
16. 第一個imageView 上 左 右 8間距 + 寬高比
先使用 com + = 自適應 ,後面再設置寬高比,這樣他會根據真實的尺寸算比例,圖片不會變形
17.再複製3個imageView 但註意它身上約束
即複製完後,clear複製的約束
18.全部選中(com+a) 左對齊 等寬等高 上下間距8
左對齊
等寬等高
上下間距8:
註意在設置上下間距前,要保證兩個圖片之間不要有重合
19.創建一個繼承 至UIView的類,並且給xib指定class
繼承關係是跟最頂層有關係的,最頂層是UIView,就繼續UIView,最頂層是UIButton,那就繼續UIButton. 這裡是頂層是UIView.
給xib指定class(其實不指定也可以,因為之間沒有連線,但最好指定一下,說明它們之間是同一類型)
20.把載入xib細節封裝在剛纔創建的類中,提供一個可以讓外部調用的類方法,目的降低耦合度.
//#########################
// ZFBBusinessPictureView.h
#import <UIKit/UIKit.h>
@interface ZFBBusinessPictureView : UIView
/**
載入xib創建頭部視圖
*/
+(instancetype)businessPictureView;
@end
//#########################
// ZFBBusinessPictureView.m
#import "ZFBBusinessPictureView.h"
@implementation ZFBBusinessPictureView
/*
知識點回顧--兩種載入xib的方式
1.NSBundle載入XIB iOS 2.0 的方法
2.使用UINib載入XIB iOS 4.0 的方法 做了記憶體優化"如果記憶體緊張"記憶體警告,可以自動釋放,如果有需要會重新自動載入""
*/
+(instancetype)businessPictureView{
UINib *nib = [UINib nibWithNibName:@"ZFBBusinessPicture" bundle:nil];
return [[nib instantiateWithOwner:nil options:nil]firstObject];
}
@end
21.給tableView設置tableHeaderView 註意要計算它將來真實的高度
回到ZFBBusinessController.m
回到控制器中,導入剛纔創建類的頭文件ZFBBusinessPictureView.h
在控制器設置tableView的頭部 視圖.
//2.設置tableView的頭部視圖
ZFBBusinessPictureView *pictureView = [ZFBBusinessPictureView businessPictureView];
//375 * 960 / 361
CGFloat pictureViewHeight = self.tableView.bounds.size.width * pictureView.bounds.size.height / pictureView.bounds.size.width; //根據比例計算真實高度
pictureView.frame = CGRectMake(0, 0, self.tableView.bounds.size.width, pictureViewHeight); //寬度最好不要給了,以防有問題
self.tableView.tableHeaderView = pictureView; //設置為頭部視圖
22.給tableView設置tableFooterView
//3.設置tableView的尾部視圖
UIButton *footerBtn = [[UIButton alloc]init];
[footerBtn setTitle:@"點擊載入更多" forState:UIControlStateNormal];
[footerBtn setTitleColor:[UIColor colorWithWhite:0.3 alpha:1] forState:UIControlStateNormal];
[footerBtn setTitleColor:[UIColor colorWithWhite:0.7 alpha:1] forState:UIControlStateHighlighted];
footerBtn.backgroundColor = [UIColor colorWithWhite:0.5 alpha:1];
footerBtn.frame = CGRectMake(0, 0, 0, 30);
self.tableView.tableFooterView = footerBtn;//設置為尾部視圖
23.實現沒點擊載入更多一次,多輸出一個cell
把之前定義是不可變數組,修改為可變數組,不然就會報警告
24.優化讓其自動滾動
1.atScrollPosition: 的參數為UITableViewScrollPositionMiddle時
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.businessData.count-1 inSection:0];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
2.atScrollPosition: 的參數為UITableViewScrollPositionBottom時
25.細節處理 讓cell的分割線從最左邊開始
self.tableView.separatorInset = UIEdgeInsetsZero;
後面還沒會慢慢對細節進行處理
檢測自己
看看哪些沒掌握:
1、能夠說出tableViewController的view屬性和tableView是一樣的
2、能夠使用xib佈局口碑的頭部視圖
3、能夠說出使用代碼重新設置nib高度的含義是為了適配不同寬度的屏幕
4、能夠使用代碼設置尾部的按鈕
5、能夠說出代碼會調用view的initWithFrame方法
6、能夠說出sb/xib會調用view的aweakFromNib方法
7、能夠將星級評價小框架移植到口碑控制器中
8、能夠解決浮點數轉字元串精度的問題
9、能夠使用代碼解析plist數據
)
10、能夠使用代碼將字典轉化成模型
11、能夠使用代碼設置tableView的headerView和footerView
簡單回顧過程
1.口碑-數據分析
2.口碑-創建模型
- 類首碼
- 分文件夾
- 素材
3.口碑-解析數據
4.口碑-通過sb載入cell
- 通過sb載入cell,需要設置cell的Identifier,給sb中的cell設置重用標識即完成註冊單元格
5.口碑-cell的佈局
1.商家配圖圖片大小不一樣,所以最好給imageView設置寬高約束,達到配圖尺寸統一
2.label如果只有一行時,只用設置位置即可,尺寸讓它自適應
3.評分view,它的大小不能自適應,所以必須設置寬高約束"60,12"
4.減是個方形的,所以最好設置個寬高比
店名字體:14字體
其它是12號字體
到cell邊距15
內部邊距11
6.口碑-自定義cell控制項連線
1.cell中的子控制項不能連線到控制器,因為當前控制器只有一個,但是將來cell有很多個,所以會報重覆連接"連線"錯誤
2.正確作法,應該創建一個繼承至UITableViewCell的類,來管理"描述/表示",設置cell的customClass
3.把cell中子控制項的連線,連入到管理cell類的.m的延展中
7.口碑-設置cell數據
引入模型屬性"strong"
重寫模型屬性set方法給cell內部子控制項設置數據
8.口碑-移植星級評價
- 拖拽文件,設置sb中的view為自定義view,連線併在set數據的方法中把數據放在控制項上
- 用自定義星星的類來描述cell中的星星view,載入sb中的小星星view創建出來的對象,就是他指定類創建來出的對象"他們是同一個東西了"
- 再給level傳入分值即可
9.口碑-頭部視圖-佈局
- 第一個視圖分別設置 上,左,右,寬高比
- 後面的視圖與前一個等寬,等高,垂直間距,水平居中
10.口碑-頭部視圖-代碼設置縮放比例
- 在xib中調整好位置高度,併在視圖載入完成之後根據'寬度'和'屏幕的寬度'和'屏幕的高度'設置**高度**
- tableView的寬 / xib中HeaderView的寬 * xib中HeaderView的高 得到按比例縮放後的realHeaderView的高
- xib中的高 * tableView的寬 / xib中的寬
- xib的高 / xib的寬 * tableView的寬
2: 3 == 4: 6?
11.口碑-尾部視圖
- 灰度,R=G=B
- 1為白色 0為黑色
12.口碑-組頭
- tableview兩種樣式組頭的區別?
- grouped跟著tableView滾動出去
- plain可以懸停在上方
13.口碑-添加導航控制器
Editor -> Embedin -> Navgation Contorller
20-MarkMan測量截圖位置
21-KVC
// 方法1 傳統寫法
_name = dict[@"name"];
// 字典不能保存基本數據類型
_age = [dict[@"age"] integerValue];
// 方法2 KVC - `間接`通過 key 設置數值
// 註意:基本數據類型,不需要轉換,KVC 可以自動實現轉換!
[self setValue:dict[@"name"] forKey:@"name"];
[self setValue:dict[@"age"] forKey:@"age"];
// 方法3 KVC - 進階,迴圈遍歷字典
for (NSString *key in dict) {
// 1. 通過 key 取值
id value = dict[key];
// 2. 通過 KVC 方法設置數值
// -key 對應對象的 `屬性`,如果屬性不存在就崩潰
[self setValue:value forKey:key];
}
// 方法4 KVC 字典轉模型大招 -> 內部實際上就是方法3的實現
[self setValuesForKeysWithDictionary:dict];
- 在保證模型的屬性和字典中的key相同的情況下,字典轉模型使用setValuesForKeysWithDictionary:方法
- keys value coding 鍵值編碼
附整體代碼
/**總步驟:
1.指定類首碼,分文件夾'刪除原有Main.sb' 自己創建一個,並別忘指定 Main interface
2.實現相應的數據源方法
3.有多少行應該根據數據來
4.載入plist字典轉換模型
5.在sb中給自帶的UITableViewCell指定重用標識 一定要和返回cell的數據源方法是的標識要一樣
6.在SB中給cell添加拖拽相應的控制項,並添加約束
7.創建一個繼承至UITableViewCell的類,並且指定SB中的UITableViewCell的class為自己創建出來的這個類
8.把SB中Cell內部的子控制項連線到指定class的.m中的延展中
9.把模型變成屬性定義在自定義cell類的.h中,在.m重寫模型屬性的set方法在此方法設置數據
10.打折 把模型中的offNum 改float類型,前提要改一下引入系統框架 UIKit
11.集成星星,把星星的文件拖拽出來後,指定SB中代表星星的那個View的Class
12.把用來表示星星view連線在自定義cell.m中,引入星星類的頭文件
13.在模型屬性的set方法中,給星星view傳level
14.創建了一個xib 把xib中的view 寬361 高960
15.在裡面拖入一個imageView並且設置好圖片, com + = 自適應下 為了不用改寬高比約束值
16. 第一個imageView 上 左 右 8間距 + 寬高比
17. 複製3個imageView 但註意它身上約束
18. 全部選中左對齊 等寬等高 上下間距8
19. 創建一個繼承 至UIView的類,並且指定class
20. 把載入xib細節封裝在此類中,提供一個可以讓外部調用的類方法
21.給tableView設置tableHeaderView 註意要計算它將來真實的高度
22.給tableView設置tableFooterView
23.實現沒點擊載入更多一次,多輸出一個cell
24.優化讓其自動滾動
25.細節處理 讓cell的分割線從最左邊開始
*/
//********************ZFBBusinessController.h*****************************
// ZFBBusinessController.h
#import <UIKit/UIKit.h>
@interface ZFBBusinessController : UITableViewController
@end
//**********************ZFBBusinessController.m***************************
//
// ZFBBusinessController.m
// LJX_支付寶口碑(stroyboard搭建)
#import "ZFBBusinessController.h"
#import "ZFBBusinessModel.h"
#import "ZFBBusinessCell.h"
#import "ZFBBusinessPictureView.h"
@interface ZFBBusinessController ()
//數據在多個數據源方法中使用,顧聲明一個屬性
@property (nonatomic ,strong)NSMutableArray *businessData;
@end
@implementation ZFBBusinessController
- (void)viewDidLoad {
[super viewDidLoad];
//1.載入數據
self.businessData = [self loadBusinessData];
//-->使用方式2時,直接調用方法就行[self loadBusinessData];
//2.設置tableView的頭部視圖
ZFBBusinessPictureView *pictureView = [ZFBBusinessPictureView businessPictureView];
//如果不設置,因為xib中設置的寬度是361,如果在375的手機屏幕上顯示,因為xib中的圖片的寬度沒有寫死,當到了寬屏幕下,變寬,高也會變高,導致圖片會超出父控制項, 出了頭部視圖的邊界.
//375 * 960 / 361
CGFloat pictureViewHeight = self.tableView.bounds.size.width * pictureView.bounds.size.height / pictureView.bounds.size.width; //計算真實高度
pictureView.frame = CGRectMake(0, 0, self.tableView.bounds.size.width, pictureViewHeight); //寬度最好不要給了,以防有問題
self.tableView.tableHeaderView = pictureView; //設置為頭部視圖
//3.設置tableView的尾部視圖
UIButton *footerBtn = [[UIButton alloc]init];
[footerBtn setTitle:@"點擊載入更多" forState:UIControlStateNormal];
// colorWithWhite:0.3 alpha:1 通過灰度來設置顏色 第一個參數如果 傳0就是黑色 如果傳1就表示白色
[footerBtn setTitleColor:[UIColor colorWithWhite:0.3 alpha:1] forState:UIControlStateNormal];
[footerBtn setTitleColor:[UIColor colorWithWhite:0.7 alpha:1] forState:UIControlStateHighlighted];
footerBtn.backgroundColor = [UIColor colorWithWhite:0.5 alpha:1];
footerBtn.frame = CGRectMake(0, 0, 0, 30);
[footerBtn addTarget:self action:@selector(loadMoreData) forControlEvents:UIControlEventTouchUpInside]; //添加點擊事件
self.tableView.tableFooterView = footerBtn;//設置為尾部視圖
//小細節處理 :讓分割線從最左邊開始
self.tableView.separatorInset = UIEdgeInsetsZero;
}
#pragma mark -尾部按鈕點擊後會調用此方法
//1.載入更多數據
-(void)loadMoreData{
//1.創建一個新的模型
ZFBBusinessModel *businessModel = [[ZFBBusinessModel alloc]init];
businessModel.icon = @"ss";
businessModel.discount = @"全場大派送,2元一件,快來買!";
businessModel.averagePrice = @2;
businessModel.distance = @20;
businessModel.offNum = 2;
businessModel.level = 5;
businessModel.name = @"西單大悅城!";
//2.把新模型添加到保存所以數據的數組中
[self.businessData addObject:businessModel];
//3.讓數據源方法重新執行
[self.tableView reloadData];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.businessData.count-1 inSection:0];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
}
#pragma mark -數據源方法
// 應該口碑案例表格就1組,預設就1組,所以不用再寫
//- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
// return 1;
//}
// 行數
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.businessData.count;
//--->使用方式2時: return _businessList.count;
}
//
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//1.創建cell
ZFBBusinessCell *cell = [tableView dequeueReusableCellWithIdentifier:@"business" forIndexPath:indexPath];
//-->這裡在storyboard中進行註冊cell
//2.設置數據 (傳遞模型,這裡是單組數據展示, 當只有一組數據的時候用row,多組的時候才先用section再用row)
cell.businessModel = self.businessData[indexPath.row];
//3.返回cell
return cell;
}
#pragma mark -載入數據
- (NSMutableArray *)loadBusinessData{
//1.載入plist
NSMutableArray *dictArr = [NSMutableArray arrayWithContentsOfURL:[[NSBundle mainBundle]URLForResource:@"business.plist" withExtension:nil]];
//2. 創建可變數組保存模型 /kə'pæsɪtɪ/ 容量
NSMutableArray *arryM = [NSMutableArray arrayWithCapacity:dictArr.count];
//3.字典轉模型
for(NSDictionary *dict in dictArr){
[arryM addObject:[ZFBBusinessModel businessWithDict:dict]];
/* 分步寫
//3.1 把字典傳遞給模型,讓模型設置自己的屬性
ZFBBusinessModel *groupModel = [ZFBBusinessModel businessWithDict:dict];
//3.2 把創建好的模型添加到可變數組中.
[arryM addObject: groupModel];
*/
}
return arryM;
}
/*
方式2. 載入數據方法的返回值設置為空 ,聲明一個成員變數(給成員變數設置泛型),把可變數組賦值給成員變數
1. NSArray<ZFBBusinessModel *> *_businessList; //聲明成員變數,設置泛型
2.
- (void)loadBusinessData{
...code略....
_businessList = arryM;
}
*/
@end
//
// ZFBBusinessModel.h
#import <UIKit/UIKit.h>
@interface ZFBBusinessModel : NSObject
///頭像
@property (nonatomic, copy) NSString *icon;
///優惠信息
@property (nonatomic, copy) NSString *discount;
///人均消費
@property (nonatomic, strong) NSNumber *averagePrice;
///距離
@property (nonatomic, strong) NSNumber *distance;
///打折
//浮點數字轉出成字元串時,可能會出現問題,把它轉換成float
@property (nonatomic, assign) float offNum;
///評分
@property (nonatomic, assign) CGFloat level;
///店名
@property (nonatomic, copy) NSString *name;
+ (instancetype)businessWithDict:(NSDictionary *)dict;
@end
#import "ZFBBusinessModel.h"
@implementation ZFBBusinessModel
+(instancetype)businessWithDict:(NSDictionary *)dict{
id obj = [[self alloc]init];
[obj setValuesForKeysWithDictionary:dict];
//--->註意使用KVC編碼,屬性名和字典中的key的名字一定要相同.
return obj;
}
@end
//
// ZFBLeverStar.h
// LJX_星級評價
#import <UIKit/UIKit.h>
@interface ZFBLeverStar : UIView
///接收評分
@property (nonatomic, assign) CGFloat lever;
@end
//
// ZFBLeverStar.m
// LJX_星級評價
#import "ZFBLeverStar.h"
@implementation ZFBLeverStar
//當一個視圖從xib或storyboard中創建完成之後就會調用此方法
-(void)awakeFromNib{
[super awakeFromNib];
//來了 直接把5個imageView創建添加好
for (NSInteger i = 0; i < 5; i++) {
UIImageView *imageView =[[UIImageView alloc]initWithImage:[UIImage imageNamed:@"full_star"]];//這個目的不是拿圖片,目的是隨便拿一張圖片,圖片就有了大小了
//設置圖片的x
CGFloat imageViewX = i * imageView.image.size.width;
imageView.frame = CGRectMake(imageViewX, 0, imageView.image.size.width, imageView.image.size.height);
[self addSubview:imageView];
}
}
//此方法只有用代碼創建時才會調用
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
//來了 直接把5個imageView創建添加好
for (NSInteger i = 0; i < 5; i++) {
UIImageView *imageView =[[UIImageView alloc]initWithImage:[UIImage imageNamed:@"full_star"]];//這個目的不是拿圖片,目的是隨便拿一張圖片,圖片就有了大小了
//設置圖片的x
CGFloat imageViewX = i * imageView.image.size.width;
imageView.frame = CGRectMake(imageViewX, 0, imageView.image.size.width, imageView.image.size.height);
[self addSubview:imageView];
}
}
return self;
}
//重寫set方法在裡面處理顯示星星圖片的細節
-(void)setLever:(CGFloat)lever{
_lever = lever;
//1.滿星
//把傳過來的分數強轉為整型,整數值就是滿星的個數
NSInteger fullStartCount = (NSInteger)lever;
for(NSInteger i = 0 ; i < fullStartCount ; i++){
[self makeLeverStarWithImageName:@"full_star" andPosition:i];
}
//2.半星
// (取傳過來的個數) - (強轉後的整數),如果 > 0 就表示有半星
if((lever - fullStartCount)>0){
[self makeLeverStarWithImageName:@"half_star" andPosition:fullStartCount];
//如果添加了一個半星那把滿星個數的值做加1 用它當做 目前已經添加星星的總個數了
fullStartCount++;
}
//3.空星 "如果到這來還不夠5顆星 那剩下的就是空星的個數了"
for (NSInteger i = fullStartCount; i < 5; i++) {
[self makeLeverStarWithImageName:@"empty_star" andPosition:i];
}
}
/**
創建星星imageView
@param imageName 星星圖片
@param position 星星位置 從0開始
*/
-(void)makeLeverStarWithImageName:(NSString *)imageName andPosition:(NSInteger)position{
//獲取相應位置的子控制項
UIImageView *imageView = self.subviews[position];
//設置圖片
imageView.image = [UIImage imageNamed:imageName];
}
@end
/*
//1.創建imageView設置圖片,那麼imageView創建出來的就有尺寸
UIImageView *imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:imageName]];
//2.設置圖片的x
CGFloat imageViewX = position * imageView.image.size.width;
imageView.frame = CGRectMake(imageViewX, 0, imageView.image.size.width, imageView.image.size.height);
[self addSubview:imageView];
*/
//
// ZFBBusinessCell.h
#import <UIKit/UIKit.h>
@class ZFBBusinessModel;
@interface ZFBBusinessCell : UITableViewCell
///模型屬性 註意模型是個對象 用strong
@property (nonatomic , strong) ZFBBusinessModel *businessModel;
@end
//
// ZFBBusinessCell.m
#import "ZFBBusinessCell.h"
#import "ZFBBusinessModel.h"//註意導入頭文件
#import "ZFBLeverStar.h"
@interface ZFBBusinessCell ()
///商店的頭像
@property (weak, nonatomic) IBOutlet UIImageView *iconView;
///店名
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
///評分
@property (weak, nonatomic) IBOutlet UILabel *levelLabel;
///人均消費
@property (weak, nonatomic) IBOutlet UILabel *averagePriceLabel;
///打折
@property (weak, nonatomic) IBOutlet UILabel *offNumLabel;
///距離
@property (weak, nonatomic) IBOutlet UILabel *distanceLabel;
///優惠信息
@property (weak, nonatomic) IBOutlet UILabel *discountLabel;
///星級評價
@property (weak, nonatomic) IBOutlet ZFBLeverStar *leverView;
@end
@implementation ZFBBusinessCell
//重寫模型屬性的set方法在此方法中給子控制項設置數據
-(void)setBusinessModel:(ZFBBusinessModel *)businessModel{
_businessModel =businessModel;
_iconView.image = [UIImage imageNamed:businessModel.icon];
_nameLabel.text = businessModel.name;
_levelLabel.text = @(businessModel.level).description;//level是NSNumber類型的,轉字元串掉description方法
_averagePriceLabel.text = [NSString stringWithFormat:@"人均消費 %@ 元",businessModel.averagePrice]; //plist中只存了個數字,要顯示人均消費**元,顧要拼接字元串
_offNumLabel.text = [NSString stringWithFormat:@"%@ 折",@(businessModel.offNum).description];
_distanceLabel.text = [NSString stringWithFormat:@"距離北京石油化工學院 %@ m",businessModel.distance];
_discountLabel.text = businessModel.discount;
//傳分
_leverView.lever = businessModel.level;
}
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
//
// ZFBBusinessPictureView.h
#import <UIKit/UIKit.h>
@interface ZFBBusinessPictureView : UIView
/**
載入xib創建頭部視圖
*/
+(instancetype)businessPictureView;
@end
//
// ZFBBusinessPictureView.m
#import "ZFBBusinessPictureView.h"
@implementation ZFBBusinessPictureView
/*
知識點回顧--兩種載入xib的方式
1.NSBundle載入XIB iOS 2.0 的方法
2.使用UINib載入XIB iOS 4.0 的方法 做了記憶體優化"如果記憶體緊張"記憶體警告,可以自動釋放,如果有需要會重新自動載入""
*/
+(instancetype)businessPictureView{
UINib *nib = [UINib nibWithNibName:@"ZFBBusinessPicture" bundle:nil];
return [[nib instantiateWithOwner:nil options:nil]firstObject];
}
@end