Sagit.Framework For IOS 自動布局教程:15、UITableView、UITableViewCell、UICollectionView、UICollectionViewCell特殊用法介紹 [2021-11-12更新]


前言:

框架對於UITableView、UITableViewCell 封裝了不少功能,下面開始介紹。

1、UITableView 基本定義。

 

@interface UITableView(ST)

#pragma mark 核心擴展
typedef void(^OnAddTableCell)(UITableViewCell *cell,NSIndexPath *indexPath);
typedef BOOL(^OnDelTableCell)(UITableViewCell *cell,NSIndexPath *indexPath);
typedef void(^OnAddTableCellAction)(STUITableViewCellAction *cellAction, NSIndexPath *indexPath);
typedef void(^OnAddTableSectionHeaderView)(UIView *sectionHeaderView,NSInteger section);
typedef void(^OnAddTableSectionFooterView)(UIView *sectionFooterView,NSInteger section);

typedef void(^OnAfterTableReloadData)(UITableView *tableView);
//!用於為Table追加每一行的Cell
@property (nonatomic,copy) OnAddTableCell addCell; //!用於為Table追加每一行的Cell的滑動菜單
@property (nonatomic,copy) OnAddTableCellAction addCellAction; //!用於為Table追加每一組Section的標題View
@property (nonatomic,copy) OnAddTableSectionHeaderView addSectionHeaderView;
//!用於為Table追加每一組Section的Bottom View
@property (nonatomic,copy) OnAddTableSectionFooterView addSectionFooterView;
//!用於為Table移除行的Cell
@property (nonatomic,copy) OnDelTableCell delCell;
//!用於為Table reloadData 加載完數據后觸發
@property (nonatomic,copy) OnAfterTableReloadData afterReload;
//!獲取Table的數據源
@property (nonatomic,strong) NSMutableArray<id> *source;
//!設置Table的數據源
-(UITableView*)source:(NSMutableArray<id> *)dataSource;
//!存檔所有Cell的高度(由系統控制)[存檔格式為:section key,[row Array]]
@property (readonly,nonatomic,retain) NSMutableDictionary *heightForCells;

//!是否重用Cell(默認Yes)
-(BOOL)reuseCell;
-(BOOL)reuseCell:(BOOL)yesNo;
//!是否自動控制Table的高度
-(BOOL)autoHeight;
//!設置是否自動控制Table的高度
-(UITableView*)autoHeight:(BOOL)yesNo;
//!獲取默認的UITableViewCellStyle
-(UITableViewCellStyle)cellStyle;
//!設置默認的UITableViewCellStyle
-(UITableView*)cellStyle:(UITableViewCellStyle)style;
//!獲取是否允許編輯【刪除】屬性
-(BOOL)allowEdit;
//!設置是否允許編輯【刪除】
-(UITableView*)allowEdit:(BOOL)yesNo;
//!移除數據源和數據行(並重新計算且刷新高度)
-(UITableView*)afterDelCell:(NSIndexPath*)indexPath;
#pragma mark 擴展屬性
-(UITableView*)scrollEnabled:(BOOL)yesNo;
//!分組數(默認1)
-(UITableView*)sectionCount:(NSInteger)count;
//!每個Section的num數:參數可以傳遞:@[@"1",@"2",@"2",@"1"] 或者:@"1,2,2,1"
-(UITableView*)rowCountInSections:(id)nums;
@end

2、UITableViewCell 基本定義:

@interface UITableViewCell(ST)
//!獲取當前所在的table,(weak,不能造成雙strong引用)
@property (readonly,nonatomic,weak) UITableView *table;
//!獲取Cell的數據源
@property (nonatomic,strong) id source;
//!Cell是否重用的Cell,如果是,就不要再添加子控制,避免重復添加。
//@property (readonly,nonatomic,assign) BOOL isReused;
//!設置Cell的數據源
-(UITableViewCell *)source:(id)dataSource;
//!創建或復用Cell
+ (instancetype)reuseCell:(UITableView *)tableView index:(NSIndexPath *)index;
//!獲取Cell所在的行數
-(NSIndexPath*)indexPath;
-(UITableViewCell*)indexPath:(NSIndexPath*)indexPath;
//!獲取是否允許刪除屬性
-(BOOL)allowDelete;
//!設置是否允許刪除
-(UITableView*)allowDelete:(BOOL)yesNo;
//!數據源中的第一個字段,系統自動設置
-(NSString*)firstValue;
-(UITableViewCell*)firstValue:(NSString*)value;
//當Cell的高度在綁定后,需要動態根據子內容高度變化,再次刷新高度時使用。
-(UITableViewCell*)resetHeightCache;
#pragma mark 擴展屬性
-(UITableViewCell*)accessoryType:(UITableViewCellAccessoryType)type;
-(UITableViewCell*)selectionStyle:(UITableViewCellSelectionStyle)style;

#pragma mark 擴展
//!獲取Cell的滑動菜單項。
@property (nonatomic,strong) STUITableViewCellAction *action;

@end

UITableView 基本用法示例一:

[[[[[sagit addTableView:nil] autoHeight:YES]  width:610] toCenter] block:^(UITableView* table)
     {
         [table relate:TopBottom v:60 v2:60];
         [table backgroundColor:ColorClear];
         table.backgroundView=[[[[UIImageView new] image:@"answer_bg_rank"]stretch] width:1 height:1];
         table.separatorColor = [ColorWhite alpha:0.2];
         table.separatorInset=UIEdgeInsetsMake(0,26, 0, 26);
         table.addCell = ^(UITableViewCell *cell, NSIndexPath *indexPath)
         {
             [cell width:1 height:140]; // 1 代表 100% <=1 被處理成百分比。
             cell.accessoryType=UITableViewCellAccessoryNone;
             cell.backgroundColor=ColorClear;
             
             
             //數據
             AnswerUserRankModel *model=[[AnswerUserRankModel new] initWithObject:cell.source];
             NSString *score=[[@(model.Score) stringValue] append:@""];
             
             [cell.contentView block:^(UIView* view)
              {
                  [view width:1 height:1];
                  if(indexPath.row!=table.source.count-1)
                  {
                      [[[[view addLine:nil color:@"#81F0D7"] width:2 height:30]y:140-15] relate:Right v:26];
                      [[[[view addLine:nil color:@"#81F0D7"] width:30 height:2] y:140] relate:Right v:26];
                  }
                  
                  [view addLabel:nil text:STNumString(model.Rank) font:30 color:ColorWhite];
                  [[STLastView x:50] toCenter:Y];
                  
                  [[[[view addImageView:nil] url:model.PhotoPath] width:80 height:80] corner:YES];
                  [[STLastView x:122] toCenter:Y];
                
                  [[[[view addLabel:nil text:model.NickName font:30 color:@"#FB8107"] onRight:STPreView x:42] toCenter:Y] width:72*2];
                  [[[view addImageView:nil img:@"answer_bg_rankscore"] width:196 height:20] block:^(UIImageView* scoreView)
                   {
                       [[scoreView x:192*2] toCenter:Y];
                       //[[scoreView relate:Right v:160] toCenter:Y];
                       [[scoreView addLabel:nil text:score font:30 color:@"#81F0D7"] toCenter];
                       //[scoreView stSizeToFit];
                   }];
                  [view onClick:^(id view)
                   {
                       [self stPush:[STNew(@"User") key:@"uid" value:model.UserID]];
                   }];
              }];
             
         };
     }];

效果:

 

 

UITableView 基本用法示例二:

 [[[[sagit addTableView:@"tableView" style:UITableViewStyleGrouped] autoHeight:YES] onBottom:STPreView y:20]  block:nil on:^(UITableView* table) {
        [table reuseCell:NO];
        table.addCell = ^(UITableViewCell *cell, NSIndexPath *indexPath)
        {
            NSString *name=cell.source[@"name"];
            NSString *title=cell.source[@"title"];
            NSString *holder=cell.source[@"holder"];
            if(holder==nil){holder=title;}
            NSString *pick=cell.source[@"pick"];
            NSString *maxLength=cell.source[@"maxLength"];
            
            [[[cell.contentView addLabel:nil text:title font:30] relate:Left v:50] toCenter:Y];//label是固定的。
            UIView *textView;
            
            if([title isEqualToString:@"簡介"])
            {
                textView=[[[[[cell.contentView addTextView:name placeholder:holder font:30] maxRow:3] maxLength:100]
                          textAlignment:NSTextAlignmentLeft] height:0.8];
                UIEdgeInsets inset=textView.asTextView.textContainerInset;
                inset.left-=5;
                textView.asTextView.textContainerInset=inset;
            }
            else
            {
                textView=[[cell.contentView addTextField:name placeholder:holder font:30] height:0.8];
                if(maxLength!=nil)
                {
                    [STLastTextField maxLength:[maxLength integerValue]];
                }
            }
            [[[textView onRight:STPreView x:50] relate:Right v:0] toCenter:Y];
            
            if(pick==nil)
            {
                cell.accessoryType=UITableViewCellAccessoryNone;
            }
            else
            {
                [[STLastView addClick:@"pick"] key:@"pick" value:pick];
            }
        };
        table.afterReload = ^(UITableView *tableView)
        {
            if(!self.hasLoaded)
            {
                self.hasLoaded=YES;
                [self setToAll:Sagit.Global.User.user];
            }
        };
        
    }];

效果:

 

數據源設置:

-(void)initData
{
    [super initData];//加載子UI的數據。
    UITableView *table=STFirstTable;
    table.source=@[@{@"title":@"姓名",@"name":@"NickName",@"maxLength":@"15"},
                   @{@"title":@"簡介",@"name":@"Description",@"holder":@"請簡單介紹一下自己!"},
                   @{@"title":@"公司",@"name":@"Company",@"holder":@"所在公司!",@"maxLength":@"20"},
                   @{@"title":@"年齡",@"name":@"Age",@"pick":@"年齡"},
                   @{@"title":@"學歷",@"name":@"Edu",@"pick":@"學歷"},
                   @{@"title":@"身高",@"name":@"Height",@"pick":@"身高"},
                   @{@"title":@"星座",@"name":@"Constellation",@"pick":@"星座"},
                   @{@"title":@"婚姻",@"name":@"MarrStatus",@"pick":@"婚姻"},
                   @{@"title":@"職業",@"name":@"Profession",@"pick":@"職業"},
                   @{@"title":@"收入",@"name":@"Wages",@"pick":@"月薪"}];
    
    [[table sectionCount:2] rowCountInSections:@"3,7"];
    //table.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f,1, 0.01f)];
    table.sectionFooterHeight=0.2;
    // table.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f,1, 1.0f)];
    //self.automaticallyAdjustsScrollViewInsets = NO;
    [table reloadData];
    
}

 

UITableView 基本用法示例三:循環嵌套[2021-11-11更新]

-(void)initUI
{
    [[[[sagit addTableView:nil]relate:TopBottom v:100 v2:200] backgroundColor:ColorRed] block:^(UITableView* table) {
        table.addCell = ^(UITableViewCell *cell, NSIndexPath *indexPath) {
            [cell backgroundColor:ColorGreen];
            [[cell addLabel:nil text:cell.firstValue] toCenter];
            [[[cell addSwitch:nil on:NO] onSwitch:^(UISwitch *view) {
                if(view.on)
                {
                    [self addTable:cell];
                }
                else
                {
                    [cell.lastSubView removeFromSuperview];
                    [cell refleshTableHeight];
                }
               
            }] relate:Right v:50];

        };
        table.source=@[@{@"a":@"aa"},@{@"a":@"bb"},@{@"a":@"cc"}];
        }];
}
-(void)addTable:(UITableViewCell*)cell
{
                    [[[[cell addTableView:nil] autoHeight:YES]  backgroundColor:ColorBlack] block:^(UITableView* cellTable) {
                        [[cellTable onBottom:cell.lastSubView.preView] x:0];
                        cellTable.addCell = ^(UITableViewCell *childCell, NSIndexPath *indexPath) {
                            childCell.accessoryType=UITableViewCellAccessoryNone;
                            [[childCell backgroundColor:ColorRandom] width:1 height:100];
                            NSString * value=childCell.firstValue;
                            [[childCell addLabel:nil text:value] toCenter];
                        };
                        cellTable.afterReload = ^(UITableView *tableView) {
                            [cell refleshTableHeight];
                           
                        };
                        cellTable.source=@[@{@"b":@"aaaa"},@{@"b":@"bb"},@{@"b":@"cc"}];
                    }];
}

代碼細節說明:

Table循環嵌套時,由於表格加載,有延后時,所以,需要在子表格的afterReolad事件(即加載完后)處理。

單元格新增了:refleshTableHeight:刷新表格高度。該方法僅會刷新單元格和表格的高度(不觸發table的reload事件)。

循環效果圖:

 

 

 

UICollectionView、UICollectionViewCell 基本定義

@interface UICollectionView(ST)
#pragma mark 核心擴展
typedef void(^AddCollectionCell)(UICollectionViewCell *cell,NSIndexPath *indexPath);
typedef BOOL(^DelCollectionCell)(UICollectionViewCell *cell,NSIndexPath *indexPath);
//!用於為Table追加每一行的Cell
@property (nonatomic,copy) AddCollectionCell addCell;
//!用於為Table移除行的Cell
@property (nonatomic,copy) DelCollectionCell delCell;
//!獲取Table的數據源
@property (nonatomic,strong) NSMutableArray<id> *source;
//!設置Table的數據源
-(UITableView*)source:(NSMutableArray<id> *)dataSource;
@end

---------------------------------------------

@interface UICollectionViewCell(ST)
//!獲取Cell的數據源
@property (nonatomic,strong) NSMutableDictionary<NSString*,id> *source;
//!設置Cell的數據源
-(UICollectionViewCell *)source:(NSMutableDictionary<NSString*,id> *)dataSource;
//!創建或復用Cell
+ (instancetype)reuseCell:(UICollectionView *)tableView index:(NSIndexPath *)index;
//!獲取當前所在的table
-(UICollectionView*)table;

//!獲取是否允許刪除屬性
//-(BOOL)allowDelete;
//!設置是否允許刪除
//-(UITableView*)allowDelete:(BOOL)yesNo;
//!數據源中的第一個字段,系統自動設置
-(NSString*)firstValue;
-(UICollectionViewCell*)firstValue:(NSString*)value;
@end

 

這兩個和上面兩個的用法基本一致,功能比上面的還少,就不過多介紹了。

3、左滑菜單說明

如果左滑的菜單只有刪除,那么只需要設置:

[table allowEdit:YES]

刪除點擊的事件:

table.delCell = ^BOOL(UITableViewCell *cell, NSIndexPath *indexPath)
    {
        [Sagit.RongYun removeFromBlacklist:cell.firstValue success:^{
            [this.http get:UrlSetBlacklist paras:@{@"blackUserID":cell.firstValue, @"blackFlag":@"2"} success:^(STHttpModel *result) {
                if (result.success)
                {
                    [cell.table afterDelCell:indexPath];
                }
            } ];
        } error:^(RCErrorCode status) {

        }];

        return false;
    };

默認是處理完業務,return true;(之后框架會調用 afterDelCell 移除行並重繪高度)。

如果有異步操作,也可以先return false; 再根據結果自己調用 afterDelCell 方法。

如果涉及到添加多個菜單:

原生事件:

-(NSArray<UITableViewRowAction*>*)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
    RCConversationModel *model = self.conversationListDataSource[indexPath.row];
    UITableViewRowAction *del  = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:@"刪除" handler:^(UITableViewRowAction * _Nonnull action,NSIndexPath * _Nonnull indexPath) {
    ......
    }];
    
    UITableViewRowAction *top  = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"置頂" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
       ......
    }];
    top.backgroundColor        = STColor(@"#fe9d00");
    return @[del, top];
}

框架用法 [2020-09-17更新]

 table.addCellAction = ^(STUITableViewCellAction *actions, NSIndexPath *indexPath) {
            [actions addAction:@"置頂" bgColor:ColorRed onAction:nil];
            [actions addAction:@"刪除2" bgColor:ColorBlack onAction:^(UITableViewCell *cell, NSIndexPath *indexPath) {
                //點擊事件。
            }];
        };

結果圖:

如果需要自定義滑動菜單:

【原生的方法:可以改變樣式,但改變不了坐標,所以在原生的基礎上添加自己的視圖即可】

- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
    
        UITableViewCell *cell=[tableView cellForRowAtIndexPath:indexPath];
        if(cell!=nil)
        {
            UIView *uiSwipeActionPullView=cell.superview.subviews[0]; //UISwipeActionPullView
            if([uiSwipeActionPullView isKindOfClass:[UITableViewCell class]])
            {
                //IOS 13 以下。
                for (UIView *view in tableView.subviews) {
                    if([view isKindOfClass:NSClassFromString(@"UISwipeActionPullView")])
                    {
                        uiSwipeActionPullView=view;
                        break;
                    }
                }
            }
            //uiSwipeActionPullView=>UISwipeActionStandardButton => UIView,UIButtonLabel
            for (UIView * btnView in uiSwipeActionPullView.subviews) {
                [btnView backgroundColor:STDeviceColor];
                [btnView removeAllSubViews];
                [[[[[[btnView addButton:nil title:@"click" font:24 color:ColorGreen img:nil] width:120 height:0.8] layerCornerRadius:24]
                   toCenter:Y] backgroundColor:ColorBlue] x:20];
            }
        }
}

滑動后的布級層級:(IOS 13) 【IOS13以下的View層級是在UITableView下

框架用法 [2020-09-17更新] 

 table.addCellAction = ^(STUITableViewCellAction *actions, NSIndexPath *indexPath) {
            [actions addAction:^(UIView *cellSwipeView, NSIndexPath *indexPath) {
                [[[[[[cellSwipeView addButton:nil title:@"click" font:24 color:ColorGreen img:nil] width:120 height:0.8] layerCornerRadius:24]
                   toCenter:Y] backgroundColor:ColorBlue] x:20];
            } onAction:nil];
        };

效果圖:

 

PS:addAction 有兩個重載方法,一個用於原生的文字和背景色調整;另一個用於自定樣式。

4、分區標題

原生用法:

// 設置表頭的高度。如果使用自定義表頭,該方法必須要實現,否則自定義表頭無法執行,也不會報錯
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 80*Ypt;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

{

    UIView *view=[[[UIView new] width:1 height:80] backgroundColor:[ColorBlue alpha:0.5]];
    [[[view addLabel:nil text:@"title"] toCenter] sizeToFit];
    [[view stSizeToFit] layerCornerRadius:20 byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight];
 
    return view;
}

框架用法: [2021-11-11更新]

table.addSectionHeaderView = ^(UIView *sectionView, NSInteger section) {
            [sectionView backgroundColor:[ColorBlue alpha:0.5]];
            [[[sectionView addLabel:nil text:@"title"] toCenter] sizeToFit];
            [[sectionView stSizeToFit] layerCornerRadius:20 byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight];
        };

結果圖片:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM