首次提交
This commit is contained in:
22
Pods/SDAutoLayout/LICENSE
generated
Executable file
22
Pods/SDAutoLayout/LICENSE
generated
Executable file
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 GSD_iOS
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
188
Pods/SDAutoLayout/README.md
generated
Executable file
188
Pods/SDAutoLayout/README.md
generated
Executable file
@@ -0,0 +1,188 @@
|
||||
# SDAutoLayout(一行代码搞定自动布局!)
|
||||
|
||||
##众多公司和个人开发者已经使用本库布局:
|
||||
SDAutoLayout使用者开发的部分app截图 http://www.jianshu.com/p/9bc04d3effb8
|
||||
|
||||
一行代码搞定自动布局!致力于做最简单易用的Autolayout库。The most easy way for autolayout.
|
||||
|
||||
## 技术支持(QQ交流群):
|
||||
|
||||
497140713(1群) 519489682(2群已满)
|
||||
|
||||
## Pod支持:
|
||||
|
||||
支持pod: pod 'SDAutoLayout', '~> 2.1.3'
|
||||
|
||||
如果发现pod search SDAutoLayout 搜索出来的不是最新版本,需要在终端执行cd转换文件路径命令退回到desktop,然后执行pod setup命令更新本地spec缓存(可能需要几分钟),然后再搜索就可以了
|
||||
|
||||
## 更新记录:
|
||||
|
||||
2018.07.02 -- 修复了部分布局组合下view居中布局失效bug
|
||||
|
||||
2017.11.11 -- 实现控制富文本可显示行数功能
|
||||
|
||||
2017.11.11 -- 解决朋友圈demo在iOS11上文字收折或者展开时出现cell跳动问题
|
||||
|
||||
2017.06.26 -- 解决部分开发者反应因出现“UITableViewCellContentView”而导致应用审核被拒问题
|
||||
|
||||
2016.08.12 -- 实现在tableview插入新的cell数据时自动缓存管理
|
||||
|
||||
2016.06.30 -- 增加多参照view的leftSpaceToView和topSpaceToView约束,例:topSpaceToView(@[self.view3, self.view4], 30)
|
||||
|
||||
2016.06.24 -- 修复给button设置约束时在iOS8.x系统中出现的崩溃问题;发布2.1.2版本
|
||||
|
||||
2016.06.23 -- 实现删除某行cell时自动调整height缓存
|
||||
|
||||
2016.05.16 -- 修复用xib生成的view出现的部分约束失效问题(发布pod2.0.0版本)
|
||||
|
||||
2016.05.15 -- 增加设置偏移量offset功能
|
||||
|
||||
2016.04.30 -- 修复之前button作为父视图时内部控件不能自动布局问题
|
||||
|
||||
2016.04.05 -- 修复宽度自适应label在重用时候偶尔出现的宽度计算不准确的问题(发布pod1.51版本)
|
||||
|
||||
2016.03.23 -- 升级了缓存机制,新版本在tableview滑动cell时候流畅度和性能提升20%以上(发布pod1.50版本)
|
||||
|
||||
2016.01.23 -- 增加label对attributedString的内容自适应
|
||||
|
||||
2016.01.21 -- 实现tableview局部刷新cell高度缓存的自动管理
|
||||
|
||||
2016.01.20 -- demo适配在ios7上的屏幕旋转问题
|
||||
|
||||
2016.01.18 -- 推出“普通简化版”tableview的cell自动高度方法(推荐使用),原来的需2步设置的普通版方法将标记过期
|
||||
|
||||
2016.01.13 -- 增加在不确定bottom view的情况下的cell高度自适应方法
|
||||
|
||||
2016.01.07 -- 1.增加 scrollview 横向内容自适应功能;2.增加view宽高相等的功能
|
||||
|
||||
2016.01.03 -- 增加任何类型对象都可以实现一行代码搞定cell高度自适应;增加文档注释
|
||||
|
||||
2015.12.08 -- 重大升级:1.支持scrollview内容自适应;2.任意添加或者修改约束不冲突;3.性能提升40%以上;4.添加最大、最小宽高约束
|
||||
|
||||
|
||||
## 视频教程:
|
||||
☆☆ SDAutoLayout 基础版视频教程:http://www.letv.com/ptv/vplay/24038772.html ☆☆
|
||||
|
||||
☆☆ SDAutoLayout 进阶版视频教程:http://www.letv.com/ptv/vplay/24381390.html ☆☆
|
||||
|
||||
☆☆ SDAutoLayout 原理简介视频教程:http://www.iqiyi.com/w_19rt0tec4p.html ☆☆
|
||||
|
||||
☆☆ SDAutoLayout 朋友圈demo视频教程:http://v.youku.com/v_show/id_XMTYzNzg2NzA0MA==.html ☆☆
|
||||
|
||||
## 部分SDAutoLayout的DEMO:
|
||||
|
||||
完整微信Demo https://github.com/gsdios/GSD_WeiXin
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
# 用法简介
|
||||
|
||||
## tableview和cell高度自适应:
|
||||
|
||||
####普通(简化)版【推荐使用】:tableview 高度自适应设置只需要2步
|
||||
|
||||
1. >> 设置cell高度自适应:
|
||||
// cell布局设置好之后调用此方法就可以实现高度自适应(注意:如果用高度自适应则不要再以cell的底边为参照去布局其子view)
|
||||
[cell setupAutoHeightWithBottomView:_view4 bottomMargin:10];
|
||||
|
||||
2. >> 获取自动计算出的cell高度
|
||||
|
||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
id model = self.modelsArray[indexPath.row];
|
||||
// 获取cell高度
|
||||
return [self.tableView cellHeightForIndexPath:indexPath model:model keyPath:@"model" cellClass:[DemoVC9Cell class] contentViewWidth:cellContentViewWith];
|
||||
}
|
||||
|
||||
|
||||
####升级版(适应于cell条数少于100的tableview):tableview 高度自适应设置只需要2步
|
||||
|
||||
1. >> 设置cell高度自适应:
|
||||
// cell布局设置好之后调用此方法就可以实现高度自适应(注意:如果用高度自适应则不要再以cell的底边为参照去布局其子view)
|
||||
[cell setupAutoHeightWithBottomView:_view4 bottomMargin:10];
|
||||
|
||||
2. >> 获取自动计算出的cell高度
|
||||
|
||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
// 获取cell高度
|
||||
return [self cellHeightForIndexPath:indexPath cellContentViewWidth:[UIScreen mainScreen].bounds.size.width];
|
||||
}
|
||||
|
||||
|
||||
## 普通view的自动布局:
|
||||
|
||||
#### 用法示例
|
||||
/* 用法一 */
|
||||
_view.sd_layout
|
||||
.leftSpaceToView(self.view, 10)
|
||||
.topSpaceToView(self.view, 80)
|
||||
.heightIs(130)
|
||||
.widthRatioToView(self.view, 0.4);
|
||||
|
||||
/* 用法二 (一行代码搞定,其实用法一也是一行代码) */
|
||||
_view.sd_layout.leftSpaceToView(self.view, 10).topSpaceToView(self.view,80).heightIs(130).widthRatioToView(self.view, 0.4);
|
||||
|
||||
|
||||
>> UILabel文字自适应:
|
||||
// autoHeightRatio() 传0则根据文字自动计算高度(传大于0的值则根据此数值设置高度和宽度的比值)
|
||||
_label.sd_layout.autoHeightRatio(0);
|
||||
|
||||
*******************************************************************************
|
||||
|
||||
注意:先把需要自动布局的view加入父view然后在进行自动布局,例:
|
||||
|
||||
UIView *view0 = [UIView new];
|
||||
UIView *view1 = [UIView new];
|
||||
[self.view addSubview:view0];
|
||||
[self.view addSubview:view1];
|
||||
|
||||
view0.sd_layout
|
||||
.leftSpaceToView(self.view, 10)
|
||||
.topSpaceToView(self.view, 80)
|
||||
.heightIs(100)
|
||||
.widthRatioToView(self.view, 0.4);
|
||||
|
||||
view1.sd_layout
|
||||
.leftSpaceToView(view0, 10)
|
||||
.topEqualToView(view0)
|
||||
.heightRatioToView(view0, 1)
|
||||
.rightSpaceToView(self.view, 10);
|
||||
*******************************************************************************
|
||||
|
||||
#### 自动布局用法简析
|
||||
|
||||

|
||||
|
||||
|
||||
1.1 > leftSpaceToView(self.view, 10)
|
||||
|
||||
方法名中带有“SpaceToView”的方法表示到某个参照view的间距,需要传递2个参数:(UIView)参照view 和 (CGFloat)间距数值
|
||||
|
||||
1.2 > widthRatioToView(self.view, 1)
|
||||
|
||||
方法名中带有“RatioToView”的方法表示view的宽度或者高度等属性相对于参照view的对应属性值的比例,需要传递2个参数:(UIView)参照view 和 (CGFloat)倍数
|
||||
|
||||
1.3 > topEqualToView(view)
|
||||
|
||||
方法名中带有“EqualToView”的方法表示view的某一属性等于参照view的对应的属性值,需要传递1个参数:(UIView)参照view
|
||||
|
||||
1.4 > widthIs(100)
|
||||
|
||||
方法名中带有“Is”的方法表示view的某一属性值等于参数数值,需要传递1个参数:(CGFloat)数值
|
||||
|
||||
# PS
|
||||
|
||||
// 如果需要用“断言”调试程序请打开此宏(位于UIView+SDAutoLayout.h)
|
||||
|
||||
//#define SDDebugWithAssert
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||

|
||||
24
Pods/SDAutoLayout/SDAutoLayoutDemo/SDAutoLayout/SDAutoLayout.h
generated
Executable file
24
Pods/SDAutoLayout/SDAutoLayoutDemo/SDAutoLayout/SDAutoLayout.h
generated
Executable file
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// SDAutoLayout.h
|
||||
// SDAutoLayoutDemo
|
||||
//
|
||||
// Created by gsd on 16/6/27.
|
||||
// Copyright © 2016年 gsd. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
/*
|
||||
|
||||
SDAutoLayout
|
||||
版本:2.1.7
|
||||
发布:2016.08.12
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SDAutoLayout_h
|
||||
#define SDAutoLayout_h
|
||||
|
||||
#import "UIView+SDAutoLayout.h"
|
||||
#import "UITableView+SDAutoTableViewCellHeight.h"
|
||||
|
||||
#endif
|
||||
169
Pods/SDAutoLayout/SDAutoLayoutDemo/SDAutoLayout/UITableView+SDAutoTableViewCellHeight.h
generated
Executable file
169
Pods/SDAutoLayout/SDAutoLayoutDemo/SDAutoLayout/UITableView+SDAutoTableViewCellHeight.h
generated
Executable file
@@ -0,0 +1,169 @@
|
||||
//
|
||||
// UITableView+SDAutoTableViewCellHeight.h
|
||||
// SDAutoLayout 测试 Demo
|
||||
//
|
||||
// Created by aier on 15/11/1.
|
||||
// Copyright © 2015年 gsd. All rights reserved.
|
||||
//
|
||||
|
||||
/*
|
||||
|
||||
*********************************************************************************
|
||||
* *
|
||||
* 在您使用此自动布局库的过程中如果出现bug请及时以以下任意一种方式联系我们,我们会及时修复bug并 *
|
||||
* 帮您解决问题。 *
|
||||
* QQ : 2689718696(gsdios) *
|
||||
* Email : gsdios@126.com *
|
||||
* GitHub: https://github.com/gsdios *
|
||||
* 新浪微博:GSD_iOS *
|
||||
* *
|
||||
*********************************************************************************
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
PS:cell高度自适应前提>>应该调用cell的“- (void)setupAutoHeightWithBottomView:(UIView *)bottomView bottomMargin:(CGFloat)bottomMargin”方法进行cell的自动高度设置
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "UIView+SDAutoLayout.h"
|
||||
|
||||
@class SDCellAutoHeightManager;
|
||||
|
||||
typedef void (^AutoCellHeightDataSettingBlock)(UITableViewCell *cell);
|
||||
|
||||
#define kSDModelCellTag 199206
|
||||
|
||||
|
||||
|
||||
#pragma mark - UITableView 方法,返回自动计算出的cell高度
|
||||
|
||||
@interface UITableView (SDAutoTableViewCellHeight)
|
||||
|
||||
@property (nonatomic, strong) SDCellAutoHeightManager *cellAutoHeightManager;
|
||||
|
||||
|
||||
/**
|
||||
* 返回计算出的cell高度(普通简化版方法,同样只需一步设置即可完成)(用法:单cell详见demo5,多cell详见demo7)
|
||||
* model : cell的数据模型实例
|
||||
* keyPath : cell的数据模型属性的属性名字符串(即kvc原理中的key)
|
||||
* cellClass : 当前的indexPath对应的cell的class
|
||||
* contentViewWidth : cell的contentView的宽度
|
||||
*/
|
||||
- (CGFloat)cellHeightForIndexPath:(NSIndexPath *)indexPath model:(id)model keyPath:(NSString *)keyPath cellClass:(Class)cellClass contentViewWidth:(CGFloat)contentViewWidth;
|
||||
|
||||
/**
|
||||
* 返回计算出的cell高度(普通简化版方法,同样只需一步设置即可完成)(用法:见DemoVC14)
|
||||
* cellClass : 当前的indexPath对应的cell的class
|
||||
* contentViewWidth : cell的contentView的宽度
|
||||
* cellDataSetting : 设置cell数据的block
|
||||
*/
|
||||
- (CGFloat)cellHeightForIndexPath:(NSIndexPath *)indexPath cellClass:(Class)cellClass cellContentViewWidth:(CGFloat)width cellDataSetting:(AutoCellHeightDataSettingBlock)cellDataSetting;
|
||||
|
||||
/** 刷新tableView但不清空之前已经计算好的高度缓存,用于直接将新数据拼接在旧数据之后的tableView刷新 */
|
||||
- (void)reloadDataWithExistedHeightCache;
|
||||
|
||||
/** 刷新tableView同时调整已经计算好的高度缓存,用于直接将新数据插在旧数据前面的tableView的刷新 */
|
||||
- (void)reloadDataWithInsertingDataAtTheBeginingOfSection:(NSInteger)section newDataCount:(NSInteger)count;
|
||||
|
||||
/**
|
||||
* 刷新tableView同时调整已经计算好的高度缓存,用于直接将新数据插在旧数据前面的tableView的刷新(用于刷新多个section)
|
||||
* sectionNumsArray : 要刷新的所有section序号组成的数组, 例@[@(0), @(1)]
|
||||
* dataCountsArray : 每个section的数据条数组成的数组, 例@[@(20), @(10)]
|
||||
*/
|
||||
- (void)reloadDataWithInsertingDataAtTheBeginingOfSections:(NSArray *)sectionNumsArray newDataCounts:(NSArray *)dataCountsArray;
|
||||
|
||||
/** 返回所有cell的高度总和 */
|
||||
- (CGFloat)cellsTotalHeight;
|
||||
|
||||
@property (nonatomic, copy) AutoCellHeightDataSettingBlock cellDataSetting;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma mark - UITableViewController 方法,返回自动计算出的cell高度
|
||||
|
||||
@interface UITableViewController (SDTableViewControllerAutoCellHeight)
|
||||
|
||||
/** (UITableViewController方法)升级版!一行代码(一步设置)搞定tableview的cell高度自适应,同时适用于单cell和多cell,性能比普通版稍微差一些,不建议在数据量大的tableview中使用 */
|
||||
- (CGFloat)cellHeightForIndexPath:(NSIndexPath *)indexPath cellContentViewWidth:(CGFloat)width;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
#pragma mark - NSObject 方法,返回自动计算出的cell高度
|
||||
|
||||
@interface NSObject (SDAnyObjectAutoCellHeight)
|
||||
|
||||
/** (NSObject方法)升级版!一行代码(一步设置)搞定tableview的cell高度自适应,同时适用于单cell和多cell,性能比普通版稍微差一些,不建议在数据量大的tableview中使用 */
|
||||
- (CGFloat)cellHeightForIndexPath:(NSIndexPath *)indexPath cellContentViewWidth:(CGFloat)width tableView:(UITableView *)tableView;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ------------------------------- 以下为库内部使用无须了解 --------------------
|
||||
|
||||
@interface SDCellAutoHeightManager : NSObject
|
||||
|
||||
@property (nonatomic, assign) BOOL shouldKeepHeightCacheWhenReloadingData;
|
||||
|
||||
@property (nonatomic, assign) CGFloat contentViewWidth;
|
||||
|
||||
@property (nonatomic, assign) Class cellClass;
|
||||
|
||||
@property (nonatomic, assign) CGFloat cellHeight;
|
||||
|
||||
@property (nonatomic, strong) UITableViewCell *modelCell;
|
||||
|
||||
@property (nonatomic, strong) NSMutableDictionary *subviewFrameCacheDict;
|
||||
|
||||
@property (nonatomic, strong, readonly) NSDictionary *heightCacheDict;
|
||||
|
||||
@property (nonatomic, copy) AutoCellHeightDataSettingBlock cellDataSetting;
|
||||
|
||||
- (void)clearHeightCache;
|
||||
|
||||
- (void)clearHeightCacheOfIndexPaths:(NSArray *)indexPaths;
|
||||
|
||||
- (void)deleteThenResetHeightCache:(NSIndexPath *)indexPathToDelete;
|
||||
|
||||
- (void)insertNewDataAtTheBeginingOfSection:(NSInteger)section newDataCount:(NSInteger)count;
|
||||
|
||||
- (void)insertNewDataAtIndexPaths:(NSArray *)indexPaths;
|
||||
|
||||
- (NSNumber *)heightCacheForIndexPath:(NSIndexPath *)indexPath;
|
||||
|
||||
- (CGFloat)cellHeightForIndexPath:(NSIndexPath *)indexPath model:(id)model keyPath:(NSString *)keyPath;
|
||||
|
||||
- (CGFloat)cellHeightForIndexPath:(NSIndexPath *)indexPath model:(id)model keyPath:(NSString *)keyPath cellClass:(Class)cellClass;
|
||||
|
||||
|
||||
- (NSMutableArray *)subviewFrameCachesWithIndexPath:(NSIndexPath *)indexPath;;
|
||||
- (void)setSubviewFrameCache:(CGRect)rect WithIndexPath:(NSIndexPath *)indexPath;
|
||||
|
||||
- (instancetype)initWithCellClass:(Class)cellClass tableView:(UITableView *)tableView;
|
||||
+ (instancetype)managerWithCellClass:(Class)cellClass tableView:(UITableView *)tableView;
|
||||
@end
|
||||
|
||||
537
Pods/SDAutoLayout/SDAutoLayoutDemo/SDAutoLayout/UITableView+SDAutoTableViewCellHeight.m
generated
Executable file
537
Pods/SDAutoLayout/SDAutoLayoutDemo/SDAutoLayout/UITableView+SDAutoTableViewCellHeight.m
generated
Executable file
@@ -0,0 +1,537 @@
|
||||
//
|
||||
// UITableView+SDAutoTableViewCellHeight.m
|
||||
// SDAutoLayout 测试 Demo
|
||||
//
|
||||
// Created by aier on 15/11/1.
|
||||
// Copyright © 2015年 gsd. All rights reserved.
|
||||
//
|
||||
|
||||
/*
|
||||
|
||||
*********************************************************************************
|
||||
* *
|
||||
* 在您使用此自动布局库的过程中如果出现bug请及时以以下任意一种方式联系我们,我们会及时修复bug并 *
|
||||
* 帮您解决问题。 *
|
||||
* QQ : 2689718696(gsdios) *
|
||||
* Email : gsdios@126.com *
|
||||
* GitHub: https://github.com/gsdios *
|
||||
* 新浪微博:GSD_iOS *
|
||||
* *
|
||||
*********************************************************************************
|
||||
|
||||
*/
|
||||
|
||||
#import "UITableView+SDAutoTableViewCellHeight.h"
|
||||
#import <objc/runtime.h>
|
||||
|
||||
@interface SDCellAutoHeightManager ()
|
||||
|
||||
@property (nonatomic, weak) UITableView *modelTableview;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDCellAutoHeightManager
|
||||
{
|
||||
NSMutableDictionary *_cacheDictionary;
|
||||
NSMutableDictionary *_modelCellsDict;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if (self = [super init]) {
|
||||
[self setup];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCellClass:(Class)cellClass tableView:(UITableView *)tableView
|
||||
{
|
||||
if (self = [super init]) {
|
||||
[self setup];
|
||||
self.modelTableview = tableView;
|
||||
[self registerCellWithCellClass:cellClass];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCellClasses:(NSArray *)cellClassArray tableView:(UITableView *)tableView
|
||||
{
|
||||
if (self = [super init]) {
|
||||
[self setup];
|
||||
self.modelTableview = tableView;
|
||||
[cellClassArray enumerateObjectsUsingBlock:^(Class obj, NSUInteger idx, BOOL *stop) {
|
||||
[self registerCellWithCellClass:obj];
|
||||
}];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setup
|
||||
{
|
||||
_cacheDictionary = [NSMutableDictionary new];
|
||||
_modelCellsDict = [NSMutableDictionary new];
|
||||
}
|
||||
|
||||
- (void)registerCellWithCellClass:(Class)cellClass
|
||||
{
|
||||
[_modelTableview registerClass:cellClass forCellReuseIdentifier:NSStringFromClass(cellClass)];
|
||||
self.modelCell = [_modelTableview dequeueReusableCellWithIdentifier:NSStringFromClass(cellClass)];
|
||||
|
||||
if (!self.modelCell.contentView.subviews.count) {
|
||||
NSString *path = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@.nib", NSStringFromClass(cellClass)] ofType:nil];
|
||||
if (path) {
|
||||
self.modelCell = nil;
|
||||
[_modelTableview registerNib:[UINib nibWithNibName:NSStringFromClass(cellClass) bundle:nil] forCellReuseIdentifier:NSStringFromClass(cellClass)];
|
||||
self.modelCell = [_modelTableview dequeueReusableCellWithIdentifier:NSStringFromClass(cellClass)];
|
||||
}
|
||||
}
|
||||
if (self.modelCell) {
|
||||
[_modelCellsDict setObject:self.modelCell forKey:NSStringFromClass(cellClass)];
|
||||
}
|
||||
}
|
||||
|
||||
+ (instancetype)managerWithCellClass:(Class)cellClass tableView:(UITableView *)tableView
|
||||
{
|
||||
SDCellAutoHeightManager *manager = [[self alloc] initWithCellClass:cellClass tableView:tableView];
|
||||
return manager;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)modelCell
|
||||
{
|
||||
if (_modelCell.contentView.tag != kSDModelCellTag) {
|
||||
_modelCell.contentView.tag = kSDModelCellTag;
|
||||
}
|
||||
return _modelCell;
|
||||
}
|
||||
|
||||
- (NSDictionary *)heightCacheDict
|
||||
{
|
||||
return _cacheDictionary;
|
||||
}
|
||||
|
||||
- (void)clearHeightCache
|
||||
{
|
||||
[_cacheDictionary removeAllObjects];
|
||||
[_subviewFrameCacheDict removeAllObjects];
|
||||
}
|
||||
|
||||
- (NSString *)cacheKeyForIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
return [NSString stringWithFormat:@"%ld-%ld", (long)indexPath.section, (long)indexPath.row];
|
||||
}
|
||||
|
||||
- (void)clearHeightCacheOfIndexPaths:(NSArray *)indexPaths
|
||||
{
|
||||
[indexPaths enumerateObjectsUsingBlock:^(NSIndexPath *indexPath, NSUInteger idx, BOOL *stop) {
|
||||
NSString *cacheKey = [self cacheKeyForIndexPath:indexPath];
|
||||
[_cacheDictionary removeObjectForKey:cacheKey];
|
||||
[_subviewFrameCacheDict removeObjectForKey:cacheKey];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)deleteThenResetHeightCache:(NSIndexPath *)indexPathToDelete
|
||||
{
|
||||
|
||||
NSString *cacheKey = [self cacheKeyForIndexPath:indexPathToDelete];
|
||||
[_cacheDictionary removeObjectForKey:cacheKey];
|
||||
[_subviewFrameCacheDict removeObjectForKey:cacheKey];
|
||||
|
||||
long sectionOfToDeleteItem = indexPathToDelete.section;
|
||||
long rowOfToDeleteItem = indexPathToDelete.row;
|
||||
NSMutableDictionary *tempHeightCacheDict = [NSMutableDictionary new];
|
||||
NSMutableDictionary *tempFrameCacheDict = [NSMutableDictionary new];
|
||||
for (NSString *key in _cacheDictionary.allKeys) {
|
||||
NSArray *res = [key componentsSeparatedByString:@"-"];
|
||||
long section = [res.firstObject integerValue];
|
||||
long row = [res.lastObject integerValue];
|
||||
if (section == sectionOfToDeleteItem && row > rowOfToDeleteItem) {
|
||||
NSNumber *heightCache = _cacheDictionary[key];
|
||||
NSArray *frameCache = _subviewFrameCacheDict[key];
|
||||
NSString *newKey = [NSString stringWithFormat:@"%ld-%ld", section, (row - 1)];
|
||||
[tempHeightCacheDict setValue:heightCache forKey:newKey];
|
||||
[tempFrameCacheDict setValue:frameCache forKey:newKey];
|
||||
[_cacheDictionary removeObjectForKey:key];
|
||||
[_subviewFrameCacheDict removeObjectForKey:key];
|
||||
}
|
||||
}
|
||||
[_cacheDictionary addEntriesFromDictionary:tempHeightCacheDict];
|
||||
[_subviewFrameCacheDict addEntriesFromDictionary:tempFrameCacheDict];
|
||||
|
||||
}
|
||||
|
||||
- (void)insertNewDataAtTheBeginingOfSection:(NSInteger)section newDataCount:(NSInteger)count
|
||||
{
|
||||
NSMutableDictionary *tempHeightCacheDict = [NSMutableDictionary new];
|
||||
NSMutableDictionary *tempFrameCacheDict = [NSMutableDictionary new];
|
||||
for (NSString *key in _cacheDictionary.allKeys) {
|
||||
NSArray *res = [key componentsSeparatedByString:@"-"];
|
||||
long originalSection = [res.firstObject integerValue];
|
||||
long row = [res.lastObject integerValue];
|
||||
if (originalSection == section) {
|
||||
NSNumber *heightCache = _cacheDictionary[key];
|
||||
NSArray *frameCache = _subviewFrameCacheDict[key];
|
||||
NSString *newKey = [NSString stringWithFormat:@"%ld-%ld", originalSection, (row + count)];
|
||||
[tempHeightCacheDict setValue:heightCache forKey:newKey];
|
||||
[tempFrameCacheDict setValue:frameCache forKey:newKey];
|
||||
[_cacheDictionary removeObjectForKey:key];
|
||||
[_subviewFrameCacheDict removeObjectForKey:key];
|
||||
}
|
||||
}
|
||||
[_cacheDictionary addEntriesFromDictionary:tempHeightCacheDict];
|
||||
[_subviewFrameCacheDict addEntriesFromDictionary:tempFrameCacheDict];
|
||||
}
|
||||
|
||||
- (void)insertNewDataAtIndexPaths:(NSArray *)indexPaths
|
||||
{
|
||||
NSMutableDictionary *sectionsdict = [NSMutableDictionary new];
|
||||
for (NSIndexPath *indexPath in indexPaths) {
|
||||
NSString *sectionkey = [@(indexPath.section) stringValue];
|
||||
if (![sectionsdict objectForKey:sectionkey]) {
|
||||
[sectionsdict setValue:[NSMutableArray new] forKey:sectionkey];
|
||||
}
|
||||
NSMutableArray *arr = sectionsdict[sectionkey];
|
||||
[arr addObject:indexPath];
|
||||
}
|
||||
for (NSString *sectionkey in sectionsdict.allKeys) {
|
||||
NSMutableArray *tempHeightCaches = [NSMutableArray new];
|
||||
NSMutableArray *tempFrameCaches = [NSMutableArray new];
|
||||
NSInteger section = [sectionkey integerValue];
|
||||
NSInteger rowCount = [self.modelTableview numberOfRowsInSection:section];
|
||||
if (rowCount <= 0) {
|
||||
continue;
|
||||
} else {
|
||||
for (int i = 0; i < rowCount; i++) {
|
||||
[tempHeightCaches addObject:[NSNull null]];
|
||||
[tempFrameCaches addObject:[NSNull null]];
|
||||
}
|
||||
}
|
||||
|
||||
for (NSString *key in _cacheDictionary.allKeys) {
|
||||
NSArray *res = [key componentsSeparatedByString:@"-"];
|
||||
long originalSection = [res.firstObject integerValue];
|
||||
long row = [res.lastObject integerValue];
|
||||
if (originalSection == section) {
|
||||
NSNumber *heightCache = _cacheDictionary[key];
|
||||
NSArray *frameCache = _subviewFrameCacheDict[key];
|
||||
[tempHeightCaches setObject:heightCache atIndexedSubscript:row];
|
||||
[tempFrameCaches setObject:frameCache atIndexedSubscript:row];
|
||||
[_cacheDictionary removeObjectForKey:key];
|
||||
[_subviewFrameCacheDict removeObjectForKey:key];
|
||||
}
|
||||
}
|
||||
NSMutableArray *objsToInsert = [NSMutableArray new];
|
||||
NSMutableIndexSet *indexSet = [NSMutableIndexSet new];
|
||||
NSArray *indexPaths = sectionsdict[sectionkey];
|
||||
[indexPaths enumerateObjectsUsingBlock:^(NSIndexPath *obj, NSUInteger idx, BOOL *stop) {
|
||||
[objsToInsert addObject:[NSNull null]];
|
||||
[indexSet addIndex:obj.row];
|
||||
}];
|
||||
[tempHeightCaches insertObjects:objsToInsert atIndexes:indexSet];
|
||||
[tempFrameCaches insertObjects:objsToInsert atIndexes:indexSet];
|
||||
[tempHeightCaches enumerateObjectsUsingBlock:^(NSNumber *heightCache, NSUInteger idx, BOOL *stop) {
|
||||
if (![heightCache isKindOfClass:[NSNull class]]) {
|
||||
NSString *key = [NSString stringWithFormat:@"%zd-%zd", section, idx];
|
||||
[_cacheDictionary setValue:heightCache forKey:key];
|
||||
[_subviewFrameCacheDict setValue:[tempFrameCaches objectAtIndex:idx] forKey:key];
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSNumber *)heightCacheForIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
/*
|
||||
如果程序卡在了这里很可能是由于你用了“dequeueReusableCellWithIdentifier:forIndexPath:”方法来重用cell,换成““dequeueReusableCellWithIdentifier:”(不带IndexPath)方法即可解决
|
||||
*/
|
||||
NSString *cacheKey = [self cacheKeyForIndexPath:indexPath];
|
||||
return (NSNumber *)[_cacheDictionary objectForKey:cacheKey];
|
||||
}
|
||||
|
||||
- (CGFloat)cellHeightForIndexPath:(NSIndexPath *)indexPath model:(id)model keyPath:(NSString *)keyPath
|
||||
{
|
||||
|
||||
NSNumber *cacheHeight = [self heightCacheForIndexPath:indexPath];
|
||||
if (cacheHeight) {
|
||||
return [cacheHeight floatValue];
|
||||
} else {
|
||||
if (!self.modelCell) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (self.modelTableview && self.modelTableview != self.modelCell.sd_tableView) {
|
||||
self.modelCell.sd_tableView = self.modelTableview;
|
||||
}
|
||||
self.modelCell.sd_indexPath = indexPath;
|
||||
|
||||
if (model && keyPath) {
|
||||
[self.modelCell setValue:model forKey:keyPath];
|
||||
} else if (self.cellDataSetting) {
|
||||
self.cellDataSetting(self.modelCell);
|
||||
}
|
||||
|
||||
|
||||
#ifdef SDDebugWithAssert
|
||||
/*
|
||||
如果程序卡在了这里说明你的cell还没有调用“setupAutoHeightWithBottomView:(UIView *)bottomView bottomMargin:(CGFloat)bottomMargin”方法或者你传递的bottomView为nil,请检查并修改。例:
|
||||
|
||||
//注意:bottomView不能为nil
|
||||
[cell setupAutoHeightWithBottomView:bottomView bottomMargin:bottomMargin];
|
||||
*/
|
||||
NSAssert(self.modelCell.sd_bottomViewsArray.count, @">>>>>> 你的cell还没有调用“setupAutoHeightWithBottomView:(UIView *)bottomView bottomMargin:(CGFloat)bottomMargin”方法或者你传递的bottomView为nil,请检查并修改");
|
||||
|
||||
#endif
|
||||
|
||||
[self.modelCell.contentView layoutSubviews];
|
||||
NSString *cacheKey = [self cacheKeyForIndexPath:indexPath];
|
||||
[_cacheDictionary setObject:@(self.modelCell.autoHeight) forKey:cacheKey];
|
||||
|
||||
|
||||
if (self.modelCell.sd_indexPath && self.modelCell.sd_tableView) {
|
||||
if (self.modelCell.contentView.shouldReadjustFrameBeforeStoreCache) {
|
||||
self.modelCell.contentView.height_sd = self.modelCell.autoHeight;
|
||||
[self.modelCell.contentView layoutSubviews];
|
||||
}
|
||||
[self.modelCell.contentView.autoLayoutModelsArray enumerateObjectsUsingBlock:^(SDAutoLayoutModel *model, NSUInteger idx, BOOL *stop) {
|
||||
[self.modelTableview.cellAutoHeightManager setSubviewFrameCache:model.needsAutoResizeView.frame WithIndexPath:self.modelCell.sd_indexPath];
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
return self.modelCell.autoHeight;
|
||||
}
|
||||
}
|
||||
|
||||
- (CGFloat)cellHeightForIndexPath:(NSIndexPath *)indexPath model:(id)model keyPath:(NSString *)keyPath cellClass:(Class)cellClass
|
||||
{
|
||||
if (![self.modelCell isKindOfClass:cellClass]) {
|
||||
self.modelCell = nil;
|
||||
self.modelCell = [_modelCellsDict objectForKey:NSStringFromClass(cellClass)];
|
||||
if (!self.modelCell) {
|
||||
[self registerCellWithCellClass:cellClass];
|
||||
}
|
||||
_modelCell.contentView.tag = kSDModelCellTag;
|
||||
}
|
||||
if (self.modelCell.contentView.width_sd != self.contentViewWidth) {
|
||||
_modelCell.contentView.width_sd = self.contentViewWidth;
|
||||
}
|
||||
return [self cellHeightForIndexPath:indexPath model:model keyPath:keyPath];
|
||||
}
|
||||
|
||||
- (void)setContentViewWidth:(CGFloat)contentViewWidth
|
||||
{
|
||||
if (_contentViewWidth == contentViewWidth) return;
|
||||
|
||||
CGFloat lastContentViewWidth = _contentViewWidth;
|
||||
_contentViewWidth = contentViewWidth;
|
||||
|
||||
self.modelCell.contentView.width_sd = self.contentViewWidth;
|
||||
|
||||
if (lastContentViewWidth > 0) {
|
||||
[_subviewFrameCacheDict removeAllObjects];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self clearHeightCache];
|
||||
[self.modelTableview reloadData];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)setSubviewFrameCache:(CGRect)rect WithIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
if (!self.subviewFrameCacheDict) {
|
||||
self.subviewFrameCacheDict = [NSMutableDictionary new];
|
||||
}
|
||||
NSString *cacheKey = [self cacheKeyForIndexPath:indexPath];
|
||||
NSMutableArray *caches = [self.subviewFrameCacheDict objectForKey:cacheKey];
|
||||
if (!caches) {
|
||||
caches = [NSMutableArray new];
|
||||
[self.subviewFrameCacheDict setValue:caches forKey:cacheKey];
|
||||
}
|
||||
[caches addObject:[NSValue valueWithCGRect:rect]];
|
||||
}
|
||||
|
||||
- (NSMutableArray *)subviewFrameCachesWithIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
NSString *cacheKey = [self cacheKeyForIndexPath:indexPath];
|
||||
return [self.subviewFrameCacheDict valueForKey:cacheKey];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation UITableView (SDAutoTableViewCellHeight)
|
||||
|
||||
+ (void)load {
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
|
||||
NSArray *selStringsArray = @[@"reloadData", @"reloadRowsAtIndexPaths:withRowAnimation:", @"deleteRowsAtIndexPaths:withRowAnimation:", @"insertRowsAtIndexPaths:withRowAnimation:"];
|
||||
|
||||
[selStringsArray enumerateObjectsUsingBlock:^(NSString *selString, NSUInteger idx, BOOL *stop) {
|
||||
NSString *mySelString = [@"sd_" stringByAppendingString:selString];
|
||||
|
||||
Method originalMethod = class_getInstanceMethod(self, NSSelectorFromString(selString));
|
||||
Method myMethod = class_getInstanceMethod(self, NSSelectorFromString(mySelString));
|
||||
method_exchangeImplementations(originalMethod, myMethod);
|
||||
}];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)sd_reloadData
|
||||
{
|
||||
if (!self.cellAutoHeightManager.shouldKeepHeightCacheWhenReloadingData) {
|
||||
[self.cellAutoHeightManager clearHeightCache];
|
||||
}
|
||||
[self sd_reloadData];
|
||||
self.cellAutoHeightManager.shouldKeepHeightCacheWhenReloadingData = NO;
|
||||
}
|
||||
|
||||
- (void)sd_reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
|
||||
{
|
||||
[self.cellAutoHeightManager clearHeightCacheOfIndexPaths:indexPaths];
|
||||
[self sd_reloadRowsAtIndexPaths:indexPaths withRowAnimation:animation];
|
||||
}
|
||||
|
||||
- (void)sd_deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
|
||||
{
|
||||
for (NSIndexPath *indexPath in indexPaths) {
|
||||
[self.cellAutoHeightManager deleteThenResetHeightCache:indexPath];
|
||||
}
|
||||
[self sd_deleteRowsAtIndexPaths:indexPaths withRowAnimation:animation];
|
||||
}
|
||||
|
||||
|
||||
- (void)sd_insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
|
||||
{
|
||||
[self.cellAutoHeightManager insertNewDataAtIndexPaths:indexPaths];
|
||||
[self sd_insertRowsAtIndexPaths:indexPaths withRowAnimation:animation];
|
||||
}
|
||||
|
||||
/*
|
||||
* 下一步即将实现的功能
|
||||
|
||||
- (void)sd_moveRowAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath
|
||||
{
|
||||
[self sd_moveRowAtIndexPath:indexPath toIndexPath:newIndexPath];
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
- (CGFloat)cellHeightForIndexPath:(NSIndexPath *)indexPath model:(id)model keyPath:(NSString *)keyPath cellClass:(Class)cellClass contentViewWidth:(CGFloat)contentViewWidth
|
||||
{
|
||||
self.cellAutoHeightManager.modelTableview = self;
|
||||
|
||||
self.cellAutoHeightManager.contentViewWidth = contentViewWidth;
|
||||
|
||||
return [self.cellAutoHeightManager cellHeightForIndexPath:indexPath model:model keyPath:keyPath cellClass:cellClass];
|
||||
}
|
||||
|
||||
- (CGFloat)cellHeightForIndexPath:(NSIndexPath *)indexPath cellClass:(__unsafe_unretained Class)cellClass cellContentViewWidth:(CGFloat)width cellDataSetting:(AutoCellHeightDataSettingBlock)cellDataSetting
|
||||
{
|
||||
|
||||
self.cellDataSetting = cellDataSetting;
|
||||
|
||||
return [self cellHeightForIndexPath:indexPath model:nil keyPath:nil cellClass:cellClass contentViewWidth:width];
|
||||
}
|
||||
|
||||
- (void)reloadDataWithExistedHeightCache
|
||||
{
|
||||
self.cellAutoHeightManager.shouldKeepHeightCacheWhenReloadingData = YES;
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (void)reloadDataWithInsertingDataAtTheBeginingOfSection:(NSInteger)section newDataCount:(NSInteger)count
|
||||
{
|
||||
self.cellAutoHeightManager.shouldKeepHeightCacheWhenReloadingData = YES;
|
||||
[self.cellAutoHeightManager insertNewDataAtTheBeginingOfSection:section newDataCount:count];
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (void)reloadDataWithInsertingDataAtTheBeginingOfSections:(NSArray *)sectionNumsArray newDataCounts:(NSArray *)dataCountsArray
|
||||
{
|
||||
self.cellAutoHeightManager.shouldKeepHeightCacheWhenReloadingData = YES;
|
||||
[sectionNumsArray enumerateObjectsUsingBlock:^(NSNumber *num, NSUInteger idx, BOOL *stop) {
|
||||
int section = [num intValue];
|
||||
int dataCountForSection = [dataCountsArray[idx] intValue];
|
||||
[self.cellAutoHeightManager insertNewDataAtTheBeginingOfSection:section newDataCount:dataCountForSection];
|
||||
}];
|
||||
[self reloadData];
|
||||
}
|
||||
|
||||
- (CGFloat)cellsTotalHeight
|
||||
{
|
||||
CGFloat h = 0;
|
||||
if (!self.cellAutoHeightManager.heightCacheDict.count) {
|
||||
[self reloadData];
|
||||
}
|
||||
NSArray *values = [self.cellAutoHeightManager.heightCacheDict allValues];
|
||||
for (NSNumber *number in values) {
|
||||
h += [number floatValue];
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
- (SDCellAutoHeightManager *)cellAutoHeightManager
|
||||
{
|
||||
|
||||
SDCellAutoHeightManager *cellAutoHeightManager = objc_getAssociatedObject(self, _cmd);
|
||||
|
||||
if (!cellAutoHeightManager) {
|
||||
|
||||
cellAutoHeightManager = [[SDCellAutoHeightManager alloc] init];
|
||||
|
||||
[self setCellAutoHeightManager:cellAutoHeightManager];
|
||||
}
|
||||
|
||||
return cellAutoHeightManager;
|
||||
}
|
||||
|
||||
- (void)setCellAutoHeightManager:(SDCellAutoHeightManager *)cellAutoHeightManager
|
||||
{
|
||||
objc_setAssociatedObject(self, @selector(cellAutoHeightManager), cellAutoHeightManager, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (void)setCellDataSetting:(AutoCellHeightDataSettingBlock)cellDataSetting
|
||||
{
|
||||
self.cellAutoHeightManager.cellDataSetting = cellDataSetting;
|
||||
}
|
||||
|
||||
- (AutoCellHeightDataSettingBlock)cellDataSetting
|
||||
{
|
||||
return self.cellAutoHeightManager.cellDataSetting;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation UITableViewController (SDTableViewControllerAutoCellHeight)
|
||||
|
||||
- (CGFloat)cellHeightForIndexPath:(NSIndexPath *)indexPath cellContentViewWidth:(CGFloat)width
|
||||
{
|
||||
return [self cellHeightForIndexPath:indexPath cellContentViewWidth:width tableView:self.tableView];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSObject (SDAnyObjectAutoCellHeight)
|
||||
|
||||
- (CGFloat)cellHeightForIndexPath:(NSIndexPath *)indexPath cellContentViewWidth:(CGFloat)width tableView:(UITableView *)tableView
|
||||
{
|
||||
tableView.cellAutoHeightManager.modelTableview = tableView;
|
||||
|
||||
if (tableView.cellAutoHeightManager.contentViewWidth != width) {
|
||||
tableView.cellAutoHeightManager.contentViewWidth = width;
|
||||
}
|
||||
if ([tableView.cellAutoHeightManager heightCacheForIndexPath:indexPath]) {
|
||||
return [[tableView.cellAutoHeightManager heightCacheForIndexPath:indexPath] floatValue];
|
||||
}
|
||||
UITableViewCell *cell = [tableView.dataSource tableView:tableView cellForRowAtIndexPath:indexPath];
|
||||
tableView.cellAutoHeightManager.modelCell = cell;
|
||||
if (cell.contentView.width_sd != width) {
|
||||
cell.contentView.width_sd = width;
|
||||
}
|
||||
return [[tableView cellAutoHeightManager] cellHeightForIndexPath:indexPath model:nil keyPath:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
484
Pods/SDAutoLayout/SDAutoLayoutDemo/SDAutoLayout/UIView+SDAutoLayout.h
generated
Executable file
484
Pods/SDAutoLayout/SDAutoLayoutDemo/SDAutoLayout/UIView+SDAutoLayout.h
generated
Executable file
@@ -0,0 +1,484 @@
|
||||
//
|
||||
// UIView+SDAutoLayout.h
|
||||
//
|
||||
// Created by gsd on 15/10/6.
|
||||
// Copyright (c) 2015年 gsd. All rights reserved.
|
||||
//
|
||||
|
||||
/*
|
||||
*************************************************************************
|
||||
|
||||
--------- INTRODUCTION ---------
|
||||
|
||||
USAGE:
|
||||
|
||||
MODE 1. >>>>>>>>>>>>>>> You can use it in this way:
|
||||
|
||||
Demo.sd_layout
|
||||
.topSpaceToView(v1, 100)
|
||||
.bottomSpaceToView(v3, 100)
|
||||
.leftSpaceToView(v0, 150)
|
||||
.rightSpaceToView(v2, 150);
|
||||
|
||||
MODE 2. >>>>>>>>>>>>>>> You can also use it in this way that is more brevity:
|
||||
|
||||
Demo.sd_layout.topSpaceToView(v1, 100).bottomSpaceToView(v3, 100).leftSpaceToView(v0, 150).rightSpaceToView(v2, 150);
|
||||
|
||||
|
||||
*************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
|
||||
*********************************************************************************
|
||||
*
|
||||
* 在您使用此自动布局库的过程中如果出现bug请及时以以下任意一种方式联系我们,我们会及时修复bug并
|
||||
* 帮您解决问题。
|
||||
* QQ : 2689718696(gsdios)
|
||||
* Email : gsdios@126.com
|
||||
* GitHub: https://github.com/gsdios
|
||||
* 新浪微博:GSD_iOS
|
||||
*
|
||||
* 视频教程:http://www.letv.com/ptv/vplay/24038772.html
|
||||
* 用法示例:https://github.com/gsdios/SDAutoLayout/blob/master/README.md
|
||||
*
|
||||
*********************************************************************************
|
||||
|
||||
|
||||
SDAutoLayout
|
||||
版本:2.1.7
|
||||
发布:2016.08.12
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// 如果需要用“断言”调试程序请打开此宏
|
||||
|
||||
//#define SDDebugWithAssert
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@class SDAutoLayoutModel, SDUIViewCategoryManager;
|
||||
|
||||
typedef SDAutoLayoutModel *(^MarginToView)(id viewOrViewsArray, CGFloat value);
|
||||
typedef SDAutoLayoutModel *(^Margin)(CGFloat value);
|
||||
typedef SDAutoLayoutModel *(^MarginEqualToView)(UIView *toView);
|
||||
typedef SDAutoLayoutModel *(^WidthHeight)(CGFloat value);
|
||||
typedef SDAutoLayoutModel *(^WidthHeightEqualToView)(UIView *toView, CGFloat ratioValue);
|
||||
typedef SDAutoLayoutModel *(^AutoHeightWidth)(CGFloat ratioValue);
|
||||
typedef SDAutoLayoutModel *(^SameWidthHeight)();
|
||||
typedef SDAutoLayoutModel *(^Offset)(CGFloat value);
|
||||
typedef void (^SpaceToSuperView)(UIEdgeInsets insets);
|
||||
|
||||
@interface SDAutoLayoutModel : NSObject
|
||||
|
||||
/*
|
||||
*************************说明************************
|
||||
|
||||
方法名中带有“SpaceToView”的需要传递2个参数:(UIView)参照view 和 (CGFloat)间距数值
|
||||
方法名中带有“RatioToView”的需要传递2个参数:(UIView)参照view 和 (CGFloat)倍数
|
||||
方法名中带有“EqualToView”的需要传递1个参数:(UIView)参照view
|
||||
方法名中带有“Is”的需要传递1个参数:(CGFloat)数值
|
||||
|
||||
*****************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* 设置距离其它view的间距 */
|
||||
|
||||
/** 左边到其参照view之间的间距,参数为“(View 或者 view数组, CGFloat)” */
|
||||
@property (nonatomic, copy, readonly) MarginToView leftSpaceToView;
|
||||
/** 右边到其参照view之间的间距,参数为“(View, CGFloat)” */
|
||||
@property (nonatomic, copy, readonly) MarginToView rightSpaceToView;
|
||||
/** 顶部到其参照view之间的间距,参数为“(View 或者 view数组, CGFloat)” */
|
||||
@property (nonatomic, copy, readonly) MarginToView topSpaceToView;
|
||||
/** 底部到其参照view之间的间距,参数为“(View, CGFloat)” */
|
||||
@property (nonatomic, copy, readonly) MarginToView bottomSpaceToView;
|
||||
|
||||
|
||||
|
||||
/* 设置x、y、width、height、centerX、centerY 值 */
|
||||
|
||||
/** x值,参数为“(CGFloat)” */
|
||||
@property (nonatomic, copy, readonly) Margin xIs;
|
||||
/** y值,参数为“(CGFloat)” */
|
||||
@property (nonatomic, copy, readonly) Margin yIs;
|
||||
/** centerX值,参数为“(CGFloat)” */
|
||||
@property (nonatomic, copy, readonly) Margin centerXIs;
|
||||
/** centerY值,参数为“(CGFloat)” */
|
||||
@property (nonatomic, copy, readonly) Margin centerYIs;
|
||||
/** 宽度值,参数为“(CGFloat)” */
|
||||
@property (nonatomic, copy, readonly) WidthHeight widthIs;
|
||||
/** 高度值,参数为“(CGFloat)” */
|
||||
@property (nonatomic, copy, readonly) WidthHeight heightIs;
|
||||
|
||||
|
||||
|
||||
/* 设置最大宽度和高度、最小宽度和高度 */
|
||||
|
||||
/** 最大宽度值,参数为“(CGFloat)” */
|
||||
@property (nonatomic, copy, readonly) WidthHeight maxWidthIs;
|
||||
/** 最大高度值,参数为“(CGFloat)” */
|
||||
@property (nonatomic, copy, readonly) WidthHeight maxHeightIs;
|
||||
/** 最小宽度值,参数为“(CGFloat)” */
|
||||
@property (nonatomic, copy, readonly) WidthHeight minWidthIs;
|
||||
/** 最小高度值,参数为“(CGFloat)” */
|
||||
@property (nonatomic, copy, readonly) WidthHeight minHeightIs;
|
||||
|
||||
|
||||
|
||||
/* 设置和某个参照view的边距相同 */
|
||||
|
||||
/** 左间距与参照view相同,参数为“(View)” */
|
||||
@property (nonatomic, copy, readonly) MarginEqualToView leftEqualToView;
|
||||
/** 右间距与参照view相同,参数为“(View)” */
|
||||
@property (nonatomic, copy, readonly) MarginEqualToView rightEqualToView;
|
||||
/** 顶部间距与参照view相同,参数为“(View)” */
|
||||
@property (nonatomic, copy, readonly) MarginEqualToView topEqualToView;
|
||||
/** 底部间距与参照view相同,参数为“(View)” */
|
||||
@property (nonatomic, copy, readonly) MarginEqualToView bottomEqualToView;
|
||||
/** centerX与参照view相同,参数为“(View)” */
|
||||
@property (nonatomic, copy, readonly) MarginEqualToView centerXEqualToView;
|
||||
/** centerY与参照view相同,参数为“(View)” */
|
||||
@property (nonatomic, copy, readonly) MarginEqualToView centerYEqualToView;
|
||||
|
||||
|
||||
|
||||
/* 设置宽度或者高度等于参照view的多少倍 */
|
||||
|
||||
/** 宽度是参照view宽度的多少倍,参数为“(View, CGFloat)” */
|
||||
@property (nonatomic, copy, readonly) WidthHeightEqualToView widthRatioToView;
|
||||
/** 高度是参照view高度的多少倍,参数为“(View, CGFloat)” */
|
||||
@property (nonatomic, copy, readonly) WidthHeightEqualToView heightRatioToView;
|
||||
/** 设置一个view的宽度和它的高度相同,参数为空“()” */
|
||||
@property (nonatomic, copy, readonly) SameWidthHeight widthEqualToHeight;
|
||||
/** 设置一个view的高度和它的宽度相同,参数为空“()” */
|
||||
@property (nonatomic, copy, readonly) SameWidthHeight heightEqualToWidth;
|
||||
/** 自适应高度,传入高宽比值,label可以传0实现文字高度自适应 */
|
||||
@property (nonatomic, copy, readonly) AutoHeightWidth autoHeightRatio;
|
||||
|
||||
/** 自适应宽度,参数为宽高比值 */
|
||||
@property (nonatomic, copy, readonly) AutoHeightWidth autoWidthRatio;
|
||||
|
||||
|
||||
|
||||
/* 填充父view(快捷方法) */
|
||||
|
||||
/** 传入UIEdgeInsetsMake(top, left, bottom, right),可以快捷设置view到其父view上左下右的间距 */
|
||||
@property (nonatomic, copy, readonly) SpaceToSuperView spaceToSuperView;
|
||||
|
||||
/** 设置偏移量,参数为“(CGFloat value),目前只有带有equalToView的方法可以设置offset” */
|
||||
@property (nonatomic, copy, readonly) Offset offset;
|
||||
|
||||
@property (nonatomic, weak) UIView *needsAutoResizeView;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
#pragma mark - UIView 高度、宽度自适应相关方法
|
||||
|
||||
@interface UIView (SDAutoHeightWidth)
|
||||
|
||||
/** 设置Cell的高度自适应,也可用于设置普通view内容高度自适应 */
|
||||
- (void)setupAutoHeightWithBottomView:(UIView *)bottomView bottomMargin:(CGFloat)bottomMargin;
|
||||
|
||||
/** 用于设置普通view内容宽度自适应 */
|
||||
- (void)setupAutoWidthWithRightView:(UIView *)rightView rightMargin:(CGFloat)rightMargin;
|
||||
|
||||
/** 设置Cell的高度自适应,也可用于设置普通view内容自适应(应用于当你不确定哪个view在自动布局之后会排布在最下方最为bottomView的时候可以调用次方法将所有可能在最下方的view都传过去) */
|
||||
- (void)setupAutoHeightWithBottomViewsArray:(NSArray *)bottomViewsArray bottomMargin:(CGFloat)bottomMargin;
|
||||
|
||||
/** 更新布局(主动刷新布局,如果你需要设置完布局代码就获得view的frame请调用此方法) */
|
||||
- (void)updateLayout;
|
||||
|
||||
/** 更新cell内部的控件的布局(cell内部控件专属的更新约束方法,如果启用了cell frame缓存则会自动清除缓存再更新约束) */
|
||||
- (void)updateLayoutWithCellContentView:(UIView *)cellContentView;
|
||||
|
||||
/** 清空高度自适应设置 */
|
||||
- (void)clearAutoHeigtSettings;
|
||||
|
||||
/** 清空宽度自适应设置 */
|
||||
- (void)clearAutoWidthSettings;
|
||||
|
||||
@property (nonatomic) CGFloat autoHeight;
|
||||
|
||||
@property (nonatomic, readonly) SDUIViewCategoryManager *sd_categoryManager;
|
||||
|
||||
@property (nonatomic, readonly) NSMutableArray *sd_bottomViewsArray;
|
||||
@property (nonatomic) CGFloat sd_bottomViewBottomMargin;
|
||||
|
||||
@property (nonatomic) NSArray *sd_rightViewsArray;
|
||||
@property (nonatomic) CGFloat sd_rightViewRightMargin;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
#pragma mark - UIView 设置圆角半径、自动布局回调block等相关方法
|
||||
|
||||
@interface UIView (SDLayoutExtention)
|
||||
|
||||
/** 自动布局完成后的回调block,可以在这里获取到view的真实frame */
|
||||
@property (nonatomic) void (^didFinishAutoLayoutBlock)(CGRect frame);
|
||||
|
||||
/** 添加一组子view */
|
||||
- (void)sd_addSubviews:(NSArray *)subviews;
|
||||
|
||||
/* 设置圆角 */
|
||||
|
||||
/** 设置圆角半径值 */
|
||||
@property (nonatomic, strong) NSNumber *sd_cornerRadius;
|
||||
/** 设置圆角半径值为view宽度的多少倍 */
|
||||
@property (nonatomic, strong) NSNumber *sd_cornerRadiusFromWidthRatio;
|
||||
/** 设置圆角半径值为view高度的多少倍 */
|
||||
@property (nonatomic, strong) NSNumber *sd_cornerRadiusFromHeightRatio;
|
||||
|
||||
/** 设置等宽子view(子view需要在同一水平方向) */
|
||||
@property (nonatomic, strong) NSArray *sd_equalWidthSubviews;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
#pragma mark - UIView 九宫格浮动布局效果
|
||||
|
||||
@interface UIView (SDAutoFlowItems)
|
||||
|
||||
/**
|
||||
* 设置类似collectionView效果的固定间距自动宽度浮动子view
|
||||
* viewsArray : 需要浮动布局的所有视图
|
||||
* perRowItemsCount : 每行显示的视图个数
|
||||
* verticalMargin : 视图之间的垂直间距
|
||||
* horizontalMargin : 视图之间的水平间距
|
||||
* vInset : 上下缩进值
|
||||
* hInset : 左右缩进值
|
||||
*/
|
||||
- (void)setupAutoWidthFlowItems:(NSArray *)viewsArray withPerRowItemsCount:(NSInteger)perRowItemsCount verticalMargin:(CGFloat)verticalMargin horizontalMargin:(CGFloat)horizontalMagin verticalEdgeInset:(CGFloat)vInset horizontalEdgeInset:(CGFloat)hInset;
|
||||
|
||||
/** 清除固定间距自动宽度浮动子view设置 */
|
||||
- (void)clearAutoWidthFlowItemsSettings;
|
||||
|
||||
/**
|
||||
* 设置类似collectionView效果的固定宽带自动间距浮动子view
|
||||
* viewsArray : 需要浮动布局的所有视图
|
||||
* perRowItemsCount : 每行显示的视图个数
|
||||
* verticalMargin : 视图之间的垂直间距
|
||||
* vInset : 上下缩进值
|
||||
* hInset : 左右缩进值
|
||||
*/
|
||||
- (void)setupAutoMarginFlowItems:(NSArray *)viewsArray withPerRowItemsCount:(NSInteger)perRowItemsCount itemWidth:(CGFloat)itemWidth verticalMargin:(CGFloat)verticalMargin verticalEdgeInset:(CGFloat)vInset horizontalEdgeInset:(CGFloat)hInset;
|
||||
|
||||
/** 清除固定宽带自动间距浮动子view设置 */
|
||||
- (void)clearAutoMarginFlowItemsSettings;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
#pragma mark - UIView 设置约束、更新约束、清空约束、从父view移除并清空约束、开启cell的frame缓存等相关方法
|
||||
|
||||
@interface UIView (SDAutoLayout)
|
||||
|
||||
/** 开始自动布局 */
|
||||
- (SDAutoLayoutModel *)sd_layout;
|
||||
|
||||
/** 清空之前的自动布局设置,重新开始自动布局(重新生成布局约束并使其在父view的布局序列数组中位置保持不变) */
|
||||
- (SDAutoLayoutModel *)sd_resetLayout;
|
||||
|
||||
/** 清空之前的自动布局设置,重新开始自动布局(重新生成布局约束并添加到父view布局序列数组中的最后一个位置) */
|
||||
- (SDAutoLayoutModel *)sd_resetNewLayout;
|
||||
|
||||
/** 是否关闭自动布局 */
|
||||
@property (nonatomic, getter = sd_isClosingAutoLayout) BOOL sd_closeAutoLayout;
|
||||
|
||||
/** 从父view移除并清空约束 */
|
||||
- (void)removeFromSuperviewAndClearAutoLayoutSettings;
|
||||
|
||||
/** 清空之前的自动布局设置 */
|
||||
- (void)sd_clearAutoLayoutSettings;
|
||||
|
||||
/** 将自身frame清零(一般在cell内部控件重用前调用) */
|
||||
- (void)sd_clearViewFrameCache;
|
||||
|
||||
/** 将自己的需要自动布局的subviews的frame(或者frame缓存)清零 */
|
||||
- (void)sd_clearSubviewsAutoLayoutFrameCaches;
|
||||
|
||||
/** 设置固定宽度保证宽度不在自动布局过程再做中调整 */
|
||||
@property (nonatomic, strong) NSNumber *fixedWidth;
|
||||
|
||||
/** 设置固定高度保证高度不在自动布局过程中再做调整 */
|
||||
@property (nonatomic, strong) NSNumber *fixedHeight;
|
||||
|
||||
/** 启用cell frame缓存(可以提高cell滚动的流畅度, 目前为cell专用方法,后期会扩展到其他view) */
|
||||
- (void)useCellFrameCacheWithIndexPath:(NSIndexPath *)indexPath tableView:(UITableView *)tableview;
|
||||
|
||||
/** 所属tableview(目前为cell专用属性,后期会扩展到其他view) */
|
||||
@property (nonatomic) UITableView *sd_tableView;
|
||||
|
||||
/** cell的indexPath(目前为cell专用属性,后期会扩展到cell的其他子view) */
|
||||
@property (nonatomic) NSIndexPath *sd_indexPath;
|
||||
|
||||
- (NSMutableArray *)autoLayoutModelsArray;
|
||||
- (void)addAutoLayoutModel:(SDAutoLayoutModel *)model;
|
||||
@property (nonatomic) SDAutoLayoutModel *ownLayoutModel;
|
||||
@property (nonatomic, strong) NSNumber *sd_maxWidth;
|
||||
@property (nonatomic, strong) NSNumber *autoHeightRatioValue;
|
||||
@property (nonatomic, strong) NSNumber *autoWidthRatioValue;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
#pragma mark - UIScrollView 内容竖向自适应、内容横向自适应方法
|
||||
|
||||
@interface UIScrollView (SDAutoContentSize)
|
||||
|
||||
/** 设置scrollview内容竖向自适应 */
|
||||
- (void)setupAutoContentSizeWithBottomView:(UIView *)bottomView bottomMargin:(CGFloat)bottomMargin;
|
||||
|
||||
/** 设置scrollview内容横向自适应 */
|
||||
- (void)setupAutoContentSizeWithRightView:(UIView *)rightView rightMargin:(CGFloat)rightMargin;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
#pragma mark - UILabel 开启富文本布局、设置单行文本label宽度自适应、 设置label最多可以显示的行数
|
||||
|
||||
@interface UILabel (SDLabelAutoResize)
|
||||
|
||||
/** 是否是attributedString */
|
||||
@property (nonatomic) BOOL isAttributedContent;
|
||||
|
||||
/** 设置单行文本label宽度自适应 */
|
||||
- (void)setSingleLineAutoResizeWithMaxWidth:(CGFloat)maxWidth;
|
||||
|
||||
/** 设置label最多可以显示多少行,如果传0则显示所有行文字 */
|
||||
- (void)setMaxNumberOfLinesToShow:(NSInteger)lineCount;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
#pragma mark - UIButton 设置button根据单行文字自适应
|
||||
|
||||
@interface UIButton (SDExtention)
|
||||
|
||||
/*
|
||||
* 设置button根据单行文字自适应
|
||||
* hPadding:左右边距
|
||||
*/
|
||||
- (void)setupAutoSizeWithHorizontalPadding:(CGFloat)hPadding buttonHeight:(CGFloat)buttonHeight;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma mark - 其他方法(如果有需要可以自己利用以下接口拓展更多功能)
|
||||
|
||||
@interface SDAutoLayoutModelItem : NSObject
|
||||
|
||||
@property (nonatomic, strong) NSNumber *value;
|
||||
@property (nonatomic, weak) UIView *refView;
|
||||
@property (nonatomic, assign) CGFloat offset;
|
||||
@property (nonatomic, strong) NSArray *refViewsArray;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface UIView (SDChangeFrame)
|
||||
|
||||
@property (nonatomic) BOOL shouldReadjustFrameBeforeStoreCache;
|
||||
|
||||
@property (nonatomic) CGFloat left_sd;
|
||||
@property (nonatomic) CGFloat top_sd;
|
||||
@property (nonatomic) CGFloat right_sd;
|
||||
@property (nonatomic) CGFloat bottom_sd;
|
||||
@property (nonatomic) CGFloat centerX_sd;
|
||||
@property (nonatomic) CGFloat centerY_sd;
|
||||
|
||||
@property (nonatomic) CGFloat width_sd;
|
||||
@property (nonatomic) CGFloat height_sd;
|
||||
|
||||
|
||||
@property (nonatomic) CGPoint origin_sd;
|
||||
@property (nonatomic) CGSize size_sd;
|
||||
|
||||
|
||||
// 兼容旧版本
|
||||
@property (nonatomic) CGFloat left;
|
||||
@property (nonatomic) CGFloat top;
|
||||
@property (nonatomic) CGFloat right;
|
||||
@property (nonatomic) CGFloat bottom;
|
||||
@property (nonatomic) CGFloat centerX;
|
||||
@property (nonatomic) CGFloat centerY;
|
||||
@property (nonatomic) CGFloat width;
|
||||
@property (nonatomic) CGFloat height;
|
||||
@property (nonatomic) CGPoint origin;
|
||||
@property (nonatomic) CGSize size;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface SDUIViewCategoryManager : NSObject
|
||||
|
||||
@property (nonatomic, strong) NSArray *rightViewsArray;
|
||||
@property (nonatomic, assign) CGFloat rightViewRightMargin;
|
||||
|
||||
@property (nonatomic, weak) UITableView *sd_tableView;
|
||||
@property (nonatomic, strong) NSIndexPath *sd_indexPath;
|
||||
|
||||
@property (nonatomic, assign) BOOL hasSetFrameWithCache;
|
||||
|
||||
@property (nonatomic) BOOL shouldReadjustFrameBeforeStoreCache;
|
||||
|
||||
@property (nonatomic, assign, getter = sd_isClosingAutoLayout) BOOL sd_closeAutoLayout;
|
||||
|
||||
|
||||
/** 设置类似collectionView效果的固定间距自动宽度浮动子view */
|
||||
|
||||
@property (nonatomic, strong) NSArray *flowItems;
|
||||
@property (nonatomic, assign) CGFloat verticalMargin;
|
||||
@property (nonatomic, assign) CGFloat horizontalMargin;
|
||||
@property (nonatomic, assign) NSInteger perRowItemsCount;
|
||||
@property (nonatomic, assign) CGFloat lastWidth;
|
||||
|
||||
|
||||
/** 设置类似collectionView效果的固定宽带自动间距浮动子view */
|
||||
|
||||
@property (nonatomic, assign) CGFloat flowItemWidth;
|
||||
@property (nonatomic, assign) BOOL shouldShowAsAutoMarginViews;
|
||||
|
||||
|
||||
@property (nonatomic) CGFloat horizontalEdgeInset;
|
||||
@property (nonatomic) CGFloat verticalEdgeInset;
|
||||
|
||||
@end
|
||||
|
||||
1842
Pods/SDAutoLayout/SDAutoLayoutDemo/SDAutoLayout/UIView+SDAutoLayout.m
generated
Executable file
1842
Pods/SDAutoLayout/SDAutoLayoutDemo/SDAutoLayout/UIView+SDAutoLayout.m
generated
Executable file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user