上篇文章介紹了UITableView的數(shù)據(jù)源驅(qū)動、重用機制、刷新數(shù)據(jù)等基本用法
創(chuàng)新互聯(lián)公司作為成都網(wǎng)站建設(shè)公司,專注重慶網(wǎng)站建設(shè)公司、網(wǎng)站設(shè)計,有關(guān)企業(yè)網(wǎng)站制作方案、改版、費用等問題,行業(yè)涉及石涼亭等多個領(lǐng)域,已為上千家企業(yè)服務(wù),得到了客戶的尊重與認(rèn)可。本篇文章介紹如何實現(xiàn)一些復(fù)雜的單元格
UITableViewCell單元格對象有四種基本樣式,開發(fā)中這個基本樣式往往不能滿足我們的需求,也就是說需要自定義UITableViewCell的樣式,介紹主要的兩種做法:
1)使用純代碼自定義
2)使用storyboard中的prototype cell
先來介紹一下UITableViewCell
UITableViewCell表格單元格
UITableView中的單元格使用UITableViewCell視圖對象
創(chuàng)建方法:
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
style參數(shù):cell的預(yù)設(shè)樣式
typedef enum : NSInteger { UITableViewCellStyleDefault, UITableViewCellStyleValue1, UITableViewCellStyleValue2, UITableViewCellStyleSubtitle } UITableViewCellStyle;
reuseIdentifier參數(shù):cell的重用ID
單元格的內(nèi)部視圖:
@property(nonatomic, readonly, retain) UIView *contentView
內(nèi)部視圖中又包含以下三個子視圖,這三個子視圖在不同樣式中顯示的個數(shù)及樣式不同
@property(nonatomic, readonly, retain) UILabel *textLabel @property(nonatomic, readonly, retain) UILabel *detailTextLabel @property(nonatomic, readonly, retain) UIImageView *p_w_picpathView
單元格的其他組件:
@property(nonatomic) UITableViewCellAccessoryType accessoryType //右側(cè)指示視圖樣式 @property(nonatomic, retain) UIView *accessoryView //自定義右側(cè)指示視圖
單元格的選擇狀態(tài):
@property(nonatomic, getter=isSelected) BOOL selected @property(nonatomic) UITableViewCellSelectionStyle selectionStyle
復(fù)雜單元格實現(xiàn)(一): 純代碼自定義
實現(xiàn)如下效果:
實現(xiàn)一個游戲人物信息的展示
分析:
UITableView使用典型的MVC設(shè)計模式進行開發(fā)
a. 模型:游戲英雄信息數(shù)據(jù)
b. 視圖:單元格視圖UITableViewCell的子類
c. 控制器:管理模型數(shù)組,以及實現(xiàn)tableView的數(shù)據(jù)源、代理等
1)模型定義
@interface AMHeroModel : NSObject @property (nonatomic, copy) NSString * name; //英雄名 @property (nonatomic, copy) NSString * title; //英雄稱號 @property (nonatomic, copy) NSString * icon; //英雄圖標(biāo) @property (nonatomic, copy) NSString * desc; //英雄描述 @property (nonatomic, copy) NSString * tags; //英雄標(biāo)簽 + (AMHeroModel*) modelWithDict:(NSDictionary*)dict;//構(gòu)造方法:字典轉(zhuǎn)模型 @end
2)控制器管理模型數(shù)組并使用懶加載
@interface ViewController () @property (nonatomic, strong) NSMutableArray * heroArray;//模型數(shù)組 @property (weak, nonatomic) IBOutlet UITableView *tableView;//tableView @end
#pragma mark - heroArray懶加載 - (NSMutableArray *)heroArray { if ( _heroArray == nil ) { NSString * plistPath = [[NSBundle mainBundle] pathForResource:@"hero.plist" ofType:nil]; NSArray * plistArray = [NSArray arrayWithContentsOfFile:plistPath]; _heroArray = [NSMutableArray array]; for ( NSDictionary * dict in plistArray ) { AMHeroModel * model = [AMHeroModel modelWithDict:dict]; [_heroArray addObject:model]; } } return _heroArray; }
3)自定義UITableViewCell子類
需要展示的模型數(shù)據(jù)包括:4個字符串、一張圖片,故UITableViewCell內(nèi)部應(yīng)自定義4個UILabel以及一個UIImageView子視圖。
實現(xiàn)需要三步:
@interface AMHeroCell : UITableViewCell //1.添加一個類方法,獲取cell + (AMHeroCell *) cellWithTableView:(UITableView * ) tableView; //2.添加模型屬性并重寫setter方法 @property (nonatomic, strong) AMHeroModel * heroModel; //3.提供一個類方法,返回cell的高度 + (CGFloat) cellHeight; @end
4)UITableViewCell子類:添加一個類方法獲取cell
這一步是自定義UITableViewCell最關(guān)鍵且最復(fù)雜的步驟,需要完成:
將cell創(chuàng)建/獲取的代碼封裝、創(chuàng)建所有的子視圖、設(shè)置所有的子視圖的frame
//1.1 實現(xiàn)類方法,獲取cell + (AMHeroCell *)cellWithTableView:(UITableView *)tableView { AMHeroCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; if ( cell == nil ) { cell = [[AMHeroCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; } return cell; }
創(chuàng)建所有的子視圖操作應(yīng)當(dāng)放在initWithStyle方法中,故重寫
//1.2 重寫initWithStyle:方法,添加自定義子視圖的代碼 - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { if ( self = [super initWithStyle:style reuseIdentifier:reuseIdentifier] ) { //1.2.1 將沒有用的子視圖刪除 [self.p_w_picpathView removeFromSuperview]; [self.textLabel removeFromSuperview]; [self.detailTextLabel removeFromSuperview]; //1.2.2 創(chuàng)建自定義的子視圖并進行一次性的屬性設(shè)置 UIImageView * iconImageView = [[UIImageView alloc] init]; self.iconImageView =iconImageView; [self.contentView addSubview:self.iconImageView]; UILabel * nameLabel = [[UILabel alloc] init]; self.nameLabel = nameLabel; [self.contentView addSubview:self.nameLabel]; self.nameLabel.textColor = [UIColor purpleColor]; self.nameLabel.font = [UIFont systemFontOfSize:16]; UILabel * titleLabel = [[UILabel alloc] init]; self.titleLabel = titleLabel; [self.contentView addSubview:self.titleLabel]; self.titleLabel.textColor = [UIColor grayColor]; self.titleLabel.font = [UIFont systemFontOfSize:14]; UILabel * tagsLabel = [[UILabel alloc] init]; self.tagsLabel = tagsLabel; [self.contentView addSubview:tagsLabel]; self.tagsLabel.textColor = [UIColor redColor]; self.tagsLabel.font = [UIFont systemFontOfSize:12]; UILabel * descLabel = [[UILabel alloc] init]; self.descLabel = descLabel; [self.contentView addSubview:descLabel]; self.descLabel.textColor = [UIColor blueColor]; self.descLabel.font = [UIFont systemFontOfSize:12]; self.descLabel.numberOfLines = 0; } return self; }
考慮到屏幕適配,使用設(shè)定frame的方式且當(dāng)前為view子類,所以重寫layoutSubviews方法
//1.3 設(shè)置所有子視圖的frame或者使用autolayout //如果使用autolayout,代碼放在重寫的initWithStyle方法中 //如果使用frame,放在layoutSubviews方法中 - (void)layoutSubviews { [super layoutSubviews]; CGFloat Xspace = self.contentView.frame.size.width*0.05; CGFloat Yspace = self.contentView.frame.size.height*0.05; CGFloat iX, iY, iW, iH; iX = Xspace; iY = Yspace; iH = self.contentView.frame.size.height*0.9; iW = iH; self.iconImageView.frame = CGRectMake(iX, iY, iW, iH); CGFloat nX, nY, nW, nH; nX = 2*Xspace+iW; nY = iY; nW = (self.contentView.frame.size.width-3*Xspace-iW-Xspace)/2; nH = self.contentView.frame.size.height*0.2; self.nameLabel.frame = CGRectMake(nX, nY, nW, nH); CGFloat tX, tY, tW, tH; tX = CGRectGetMaxX(self.nameLabel.frame)+Xspace; tY = nY; tW = nW; tH = nH; self.titleLabel.frame = CGRectMake(tX, tY, tW, tH); CGFloat taX, taY, taW, taH; taX = nX; taY = self.contentView.frame.size.height*0.3; taW = self.contentView.frame.size.width- 3*Xspace -iW; taH = nH; self.tagsLabel.frame = CGRectMake(taX, taY, taW, taH); CGFloat dX, dY, dW, dH; dX = nX; dY = self.contentView.frame.size.height*0.55; dW = taW; dH = self.contentView.frame.size.height*0.4; self.descLabel.frame = CGRectMake(dX, dY, dW, dH); }
5)UITableViewCell子類:添加模型屬性并重寫setter方法
在3)中的代碼示例中已經(jīng)看到添加了模型屬性
重寫setter方法的目的是:對外隱藏子視圖,數(shù)據(jù)顯示到子視圖的操作封裝在setter方法內(nèi)部
- (void)setHeroModel:(AMHeroModel *)heroModel { _heroModel = heroModel; //圖片對象的創(chuàng)建:兩種方式: //1)p_w_picpathNamed 有緩存的圖片對象創(chuàng)建方式 以空間換時間 //self.iconImageView.p_w_picpath = [UIImage p_w_picpathNamed:_heroModel.icon]; //2)withContentOfFile方式創(chuàng)建的 不使用緩存 以時間換空間 NSString * path = [[NSBundle mainBundle] pathForResource:_heroModel.icon ofType:nil]; self.iconImageView.p_w_picpath = [[UIImage alloc] initWithContentsOfFile:path]; self.nameLabel.text = _heroModel.name; self.titleLabel.text = _heroModel.title; self.tagsLabel.text = _heroModel.tags; self.descLabel.text = _heroModel.desc; }
6)UITableViewCell子類:類方法返回cell的高度
UITableView中單元格的高度,默認(rèn)是44,添加一個類方法返回指定的高度,這樣做的好處是:當(dāng)需求有變時,只需要修改UITableViewCell的子類,即高內(nèi)聚低耦合的編程思想。
+ (CGFloat)cellHeight { return 140.f; }
7)控制器實現(xiàn)tableView的數(shù)據(jù)源、代理方法
#pragma mark - tableView的數(shù)據(jù)源和代理 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.heroArray.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { return [AMHeroCell cellWithTableView:tableView]; } - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { AMHeroCell * heroCell = cell; heroCell.heroModel = self.heroArray[indexPath.row]; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return [AMHeroCell cellHeight]; }
可以看到數(shù)據(jù)源、代理方法的實現(xiàn)極其簡單,且無論模型數(shù)據(jù)怎么變,cell怎么變,這部分的代碼是幾乎不變的
案例的額外功能擴展
1)添加功能
從截圖可以看到,導(dǎo)航欄有一個加號按鈕,實現(xiàn)響應(yīng)方法:隨機添加一個英雄
#pragma mark - 添加cell - (void) addBarBtnClicked { NSInteger index = random()%self.heroArray.count; AMHeroModel * model = self.heroArray[index]; [self.heroArray insertObject:model atIndex:0]; [self.tableView reloadData]; }
2)刪除功能
從截圖可以看到,導(dǎo)航欄有一個刪除按鈕,點擊后UITableView進入編輯狀態(tài)
#pragma mark - 刪除cell - (void) delBarBtnClicked { [self.tableView setEditing:!self.tableView.isEditing animated:YES]; }
點擊編輯狀態(tài)的刪除按鈕的響應(yīng)方法
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {//當(dāng)進入編輯狀態(tài)后,點擊delete按鈕時按鈕 [self.heroArray removeObjectAtIndex:indexPath.row]; [self.tableView reloadData]; }
3)點擊一個cell,彈出一個UIAlertController,可以進行簡單的數(shù)據(jù)修改
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { UIAlertController * ac = [UIAlertController alertControllerWithTitle:@"修改英雄信息" message:@"輸入修改該的數(shù)據(jù)" preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction * a1 = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { }]; UIAlertAction * a2 = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { model.name = ac.textFields[0].text; model.title = ac.textFields[1].text; [self.tableView reloadData];//重新加載數(shù)據(jù) }]; [ac addAction:a1]; [ac addAction:a2]; [ac addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { textField.text = model.name; }]; [ac addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { textField.text = model.title; }]; [self presentViewController:ac animated:YES completion:nil]; }
效果:
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。
網(wǎng)頁題目:UIKit框架(21)UITableView實現(xiàn)復(fù)雜單元格(一)-創(chuàng)新互聯(lián)
標(biāo)題路徑:http://jinyejixie.com/article6/egiig.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供移動網(wǎng)站建設(shè)、網(wǎng)站改版、關(guān)鍵詞優(yōu)化、品牌網(wǎng)站設(shè)計、軟件開發(fā)、域名注冊
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容