目录
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)
- 概念
举个不太恰当的例子(一个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、实现代理方法
- 使用
// 创建
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
- 系统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
*/
- 自定义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.创建 布局对象
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{}
常见
流布局
一组标签,向左对齐(默认一行上,会分散对齐)
解决:
创建UICollectionViewFlowLayout子类,并进行相关配置