iOS 7 UITableViewCell与AutoLayout的冲突约束

基本上,我在单独的XIB文件中创build一个空的UITableViewCell。 层次结构显示在这里: https : //www.dropbox.com/s/nba8e5t7dvti7os/hierarchy.png

我想根据内容(通过更新约束常量)在运行时改变内部视图的高度,并基于这个计算单元格/行高度。 所以,如果我有很高的内容,我的行就会扩大,如果我的内容很短,我的行就会变小。 我想为这些计算使用AutoLayout。

我有限制,坚持ContentView的顶部/底部,并希望我的内部视图的高度= 20。

几乎立即我看到一个冲突: https : //www.dropbox.com/s/b3effgdw3t2768m/conflict.png

绝对是我对AutoLayout的理解不完整。

第一个问题是:我希望我的视angular是20pt高度,而我的ContenView是完全一样的大小,这是怎么回事?

第二个问题是:我如何实现这一目标?

这是一个我为你破解的演示程序,完全是用代码完成的。

你会看到在我的DemoTableViewCell.m文件中,我使用的约束没有固定的高度约束,以允许内容自由扩展。 它被固定在四个contentView边缘(顶部,右边,底部,左边),可选的20像素填充为视觉格式的目的。

结果是这样的:

动态TableView单元格高度

应用程序委托方法

#import "AppDelegate.h" #import "DemoViewController.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. DemoViewController *demoVC = [[DemoViewController alloc] init]; UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:demoVC]; self.window.rootViewController = navController; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES; } 

DemoViewController.h

 #import <UIKit/UIKit.h> @interface DemoViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> @property (nonatomic, strong) NSArray *arrText; @property (nonatomic, strong) UITableView *tableView; @end 

DemoViewController.m

 #import "DemoViewController.h" #import "DemoTableViewCell.h" @interface DemoViewController () { DemoTableViewCell *offscreenCell; } @end @implementation DemoViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.navigationItem.title = @"Dynamic Cell Height"; [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone]; // init data source self.arrText = @[ @"Lorem ipsum dolor sit amet, consectetur adipiscing elit.", @"Cras rhoncus velit odio, quis dapibus orci tristique eget. Aenean pretium lorem sit amet risus euismod, at dictum justo imperdiet. Suspendisse id feugiat quam, quis mattis felis. Maecenas justo magna, pellentesque sed elementum sed, ultricies rutrum neque.", @"Cras lobortis lacus arcu, non ullamcorper magna faucibus eu. Donec adipiscing eu odio ac dignissim.", @"Vivamus sodales leo massa, in rhoncus purus placerat sit amet. Praesent mattis, lacus scelerisque porttitor interdum, urna sapien ullamcorper est, in placerat augue nulla eget turpis. Curabitur et feugiat orci, lacinia commodo nisl. Nulla sit amet tellus consequat, luctus tellus nec, porttitor libero. Proin mattis, purus nec pellentesque mollis, ligula sapien vehicula magna, et volutpat ligula ligula pulvinar risus. Cras hendrerit urna sagittis iaculis scelerisque. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Suspendisse ut porttitor arcu. Curabitur sit amet sodales tortor. Pellentesque consequat dui quis mi luctus consectetur. Etiam et dignissim felis.", @"Pellentesque habitant", @"Sed nec consectetur lectus. Mauris at enim nec purus sagittis pellentesque eget id urna." ]; // init table view self.tableView = [[UITableView alloc] initWithFrame:self.view.frame]; self.tableView.separatorInset = UIEdgeInsetsZero; self.tableView.dataSource = self; self.tableView.delegate = self; [self.view addSubview:self.tableView]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (BOOL)prefersStatusBarHidden { return YES; } #pragma mark - UITableViewDelegate Methods - -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.arrText.count; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellID = @"cellID"; DemoTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; if(cell == nil) { cell = [[DemoTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID]; } cell = [self setupCell:cell forIndexPath:indexPath]; return cell; } // --------------------------------------------------------------------------- // This method will setup the cell text and such // --------------------------------------------------------------------------- -(DemoTableViewCell *)setupCell:(DemoTableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath { cell.lblText.text = [self.arrText objectAtIndex:indexPath.row]; return cell; } -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if(offscreenCell == nil) { offscreenCell = [[DemoTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"offscreenCell"]; } DemoTableViewCell *cell = [self setupCell:offscreenCell forIndexPath:indexPath]; [cell layoutIfNeeded]; return [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; } @end 

DemoTableViewCell.h

 #import <UIKit/UIKit.h> @interface DemoTableViewCell : UITableViewCell @property (nonatomic, strong) UILabel *lblText; @end 

DemoTableViewCell.m

 #import "DemoTableViewCell.h" @implementation DemoTableViewCell - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { // Initialization code [self initView]; [self addAllConstraints]; } return self; } - (void)awakeFromNib { // Initialization code } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; // Configure the view for the selected state } -(void)initView { self.lblText = [[UILabel alloc] init]; self.lblText.numberOfLines = 0; self.lblText.lineBreakMode = NSLineBreakByWordWrapping; self.lblText.preferredMaxLayoutWidth = self.bounds.size.width - 40.0; self.lblText.font = [UIFont systemFontOfSize:12]; [self.contentView addSubview:self.lblText]; } -(void)addAllConstraints { self.lblText.translatesAutoresizingMaskIntoConstraints = NO; id views = @{@"lblText": self.lblText}; // ------------------------------------------------------------ // Pin the label text subview to all four contentView edges. // // The lblText should automatically expand to fit the content // text, no need for fixed height constraints here. // ------------------------------------------------------------ [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[lblText]-20-|" options:0 metrics:nil views:views]]; [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[lblText]-20-|" options:0 metrics:nil views:views]]; } @end