Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

修复HeaderFooterView的bug 哔了狗了 快合并 #243

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
47 changes: 36 additions & 11 deletions Classes/UITableView+FDTemplateLayoutCell.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
#import "UITableView+FDIndexPathHeightCache.h"
#import "UITableView+FDTemplateLayoutCellDebug.h"


#pragma mark - Cell

@interface UITableView (FDTemplateLayoutCell)

/// Access to internal template layout cell for given reuse identifier.
Expand Down Expand Up @@ -70,18 +73,17 @@
///
- (CGFloat)fd_heightForCellWithIdentifier:(NSString *)identifier cacheByKey:(id<NSCopying>)key configuration:(void (^)(id cell))configuration;

@end

@interface UITableView (FDTemplateLayoutHeaderFooterView)

/// Returns header or footer view's height that registered in table view with reuse identifier.
///
/// Use it after calling "-[UITableView registerNib/Class:forHeaderFooterViewReuseIdentifier]",
/// same with "-fd_heightForCellWithIdentifier:configuration:", it will call "-sizeThatFits:" for
/// subclass of UITableViewHeaderFooterView which is not using Auto Layout.
///
- (CGFloat)fd_heightForHeaderFooterViewWithIdentifier:(NSString *)identifier configuration:(void (^)(id headerFooterView))configuration;

/**

configure a undequere tableViewCell

@param staticCell It's create by [[UITableView alloc] init];
@param configuration It's could be NULL

@return Static cell height
*/
- (CGFloat)fd_heightForCellWithStaticCell:(UITableViewCell *)staticCell configuration:(void (^)(id cell))configuration;
@end

@interface UITableViewCell (FDTemplateLayoutCell)
Expand All @@ -106,3 +108,26 @@
@property (nonatomic, assign) BOOL fd_enforceFrameLayout;

@end


#pragma mark - HeaderFooterView

@interface UITableView (FDTemplateLayoutHeaderFooterView)

/// Returns header or footer view's height that registered in table view with reuse identifier.
///
/// Use it after calling "-[UITableView registerNib/Class:forHeaderFooterViewReuseIdentifier]",
/// same with "-fd_heightForCellWithIdentifier:configuration:", it will call "-sizeThatFits:" for
/// subclass of UITableViewHeaderFooterView which is not using Auto Layout.
///
- (CGFloat)fd_heightForHeaderFooterViewWithIdentifier:(NSString *)identifier configuration:(void (^)(id headerFooterView))configuration;

@end

@interface UITableViewHeaderFooterView (FDTemplateLayoutHeaderFooterView)

@property (nonatomic, assign) BOOL fd_isTemplateLayoutHeaderFooterView;

@property (nonatomic, assign) BOOL fd_enforceFrameLayout;

@end
152 changes: 124 additions & 28 deletions Classes/UITableView+FDTemplateLayoutCell.m
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
#import "UITableView+FDTemplateLayoutCell.h"
#import <objc/runtime.h>


#pragma mark - Cell

@implementation UITableView (FDTemplateLayoutCell)

- (CGFloat)fd_systemFittingHeightForConfiguratedCell:(UITableViewCell *)cell {
Expand Down Expand Up @@ -57,6 +60,7 @@ - (CGFloat)fd_systemFittingHeightForConfiguratedCell:(UITableViewCell *)cell {
// Add a hard width constraint to make dynamic content views (like labels) expand vertically instead
// of growing horizontally, in a flow-layout manner.
NSLayoutConstraint *widthFenceConstraint = [NSLayoutConstraint constraintWithItem:cell.contentView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:contentViewWidth];
widthFenceConstraint.priority = UILayoutPriorityDefaultHigh;
[cell.contentView addConstraint:widthFenceConstraint];

// Auto layout engine does its math
Expand Down Expand Up @@ -175,11 +179,127 @@ - (CGFloat)fd_heightForCellWithIdentifier:(NSString *)identifier cacheByKey:(id<
return height;
}


// Static Cell - by Star.
- (CGFloat)fd_heightForCellWithStaticCell:(UITableViewCell *)staticCell configuration:(void (^)(id cell))configuration {

if (!staticCell) {
return 0;
}

UITableViewCell *templateLayoutCell = staticCell;

// Manually calls to ensure consistent behavior with actual cells. (that are displayed on screen)
[templateLayoutCell prepareForReuse];

// Customize and provide content for our template cell.
if (configuration) {
configuration(templateLayoutCell);
}

return [self fd_systemFittingHeightForConfiguratedCell:templateLayoutCell];
}

@end

@implementation UITableViewCell (FDTemplateLayoutCell)

- (BOOL)fd_isTemplateLayoutCell {
return [objc_getAssociatedObject(self, _cmd) boolValue];
}

- (void)setFd_isTemplateLayoutCell:(BOOL)isTemplateLayoutCell {
objc_setAssociatedObject(self, @selector(fd_isTemplateLayoutCell), @(isTemplateLayoutCell), OBJC_ASSOCIATION_RETAIN);
}

- (BOOL)fd_enforceFrameLayout {
return [objc_getAssociatedObject(self, _cmd) boolValue];
}

- (void)setFd_enforceFrameLayout:(BOOL)enforceFrameLayout {
objc_setAssociatedObject(self, @selector(fd_enforceFrameLayout), @(enforceFrameLayout), OBJC_ASSOCIATION_RETAIN);
}

@end




#pragma mark - HeaderFooterView

@implementation UITableViewHeaderFooterView (FDTemplateLayoutHeaderFooterView)

- (BOOL)fd_isTemplateLayoutHeaderFooterView {
return [objc_getAssociatedObject(self, _cmd) boolValue];
}

- (void)setFd_isTemplateLayoutHeaderFooterView:(BOOL)fd_isTemplateLayoutHeaderFooterView {
objc_setAssociatedObject(
self,
@selector(fd_isTemplateLayoutCell),
@(fd_isTemplateLayoutHeaderFooterView),
OBJC_ASSOCIATION_RETAIN
);
}

- (BOOL)fd_enforceFrameLayout {
return [objc_getAssociatedObject(self, _cmd) boolValue];
}

- (void)setFd_enforceFrameLayout:(BOOL)enforceFrameLayout {
objc_setAssociatedObject(self, @selector(fd_enforceFrameLayout), @(enforceFrameLayout), OBJC_ASSOCIATION_RETAIN);
}

@end

@implementation UITableView (FDTemplateLayoutHeaderFooterView)

- (CGFloat)fd_systemFittingHeightForConfiguratedHeaderFooterView:(UITableViewHeaderFooterView *)headerFooterView {
CGFloat contentViewWidth = CGRectGetWidth(self.frame);


CGFloat fittingHeight = 0;

if (!headerFooterView.fd_enforceFrameLayout && contentViewWidth > 0) {
// Add a hard width constraint to make dynamic content views (like labels) expand vertically instead
// of growing horizontally, in a flow-layout manner.
NSLayoutConstraint *widthFenceConstraint = [NSLayoutConstraint constraintWithItem:headerFooterView.contentView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:contentViewWidth];
widthFenceConstraint.priority = UILayoutPriorityDefaultHigh;
[headerFooterView.contentView addConstraint:widthFenceConstraint];

// Auto layout engine does its math
fittingHeight = [headerFooterView.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
[headerFooterView.contentView removeConstraint:widthFenceConstraint];

[self fd_debugLog:[NSString stringWithFormat:@"calculate using system fitting size (AutoLayout) - %@", @(fittingHeight)]];
}

if (fittingHeight == 0) {
#if DEBUG
// Warn if using AutoLayout but get zero height.
if (headerFooterView.contentView.constraints.count > 0) {
if (!objc_getAssociatedObject(self, _cmd)) {
NSLog(@"[FDTemplateLayoutCell] Warning once only: Cannot get a proper cell height (now 0) from '- systemFittingSize:'(AutoLayout). You should check how constraints are built in cell, making it into 'self-sizing' cell.");
objc_setAssociatedObject(self, _cmd, @YES, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
}
#endif
// Try '- sizeThatFits:' for frame layout.
// Note: fitting height should not include separator view.
fittingHeight = [headerFooterView sizeThatFits:CGSizeMake(contentViewWidth, 0)].height;

[self fd_debugLog:[NSString stringWithFormat:@"calculate using sizeThatFits - %@", @(fittingHeight)]];
}

if (fittingHeight == 0) {
fittingHeight = 44;
}

return fittingHeight;
}

- (__kindof UITableViewHeaderFooterView *)fd_templateHeaderFooterViewForReuseIdentifier:(NSString *)identifier {

NSAssert(identifier.length > 0, @"Expect a valid identifier - %@", identifier);

NSMutableDictionary<NSString *, UITableViewHeaderFooterView *> *templateHeaderFooterViews = objc_getAssociatedObject(self, _cmd);
Expand All @@ -194,6 +314,7 @@ - (__kindof UITableViewHeaderFooterView *)fd_templateHeaderFooterViewForReuseIde
templateHeaderFooterView = [self dequeueReusableHeaderFooterViewWithIdentifier:identifier];
NSAssert(templateHeaderFooterView != nil, @"HeaderFooterView must be registered to table view for identifier - %@", identifier);
templateHeaderFooterView.contentView.translatesAutoresizingMaskIntoConstraints = NO;
templateHeaderFooterView.fd_isTemplateLayoutHeaderFooterView = true;
templateHeaderFooterViews[identifier] = templateHeaderFooterView;
[self fd_debugLog:[NSString stringWithFormat:@"layout header footer view created - %@", identifier]];
}
Expand All @@ -203,37 +324,12 @@ - (__kindof UITableViewHeaderFooterView *)fd_templateHeaderFooterViewForReuseIde

- (CGFloat)fd_heightForHeaderFooterViewWithIdentifier:(NSString *)identifier configuration:(void (^)(id))configuration {
UITableViewHeaderFooterView *templateHeaderFooterView = [self fd_templateHeaderFooterViewForReuseIdentifier:identifier];

NSLayoutConstraint *widthFenceConstraint = [NSLayoutConstraint constraintWithItem:templateHeaderFooterView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:CGRectGetWidth(self.frame)];
[templateHeaderFooterView addConstraint:widthFenceConstraint];
CGFloat fittingHeight = [templateHeaderFooterView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
[templateHeaderFooterView removeConstraint:widthFenceConstraint];

if (fittingHeight == 0) {
fittingHeight = [templateHeaderFooterView sizeThatFits:CGSizeMake(CGRectGetWidth(self.frame), 0)].height;
if (configuration) {
configuration(templateHeaderFooterView);
}

return fittingHeight;
return [self fd_systemFittingHeightForConfiguratedHeaderFooterView:templateHeaderFooterView];
}

@end

@implementation UITableViewCell (FDTemplateLayoutCell)

- (BOOL)fd_isTemplateLayoutCell {
return [objc_getAssociatedObject(self, _cmd) boolValue];
}

- (void)setFd_isTemplateLayoutCell:(BOOL)isTemplateLayoutCell {
objc_setAssociatedObject(self, @selector(fd_isTemplateLayoutCell), @(isTemplateLayoutCell), OBJC_ASSOCIATION_RETAIN);
}

- (BOOL)fd_enforceFrameLayout {
return [objc_getAssociatedObject(self, _cmd) boolValue];
}

- (void)setFd_enforceFrameLayout:(BOOL)enforceFrameLayout {
objc_setAssociatedObject(self, @selector(fd_enforceFrameLayout), @(enforceFrameLayout), OBJC_ASSOCIATION_RETAIN);
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"DVTSourceControlWorkspaceBlueprintIdentifierKey" : "6569ED7F-B9F6-4B04-BF61-CB6FDE03BD78",
"DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
"32d7d9b4-ffb1-4469-8922-27dbf3d99605++9332" : "svn\/iknow",
"45232C3CDBDF9DB333979E103A0429BCEB54D2EF" : "UITableView-FDTemplateLayoutCell"
"45232C3CDBDF9DB333979E103A0429BCEB54D2EF" : "UITableView-FDTemplateLayoutCell\/"
},
"DVTSourceControlWorkspaceBlueprintNameKey" : "FDTemplateCell",
"DVTSourceControlWorkspaceBlueprintVersion" : 204,
Expand Down