使用AutoLayout在iOS 7 UITableViewCell中存在冲突约束

时间:2014-06-29 18:12:30

标签: ios uitableview autolayout nslayoutconstraint

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

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

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

几乎立即我发现了冲突: https://www.dropbox.com/s/b3effgdw3t2768m/conflict.png

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

第一个问题是:我希望我的视图高度为20pt并且我的ContenView的大小完全相同是多么错误?

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

1 个答案:

答案 0 :(得分:2)

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

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

结果如下:

Dynamic TableView Cell Height

App Delegate Method

#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