iOS控件--UITableView--表格行控件

1.基本介紹:

UITableView 有兩種風(fēng)格:UITableViewStylePlain不分組樣式和UITableViewStyleGrouped分組樣式。 UITableViewStylePlainUITableViewStyleGrouped 這兩者操作起來其實并沒有本質(zhì)區(qū)別,只是后者按分組樣式顯示前者按照普通樣式顯示而已。

在UITableView中數(shù)據(jù)只有行的概念,并沒有列的概念。UITableView中每行數(shù)據(jù)都是一個UITableViewCell

在這個控件中為了顯示更多的信息,iOS已經(jīng)在其內(nèi)部設(shè)置好了多個子控件以供開發(fā)者使用。如果我們查看UITableViewCell的聲明文件可以發(fā)現(xiàn)在內(nèi)部有一個UIView控件(contentView,作為其他元素的父控件)、兩個UILable控件(textLabel、detailTextLabel)、一個UIImage控件(imageView),分別用于容器、顯示內(nèi)容、詳情和圖片。使用效果類似于微信、QQ信息列表。

這些子控件并不一定要全部使用,具體操作時可以通過UITableViewCellStyle進(jìn)行設(shè)置:

typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
    UITableViewCellStyleDefault, // 左側(cè)顯示textLabel(不顯示detailTextLabel),imageView可選(顯示在最左邊)
    UITableViewCellStyleValue1, // 左側(cè)顯示textLabel、右側(cè)顯示detailTextLabel(默認(rèn)藍(lán)色),imageView可選(顯示在最左邊)
    UITableViewCellStyleValue2, // 左側(cè)依次顯示textLabel(默認(rèn)藍(lán)色)和detailTextLabel,imageView可選(顯示在最左邊)
    UITableViewCellStyleSubtitle // 左上方顯示textLabel,左下方顯示detailTextLabel(默認(rèn)灰色),imageView可選(顯示在最左邊)
};

2.數(shù)據(jù)源 -- dataSource

由于iOS是遵循MVC模式設(shè)計的,很多操作都是通過代理和外界溝通的,但對于數(shù)據(jù)源控件除了代理還有一個數(shù)據(jù)源屬性,通過它和外界進(jìn)行數(shù)據(jù)交互。 對于UITableView設(shè)置完dataSource后需要實現(xiàn)UITableViewDataSource協(xié)議,在這個協(xié)議中定義了多種數(shù)據(jù)操作方法。

UITableView需要一個數(shù)據(jù)源(dataSource)來顯示數(shù)據(jù),UITableView會向數(shù)據(jù)源查詢一共有多少行數(shù)據(jù)以及每一行顯示什么數(shù)據(jù)等。沒有設(shè)置數(shù)據(jù)源的UITableView只是個空殼。凡是遵守 UITableViewDataSource 協(xié)議的OC對象,都可以是UITableView的數(shù)據(jù)源。

通常都要為UITableView設(shè)置代理對象(delegate),以便在UITableView觸發(fā)一下事件時做出相應(yīng)的處理,比如選中了某一行。凡是遵守了UITableViewDelegate協(xié)議的OC對象,都可以是UITableView的代理對象。

一般會讓控制器充當(dāng)UITableView的dataSource和delegate,這就涉及到MVC的具體使用,如果 UITableView是在 自定義UIView中添加,則delegate和dataSource可以放置在 自定義UIVie的控制器中來進(jìn)行,相應(yīng)的數(shù)據(jù)源控制和方法觸發(fā)

3.方法的使用及描述

UITableViewDataSource/UITableViewDelegate

下面是涉及到的代理和數(shù)據(jù)源的所有正常使用提供的方法

@required
    //第section分區(qū)一共有多少行
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
    //創(chuàng)建第section分區(qū)第row行的cell對象(indexPath包含了section和row),加載cell對象數(shù)據(jù)。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
@end
@optional
    //一共有多少個分區(qū)
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
    //第section分區(qū)的頭部標(biāo)題
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
    //第section分區(qū)的底部標(biāo)題
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
    //某一行是否可以編輯(刪除)
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;
    //某一行是否可以移動來進(jìn)行重新排序
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath;
    //UITableView右邊的索引欄的內(nèi)容
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView;
    //選中了UITableView的某一行
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
    //某一行的高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
    //第section分區(qū)頭部的高度
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
    //第section分區(qū)尾部的高度
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
    //第section分區(qū)頭部顯示的視圖
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
    //第section分區(qū)尾部顯示的視圖
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;
    //設(shè)置每一行的等級縮進(jìn)(數(shù)字越小,等級越高)
- (NSInteger)tableView:(UITableView *)tableViewindentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath;
@end

4.UITableViewCell對象的重用原理

重用原理:當(dāng)滾動列表時,部分UITableViewCell會移出窗口,UITableView會將窗口外的UITableViewCell放入一個對象池中,等待重用。當(dāng)UITableView要求dataSource返回UITableViewCell時,dataSource會先查看這個對象池,如果池中有未使用的UITableViewCell,dataSource會用新的數(shù)據(jù)配置這個UITableViewCell,然后返回給UITableView,重新顯示到窗口中,從而避免創(chuàng)建新對象

一個非常重要的問題:有時候需要自定義UITableViewCell(用一個子類繼承UITableViewCell),而且每一行用的不一定是同一種UITableViewCell(如短信聊天布局),所以一個UITableView可能擁有不同類型的UITableViewCell,對象池中也會有很多不同類型的UITableViewCell,那么UITableView在重用UITableViewCell時可能會得到錯誤類型的UITableViewCell

解決方案:UITableViewCell有個NSString *reuseIdentifier屬性,可以在初始化UITableViewCell的時候傳入一個特定的字符串標(biāo)識來設(shè)置reuseIdentifier(一般用UITableViewCell的類名)。當(dāng)UITableView要求dataSource返回UITableViewCell時,先通過一個字符串標(biāo)識到對象池中查找對應(yīng)類型的UITableViewCell對象,如果有,就重用,如果沒有,就傳入這個字符串標(biāo)識來初始化一個UITableViewCell對象

重用UITableViewCell對象: -- 使用方法

- (UITableViewCell *)tableView:(UITableView *)tableView  cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 配置一個cell 的重用ID
    static NSString *id = @"UITableViewCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"id"];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"id"];
            }
    cell.textLabel.text = [NSString stringWithFormat:@"Text %li", indexPath.row];
    return cell;
}

5.UITableViewCell的常用屬性:

設(shè)置背景:backgroundView -- 設(shè)置被選中時的背景視圖:selectedBackgroundView

selectionStyle屬性可設(shè)置UITableViewCell被選中時的背景顏色:

  • UITableViewCellSelectionStyleNone沒有顏色
  • UITableViewCellSelectionStyleBlue藍(lán)色(默認(rèn))
  • UITableViewCellSelectionStyleGray灰色

6.自定義UITableViewCell

> 1. 新建一個繼承自:UITableViewCell類
> 2. 重寫:initWithStyle:reuseIdentifier:方法

-->添加所有需要顯示的子控件(而不需要設(shè)置子控件的數(shù)據(jù)和frame,子控件要添加到contentView中)

-->進(jìn)行子控件的一次性設(shè)置(有些屬性只需要設(shè)置一次,如字體、圖片等)

> 3.提供2個模型

-->數(shù)據(jù)模型:存放文字?jǐn)?shù)據(jù)/圖片數(shù)據(jù)

-->frame模型:存放數(shù)據(jù)模型/所有子控件的frame/cell高度

4.cell擁有一個frame模型,不要直接擁有數(shù)據(jù)模型。
5.重寫frame模型的屬性的setter方法:在這個方法中設(shè)置顯示數(shù)據(jù)和frame
6.frame模型數(shù)據(jù)的初始化已經(jīng)采取懶加載的方式(每個cell對應(yīng)的frame模型數(shù)據(jù)只加載一次)。

7.UITableView使用方法步驟

>1>一共有多少組;- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView  
>2>第section組一共有多少行:@required - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section  
>3>第indexPath.section組 第indexPath.row行顯示怎樣的cell(顯示什么內(nèi)容,加載數(shù)據(jù))@required:- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath。  在這個方法中使用:tableCell.textLabel.text=[[NSArray array] objectAtIndex:indexPath.row]; 可以在UITableViewCell中依次顯示數(shù)組中的內(nèi)容  
>4>第section組顯示怎樣的頭部標(biāo)題:-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;  
>5>第section組顯示怎樣的尾部標(biāo)題:- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;  
>6>選中某一行操作:-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;

8.tableView刷新數(shù)據(jù)的方式

1). 修改模型數(shù)據(jù)

2). 全局刷新:[self.tableView reloadData];

3). 修改局部刷新:前提是模型數(shù)據(jù)的個數(shù)不變,所以可以進(jìn)行局部刷新:[self.tableView reloadRowsAtIndexPaths:@[indexPath]withRowAnimation:UITableViewRowAnimationBottom];

4). 刪除局部刷新:[self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0inSection:0]] withRowAnimation:UITableViewRowAnimationMiddle];

9.添加每個cell出現(xiàn)時的3D動畫

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
     // 動畫1
     //    CATransform3D rotation;//3D旋轉(zhuǎn)
     //    rotation = CATransform3DMakeRotation( (90.0*M_PI)/180, 0.0, 0.7, 0.4);
     //    //逆時針旋轉(zhuǎn)
     //    rotation.m34 = 1.0/ -600;
     //
     //    cell.layer.shadowColor = [[UIColor blackColor]CGColor];
     //    cell.layer.shadowOffset = CGSizeMake(10, 10);
     //    cell.alpha = 0;
     //
     //    cell.layer.transform = rotation;
     //
     //    [UIView beginAnimations:@"rotation" context:NULL];
     //    //旋轉(zhuǎn)時間
     //    [UIView setAnimationDuration:0.8];
     //    cell.layer.transform = CATransform3DIdentity;
     //    cell.alpha = 1;
     //    cell.layer.shadowOffset = CGSizeMake(0, 0);
     //    [UIView commitAnimations];
     // 動畫2
     cell.alpha = 0.5;
     CGAffineTransform transformScale = CGAffineTransformMakeScale(0.3,0.8);
     CGAffineTransform transformTranslate = CGAffineTransformMakeTranslation(0.5, 0.6);
     cell.transform = CGAffineTransformConcat(transformScale, transformTranslate);
     [tableView bringSubviewToFront:cell];
     [UIView animateWithDuration:.4f
                           delay:
                         options:UIViewAnimationOptionAllowUserInteraction
                      animations:^{
                          cell.alpha = ;
                          //清空 transform
                          cell.transform = CGAffineTransformIdentity;
                      } completion:nil];
     // 動畫3
     /*
      // 從錨點位置出發(fā),逆時針繞 Y 和 Z 坐標(biāo)軸旋轉(zhuǎn)90度
      CATransform3D transform3D = CATransform3DMakeRotation(M_PI_2, 0.0, 1.0, 1.0);
      // 定義 cell 的初始狀態(tài)
      cell.alpha = 0.0;
      cell.layer.transform = transform3D;
      cell.layer.anchorPoint = CGPointMake(0.0, 0.5); // 設(shè)置錨點位置;默認(rèn)為中心點(0.5, 0.5)
      // 定義 cell 的最終狀態(tài),執(zhí)行動畫效果
      // 方式一:普通操作設(shè)置動畫
      [UIView beginAnimations:@"transform" context:NULL];
      [UIView setAnimationDuration:0.5];
      cell.alpha = 1.0;
      cell.layer.transform = CATransform3DIdentity;
      CGRect rect = cell.frame;
      rect.origin.x = 0.0;
      cell.frame = rect;
      [UIView commitAnimations];
      // 方式二:代碼塊設(shè)置動畫
      //        [UIView animateWithDuration:0.5 animations:^{
      //                cell.alpha = 1.0;
      //                 cell.layer.transform = CATransform3DIdentity;
      //                CGRect rect = cell.frame;
      //                 rect.origin.x = 0.0;
      //            cell.frame = rect;
      //             }];
      */
 }

>> UITableViewCell可移動,需要打開的代理方法以及移動過程中調(diào)用的代理方法

// tableView可移動  移動完成之后會調(diào)用此代理方法
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
}
// 移動過程中調(diào)用的代理方法 -- 示例為不能跨區(qū)移動
/**
 *  <#Description#>
 *
 *  @param tableView
 *  @param sourceIndexPath              所要移動單元格的原始位置
 *  @param proposedDestinationIndexPath 將要移動到的位置
 *
 *  @return return value description
 */
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
    // 移動位置在同一分區(qū)
    if (sourceIndexPath.section == proposedDestinationIndexPath.section)
    {
        // 這時允許單元格移動
        return proposedDestinationIndexPath ;
    }
    // 不在同一分區(qū) 不讓單元格移動,返回原始的indexPath
    else
    {
        return sourceIndexPath ;
    }
}

以上是對 UITableView 控件的描述和使用,不以偏概全,只授之以漁,有更好的操作也會及時更新。如果您有UITableView控件的更好使用歡迎留言交流!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容