iOS基础之滚动视图(UIScrollView、UITableView、UICollectionView、)

目录
  1. UIScrollView: UIView 
  2. UITableView: UIScrollView
  3. UICollectionView : UIScrollView

1. UIScrollView 滚动视图(: UIView)

    UIScrollView *contentSV=[UIScrollView new];
    [self.view addSubview:contentSV];

常用

    // 设置 frame(显示区域的大小)
    [contentSV setFrame:CGRectZero];
    // 设置 contentSize(内容的大小(默认为CGSizeZero,必须设置,否则不滚动)(宽为0时只滚动高))
    [contentSV setContentSize:CGSizeMake(100, 100)];

    // 设置 偏移量(让scrollView滚动x,y)(固定的UI左上角-移动的内容左上角)
    [contentSV setContentOffset:CGPointMake(100, 100)];
    [contentSV setContentOffset:CGPointZero animated:true];
    // 设置 内容周边(上,左,下,右)
    [contentSV setContentInset:UIEdgeInsetsZero];
    
    // 设置 弹簧效果 滚动到边界时反弹(默认true)
    [contentSV setBounces:true];
    // 设置 是否以页为单位(默认false)滚动
    [contentSV setPagingEnabled:true];

    // 设置 最小缩放比例
    [contentSV setMinimumZoomScale:0.5];
    // 设置 最大缩放比例
    [contentSV setMaximumZoomScale:2.0];
    
滚动    
    // 设置 是否允许滚动
    [contentSV setScrollEnabled:true];
    // 设置 是否只允许一个方向滚动(默认false)
    [contentSV setDirectionalLockEnabled:true];
    // 设置 是否纵向永远可滚动
    // 当sv中的子View小于sv的可视大小时默认不允许滚动,设置后允许纵向滚动(默认false )
    [contentSV setAlwaysBounceVertical:true];
    // 设置 是否横向永远可滚动
    [contentSV setAlwaysBounceHorizontal:true];

滚动条
    // 设置 滚动条距sv边距
    [contentSV setScrollIndicatorInsets:UIEdgeInsetsZero];
    // 设置 滚动条风格
    [contentSV setIndicatorStyle:UIScrollViewIndicatorStyleBlack];
    /*
     UIScrollViewIndicatorStyleDefault,
     UIScrollViewIndicatorStyleBlack,
     UIScrollViewIndicatorStyleWhite
     */
    // 设置 是否允许显示纵向滚动条
    [contentSV setShowsVerticalScrollIndicator:true];
    // 设置 是否允许显示横向滚动条
    [contentSV setShowsHorizontalScrollIndicator:true];
    // 获取 是否开始触摸
    BOOL isTracking=[contentSV isTracking];
    // 获取 是否开始触摸滑动
    BOOL isDragging=[contentSV isDragging];
    // 获取 是否手指释放后正在滑动
    BOOL isDecelerating=[contentSV isDecelerating];
    // 设置 是否允许滚动到顶部(可定义一个按钮用来滚动到最上方)
    [contentSV setScrollsToTop:true];
    // 滚动到rect,一般用contentOffset
    [contentSV scrollRectToVisible:CGRectZero animated:true];
    // 设置 手指抬起后的减速率
    [contentSV setDecelerationRate:UIScrollViewDecelerationRateNormal];
    /*
     UIScrollViewDecelerationRateNormal
     UIScrollViewDecelerationRateFast
     */
    // 设置 滚动时键盘的显示style,默认不消失
    [contentSV setKeyboardDismissMode:UIScrollViewKeyboardDismissModeOnDrag];
    /*
     UIScrollViewKeyboardDismissModeNone
     UIScrollViewKeyboardDismissModeOnDrag
     UIScrollViewKeyboardDismissModeInteractive
     */
    //
    

    // 获取 是否正在缩放
    BOOL isZooming=[contentSV isZooming];
    // 获取 是否缩放超出临界值
    BOOL isZoomBouncing=[contentSV isZoomBouncing];
    // 获取 缩当前放比例
    CGFloat zoomScale=[contentSV zoomScale];
    // 缩放到某矩形块
    [contentSV zoomToRect:CGRectMake(0, 0, 100, 100) animated:true];
    // 缩放(动画)
    [contentSV setZoomScale:0.6 animated:true];
    [contentSV setZoomScale:0.6];
    
    // 设置 背景色
    [contentSV setBackgroundColor:[UIColor blackColor]];

dele

    // dele<UIScrollViewDelegate>
    [contentSV setDelegate:self];

// 滑动时调用(持续触发)
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{}
// 1.手指即将触摸前调用(此时可销毁计时器)
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{}
// 2.手指离开后调用(此时可启动计时器)    (decelerate:是否会继续滚动)
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{}
// 3.即将减速时调用
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView{}
// 4.停止减速时调用
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{}
// 5.完全停止后调用(手动滑动不调用)    设置偏移量调用
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView{}

// 是否允许滚动到顶部
- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView{return true;}
// 滚动到顶部后调用
- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView{}

//
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{}
// 
- (void)scrollViewDidChangeAdjustedContentInset:(UIScrollView *)scrollView{};

缩放
// (缩放必须+maxmin缩放值,否则不能缩放)
// 返回要缩放的对象
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{}
// 开始缩放前调用
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view{}
// 缩放时调用(持续触发)
- (void)scrollViewDidZoom:(UIScrollView *)scrollView{}
// 结束缩放后调用
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view atScale:(CGFloat)scale{}
使用Masonry自动布局时,UIScrollView有点特殊,通常我会
  每一个子View明确设定宽高。
  最后一个View多加一个距下的约束

2. UITableView(: UIScrollView)

  1. 概念
举个不太恰当的例子(一个UITableView就好像一列火车):
    火车头  车厢头-座-车厢尾  车厢头-座-座-车厢尾  火车尾
    火车头:tableHeaderView
    火车尾:tableFooterView
    车厢头:sectionHeader
    车厢尾:sectionFooter
    一行座:cell

复用原理
  1、UITableView有2个数组(可视数组 和 复用数组)。当需要显示Cell时,先从复用数组中查找,如果有则复用,如果没有则创建并加入到可视数组中。当cell不再需要显示时,将cell从可视数组中移除,并放入复用数组。
  2、通过不同的identify标示符来复用不同类型的Cell。

其他事项
  1、一个tableView只能有一个数据源,一个Controller可以有多个tableView(通过tag进行区分,不建议这样写,太多的判断。可以将每个tableView分散写在各自的View中)。
  2、cell高度可变:在Model中加个height属性覆写get方法

使用
  1、创建UITableView并配置,设置dele。
  2、注册CELL、HeadFootView
  3、实现代理方法
  1. 使用

// 创建
UITableView *contentTV=[UITableView new];
[self.view addSubview:contentTV];

    // 设置预估 行-组头-组尾 高,(必须+,版本间适配,避免UI发生错乱)
    [contentTV setEstimatedRowHeight:0];
    [contentTV setEstimatedSectionHeaderHeight:0];
    [contentTV setEstimatedSectionFooterHeight:0];
    // 
    if (@available(iOS 11.0, *)) {
        contentTV.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    } else {
        // 当controller的第一个View属于UIScrollView类型,设置为true则以导航栏左下角为坐标原点
        self.automaticallyAdjustsScrollViewInsets = NO;
    }
/**
safeAreaInset(不需手动设置)
安全区域(可视区域。减去StatusBar、NavigationBar、TabBar的高,距离屏幕上下左右的距离)

iOS 11中Controller的automaticallyAdjustsScrollViewInsets属性被废弃,替代为contentInsetAdjustmentBehavior自适应内容边距

typedef NS_ENUM(NSInteger, UIScrollViewContentInsetAdjustmentBehavior) {
        UIScrollViewContentInsetAdjustmentAutomatic, 
        UIScrollViewContentInsetAdjustmentScrollableAxes,  在可滚动方向上使用安全区域
        UIScrollViewContentInsetAdjustmentNever, 禁用安全区域
        UIScrollViewContentInsetAdjustmentAlways,  使用安全区域
    } API_AVAILABLE(ios(11.0),tvos(11.0));
*/

    // 设置dele,<UITableViewDelegate,UITableViewDataSource>
    [contentTV setDelegate:self];
    [contentTV setDataSource:self];

    // 注册cell
    [contentTV registerClass:[UITableViewCell class] forCellReuseIdentifier:NSStringFromClass([UITableViewCell class])];
    [contentTV registerNib:[UINib nibWithNibName:@"" bundle:nil] forCellReuseIdentifier:@""];
    // 注册 head、foot视图
    [contentTV registerClass:[] forHeaderFooterViewReuseIdentifier:@""];
    [contentTV registerNib:[UINib nibWithNibName:@"" bundle:nil] forHeaderFooterViewReuseIdentifier:@""];

常用属性/方法

背景
    // 设置 背景色
    [contentTV setBackgroundColor:[UIColor whiteColor]];
    // 设置 bgView
    [contentTV setBackgroundView:[UIView new]];

分割线
    // 设置 分割线style
    [contentTV setSeparatorStyle:UITableViewCellSeparatorStyleNone];
    // 设置 分割线的颜色
    [contentTV setSeparatorColor:[UIColor blackColor]];

头、尾视图
    // 设置 头、尾视图
    [contentTV setTableHeaderView:[UIView new]];
    [contentTV setTableFooterView:[UIView new]];

纵向滚动条
    // 设置 纵向滚动条是否隐藏
    [contentTV setShowsVerticalScrollIndicator:false];

行高、组头、组尾视图高(本质还是去调用dele方法)
    // 设置 行高、组头、组尾视图高
    [contentTV setRowHeight:65];
    [contentTV setSectionHeaderHeight:10];
    [contentTV setSectionFooterHeight:10];
是否进入编辑模式
    [contentTV setEditing:true];
    [contentTV setEditing:true animated:true];

刷新
    // 刷新 UI(更新dataSourceArr数据源后再调用)
    [contentTV reloadData];
    // 刷新 指定组
    [contentTV reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationTop];
    /*
     UITableViewRowAnimationFade,
     UITableViewRowAnimationRight,
     UITableViewRowAnimationLeft,
     UITableViewRowAnimationTop,
     UITableViewRowAnimationBottom,
     UITableViewRowAnimationNone,
     UITableViewRowAnimationMiddle,
     UITableViewRowAnimationAutomatic
     */
    // 刷新 指定行
    [contentTV reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationTop];
    // 刷新 索引标题
    [contentTV reloadSectionIndexTitles];

滚动
    // 滚动到 指定行
    [contentTV scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:true];
    // 滚动到 最近被选中的cell
    [contentTV scrollToNearestSelectedRowAtScrollPosition:UITableViewScrollPositionTop animated:true];

移动
    // 移动 行
    [contentTV moveRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] toIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
    // 移动 组
    [contentTV moveSection:0 toSection:1];

删除
    // 删除 行
    [contentTV deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationTop];
    // 删除 组
    [contentTV deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationTop];

插入
    // 插入 行
    [contentTV insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationTop];
    // 插入 组
    [contentTV insertSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationTop];
    
选中
    // 选中某行
    [contentTV selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:true scrollPosition:UITableViewScrollPositionTop];
    // 反选某行
    [contentTV deselectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:true];
    // 获取 选中行indexPath
    NSIndexPath *indexPath=[contentTV indexPathForSelectedRow];
    // 获取 选中行indexPathArr
    NSArray *indexPathArr=[contentTV indexPathsForSelectedRows];
    // 选中 cell
    [cell setSelected:true];
    // 是否允许选中
    [_tableView setAllowsSelection:true];
    // 是否允许多选
    [_tableView setAllowsMultipleSelection:true];
    // 编辑时是否允许选中
    [_tableView setAllowsSelectionDuringEditing:true];
    // 编辑时允许多选
    [_tableView setAllowsMultipleSelectionDuringEditing:true];

可视cell
    // 可视cell的indexPath数组
    NSArray<NSIndexPath *> *visibleArr=[contentTV indexPathsForVisibleRows];

指定cell
    // 获取 指定indexPath的cell
    // indexPath:[NSIndexPath indexPathForRow:0 inSection:0]
    UITableViewCell *cell=[contentTV cellForRowAtIndexPath:indexPath];

dele代理方法

常用

// 返回 组数
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{return 0;}
// 返回 行数(@required)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{return 0;}
// 返回 行高
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return 65;
}
// (@required)
// 返回每行(每当重新出现在界面上时,都调用一次)(向cell中添加子控件时最好加在contentView中:统一管理)
// 内存中:可见队列和可重用队列,当cell滚动出视图后,则从可见队列移出移入到可重用队列;当cell显示在界面上时先从可重用队列中查找,若有则从可重用队列移出并移入可见队列,若没有则重新创建并放入可见队列
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:@"" forIndexPath:indexPath];
    return cell;
}

点击

// 点击一行时调用
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{}

// 反选一行时调用
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{}
// 即将选中一行时调用
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath{}
// 即将反选反选一行时调用
- (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath{}

// 返回 组头视图高
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{return 100;}
// 返回 组尾视图高
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{return 100;}
// 返回 组头视图
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{return [UIView new];}
// 返回 组尾视图
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{return [UIView new];}
// 返回 组头标题
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{return @"";}
// 返回 组尾标题
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section{return @"";}

索引

// 返回 索引标题数组
- (NSArray<NSString *> *)sectionIndexTitlesForTableView:(UITableView *)tableView{return @[@"A"];}
// 返回 标题索引(每次点击索引标题后调用 跳到相应section,从0开始,加上搜索图标后-1)
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index{return index;}

移动

// 返回 是否允许移动
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath{return true;}
// 移动后调用
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{}
// 移动行的过程中会多次调用(用来限制只能在本section中移动)
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath{return sourceIndexPath;}

左滑编辑

// 返回 向左滑动时,自定义按钮上的删除文本
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath{return @"删";}
// 向左滑动时,自定义右边编辑按钮 (可编辑类型)
- (NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath{
    return @[[UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
    }]];
}
// 返回 是否允许编辑
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{return true;}
// 返回 每行的编辑style
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
    return UITableViewCellEditingStyleDelete;
    /*
     UITableViewCellEditingStyleNone,
     UITableViewCellEditingStyleDelete,
     UITableViewCellEditingStyleInsert
     */
}
// 即将编辑前调用
- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath{}
// 结束编辑后调用
- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(nullable NSIndexPath *)indexPath{}
// 编辑时调用
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{}
// 返回 编辑时是否对指定行向左缩进
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath{return true;}
// 返回 每行行缩进
- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath{return 60;}

长按

// 返回 每行长按时 是否允许Menu菜单
- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath{return true;}
// 返回 每行出现菜单时 可以做某种操作
- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender{return true;}
// 点击菜单 某项后调用
- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender{}

cell右侧图标

// 返回 cell右侧图标
- (UITableViewCellAccessoryType)tableView:(UITableView *)tableView accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath{
    return UITableViewCellAccessoryCheckmark;
    /*
     UITableViewCellAccessoryNone,
     UITableViewCellAccessoryDisclosureIndicator,
     UITableViewCellAccessoryDetailDisclosureButton
     UITableViewCellAccessoryCheckmark,
     UITableViewCellAccessoryDetailButton
     */
}
// 点击 cell右侧图标时调用
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath{}

高亮

// 是否 允许行高亮
- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath{return true;}
// 某行 高亮后调用
- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath{}
// 某行 被反高亮后调用
- (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath{}

即将显示、完全消失

// 即将显示cell时调用
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{}
// 完全隐藏cell后调用
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath{}

// 即将显示head视图时调用
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section{}
// 完全隐藏head后调用
- (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section{}

// 即将显示foot视图时调用
- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section{}
// 完全隐藏foot后调用
- (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section{}

预估高

// 返回预估行高、预估组头视图高、预估组尾视图高
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{}
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForHeaderInSection:(NSInteger)section{}
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForFooterInSection:(NSInteger)section{}

CELL

  1. 系统CELL(基本不用)
    // 类型
    UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:@"iden"];
    if(!cell){
        cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"iden"];
    }
    /*
     UITableViewCellStyleDefault,       // 从左到右(imageView(可选)->textLabel
     UITableViewCellStyleValue1,        // 从左到右(imageView(可选)->textLabel(粗黑)->detailTextLabel(右侧、蓝)
     UITableViewCellStyleValue2,        // 从左到右(imageView(可选)->textLabel(蓝)->detailTextLabel(紧跟textLabel)
     UITableViewCellStyleSubtitle       // 从左到右(imageView(可选)->textLabel(上方、粗黑),detailTextLabel(下方、灰色)
     */

    cell.textLabel
    cell.imageView
    cell.detailTextLabel

    // 右侧小图标
    [cell setAccessoryType:UITableViewCellAccessoryCheckmark];
    /*
     UITableViewCellAccessoryNone,                      // 无
     UITableViewCellAccessoryDisclosureIndicator,       // >
     UITableViewCellAccessoryDetailDisclosureButton     // ?>
     UITableViewCellAccessoryCheckmark,                 // 对勾
     UITableViewCellAccessoryDetailButton               // 信息按钮
     */
    // 右侧小图标(自定义)
    [cell setAccessoryView:[UIView new]];
    // 分割线距屏幕两边为0(默认左方有间隙)
    [cell setSeparatorInset:UIEdgeInsetsZero];
    [cell setLayoutMargins:UIEdgeInsetsZero];
    // 选中后的状态(tableView选中后,它的子控件的背景色将没了)
    [cell setSelectionStyle:UITableViewCellSelectionStyleBlue];
    /*
        UITableViewCellSelectionStyleNone   // 无
        UITableViewCellSelectionStyleBlue   // 变蓝
        UITableViewCellSelectionStyleGray   // 变灰
        UITableViewCellSelectionStyleDefault
     */
  1. 自定义CELL :UITableViewCell

方式一(未经过registerClass,基本不用)

在基类中

Cell.h
+(instancetype)CreateWithTableView:(UITableView *)tableView;


Cell.m
+(instancetype)CreateWithTableView:(UITableView *)tableView{
    
    YTPlaceTableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:NSStringFromClass([YTPlaceTableViewCell class])];
    if(!cell){
        cell=[[YTPlaceTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NSStringFromClass([YTPlaceTableViewCell class])];
    }
    
    return cell;
}
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
    self=[super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if(self){
        self.selectionStyle=UITableViewCellSelectionStyleNone;
        // UI
        [self setupUI];
    }
    return self;
}
-(void)setupUI{
}

方式二(使用registerClass,常用)

Cell.h

@interface Cell : UITableViewCell
-(void)cellWithIndexPath:(NSIndexPath *)indexPath withModel:(id)model;
@end


Cell.m

@interface Cell()
各种控件 与 约束
@property (nonatomic,weak) UIView *headView;
@property (nonatomic,strong) NSLayoutConstraint *headC;
@end

@implementation Cell
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
    self=[super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if(self){
        self.selectionStyle=UITableViewCellSelectionStyleNone;
        // UI
        [self setupUI];
    }
    return self;
}
-(void)setupUI{
}
-(void)cellWithIndexPath:(NSIndexPath *)indexPath withModel:(id)model{
  给各种控件赋值
  更新布局约束
}
// 通过xib创建的cell
- (void)awakeFromNib {
    [super awakeFromNib];
    [self setupUI];
}
@end

3. UICollectionView (: UIScrollView)

  1. 使用
    // 1.创建 布局对象
    UICollectionViewFlowLayout *fl=[UICollectionViewFlowLayout new];
    // 设置 滚动方向
    [fl setScrollDirection:UICollectionViewScrollDirectionVertical];
/*
以下通常不在这里设置,而是通过dele方法设置
(本质上也还是会调用相应的dele方法,dele的优先级高)
    // 设置 最小行间距
    [fl setMinimumLineSpacing:10];
    // 设置 最小项间距
    [fl setMinimumInteritemSpacing:10];
    // 设置 项大小
    [fl setItemSize:CGSizeMake(200, 100)];
    // 设置 组内边距
    [fl setSectionInset:UIEdgeInsetsZero];
    // 垂直滚动时 高起作用(宽无效 为collV宽),水平滚动时 宽起作用(高无效 为collV高)
    // 设置 头视图大小
    [fl setHeaderReferenceSize:CGSizeMake(100, 100)];
    // 设置 尾视图大小
    [fl setFooterReferenceSize:CGSizeMake(100, 100)];
*/

    // 2.创建 UICollectionView    : UIScrollView
    UICollectionView *contentCollV=[[UICollectionView alloc]initWithFrame:CGRectZero collectionViewLayout:fl];
    // 设置 dele<UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
    [contentCollV setDelegate:self];
    [contentCollV setDataSource:self];
    [self.view addSubview:contentCollV];
    // 3.注册 cell
    [contentCollV registerClass:[] forCellWithReuseIdentifier:NSStringFromClass([])];
    [contentCollV registerNib:[UINib nibWithNibName:@"" bundle:nil] forCellWithReuseIdentifier:@""];
    // 3.注册 head、foot视图
    [contentCollV registerClass:[] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:NSStringFromClass([])];
    [contentCollV registerNib:[UINib nibWithNibName:@"" bundle:nil] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@""];
    // 删除 指定组
    [contentCollV deleteSections:[NSIndexSet indexSetWithIndex:0]];
    // 删除 指定项
    [contentCollV deleteItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:0 inSection:0]]];
    // 插入 指定组
    [contentCollV insertSections:[NSIndexSet indexSetWithIndex:0]];
    // 插入 指定项
    [contentCollV insertItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:0 inSection:0]]];
    // 获取 指定indexPath对应的项
    UICollectionViewCell *cell=(UICollectionViewCell *)[contentCollV cellForItemAtIndexPath:indexPath];

自定义相关基类

自定义基类CELL BaseCell: UICollectionViewCell

-(instancetype)initWithFrame:(CGRect)frame{
    self=[super initWithFrame:frame];
    if(self){
        [self setupUI];
    }
    return self;
}
-(void)setupUI{  // 拿到.h中,对外
}
自定义头尾视图 BaseHeadFootView:UICollectionReusableView
// 初始化控件
-(void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes{  
  [self setupUI];
}
-(void)setupUI{  // 拿到.h中,对外
}

遇到过的一个需求:更新数据源后立刻设置contentOffset

        [self.matchCollectionView reloadData];
        [self.matchCollectionView layoutIfNeeded];  // 如果不加,会导致setContentOffset没效果
        [self.matchCollectionView setContentOffset:CGPointMake(kScreenWidth, 0)];

dele

<UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>

常用

// 返回 组数
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{return 0;}
// 返回 每组的项数
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{return 0;}
// 返回 每项大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{return CGSizeMake(100, 100);}
// 返回 每项
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"" forIndexPath:indexPath];
    return cell;
}
// 返回 每项的最小行间距
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section{return CGFLOAT_MIN;}
// 返回 每项的最小列间距
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section{return CGFLOAT_MIN;}
// 返回 组间距
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{return UIEdgeInsetsZero;}
// 返回 头视图的size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section{return CGSizeMake(100, 100);}
// 返回 尾视图的size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section{return CGSizeMake(100, 100);}
// 返回 头视图、尾视图
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath{
    if([kind isEqualToString:UICollectionElementKindSectionHeader]){
        UICollectionReusableView *headV=[collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"" forIndexPath:indexPath];
        return headV;
    }else{
        UICollectionReusableView *footV=[collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"" forIndexPath:indexPath];
        return footV;
    }
    return [UICollectionReusableView new];
}

选中/反选

// 是否允许选择项
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath{return true;}
// 选择某项后调用
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{}
// 是否允许反选项
- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath{return true;}
// 反选某项后调用
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath{}

高亮

// 是否 允许项高亮
- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath{return true;}
// 项高亮后调用
- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath{}
// 项反高亮后调用
- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath{}

移动

// 是否允许移动项
- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath{return true;}
// 移动项后调用
- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath*)destinationIndexPath{}

索引(仅tvos系统可用,iOS系统不可用)

// 返回 索引
- (NSArray<NSString *> *)indexTitlesForCollectionView:(UICollectionView *)collectionView{return @[@"A",@"B"];}
// 返回 索引下标
- (NSIndexPath *)collectionView:(UICollectionView *)collectionView indexPathForIndexTitle:(NSString *)title atIndex:(NSInteger)index{}

长按

// 长按时是否显示菜单
- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath{return true;}
// 是否允许某操作
- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender{return true;}
// 进行某种操作时调用
- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender{}

即将显示/结束显示 (滚动至临界部位,作相应回调。例:左右两边都是列表,滚动右边后 联动左边的选中项。最常见于电商)

// 即将显示项时调用
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{}
// 即将显示头尾视图时调用
- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath{}
// 结束显示项时调用
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{}
// 结束显示头尾视图时调用
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath{}

常见

  1. 流布局

  2. 一组标签,向左对齐(默认一行上,会分散对齐)

解决:

  创建UICollectionViewFlowLayout子类,并进行相关配置
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容