UITableViewCell 中的 UITextField 使用自动布局

Posted

技术标签:

【中文标题】UITableViewCell 中的 UITextField 使用自动布局【英文标题】:UITextField within UITableViewCell using auto layout 【发布时间】:2013-11-11 02:48:04 【问题描述】:

我有一个UITableViewController,它显示一个部分和一个单元格(测试用例)。 在那个单元格中,我有一个UITextField,它应该跨越单元格contentView 的长度,两边各有20 个点(即H:|-20-[field]-20-|)并垂直居中。 当我使用带有必要约束的笔尖时,它可以完美地工作,但是当我以编程方式添加约束时,它似乎没有遵循它们。 (见图片。)

-tableView:willDisplayCell:forRowAtIndexPath: 中的NSLog() 在两种情况下打印完全相同的约束。

FOOAppDelegate.m:

#import "FOOAppDelegate.h"
#import "FOORootViewController.h"

@implementation FOOAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    UINavigationController *controller = [[UINavigationController alloc] initWithRootViewController:[[FOORootViewController alloc] initWithStyle:UITableViewStyleGrouped]];
    self.window.rootViewController = controller;
    [self.window makeKeyAndVisible];
    return YES;


@end

FOORootViewController.m:(注意:被声明为 UITextFieldDelegate)

#import "FOORootViewController.h"

enum  kFOOTextFieldTag = 0xFEED /* Arbitrary. */ ;

@implementation FOORootViewController

- (id)initWithStyle:(UITableViewStyle)style

    self = [super initWithStyle:style];
    if (self) 
        self.title = @"Foo";
        self.navigationItem.rightBarButtonItem = self.editButtonItem;
    
    return self;


- (void)setEditing:(BOOL)editing animated:(BOOL)animated

    [super setEditing:editing animated:animated];
    [self.tableView reloadData];


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

    return 1;


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    return 1;


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    static NSString *CellIdentifier = @"FooCell";
    /* Uncomment the following line when using nib. */
    //[self.tableView registerNib:[UINib nibWithNibName:@"FooCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:CellIdentifier];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    /* Comment this if block when using nib. */
    if (cell == nil) 
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    

    /* Comment this if block when using nib. */
    if (self.editing && ([cell.contentView viewWithTag:kFOOTextFieldTag] == nil)) 
        UITextField *field = [[UITextField alloc] init];
        field.autocapitalizationType = UITextAutocapitalizationTypeSentences;
        field.borderStyle = UITextBorderStyleLine;
        field.delegate = self;
        field.placeholder = @"New";
        field.tag = kFOOTextFieldTag;
        field.translatesAutoresizingMaskIntoConstraints = NO;
        field.userInteractionEnabled = YES;
        [cell.contentView addSubview:field];

        NSDictionary *objs = NSDictionaryOfVariableBindings(cell.contentView, field);
        cell.contentView.translatesAutoresizingMaskIntoConstraints = NO;
        [cell.contentView addConstraints:[NSLayoutConstraint
            constraintsWithVisualFormat:@"V:|-7-[field]"
            options:0
            metrics:nil
            views:objs]];
        [cell.contentView addConstraints:[NSLayoutConstraint
            constraintsWithVisualFormat:@"V:[field]-6-|"
            options:0
            metrics:nil
            views:objs]];
        [cell.contentView addConstraints:[NSLayoutConstraint
            constraintsWithVisualFormat:@"H:|-20-[field]"
            options:0
            metrics:nil
            views:objs]];
        [cell.contentView addConstraints:[NSLayoutConstraint
            constraintsWithVisualFormat:@"H:[field]-20-|"
            options:0
            metrics:nil
            views:objs]];
    

    return cell;


- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath

    UITextField *field = (UITextField *)[cell.contentView viewWithTag:kFOOTextFieldTag];
    if (self.editing) 
        field.hidden = NO;

        NSLog(@"field: %@", field);
     else 
        field.hidden = YES;
    

    NSLog(@"cell.contentView: %@", cell.contentView);
    NSLog(@"constraints: %@", cell.contentView.constraints);


- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath

    return YES;


- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath

    return UITableViewCellEditingStyleInsert;

这是我不使用笔尖时得到的结果(横向时没有区别):

这就是我用笔尖得到的(适合横向缩放):

【问题讨论】:

我在单元格约束方面遇到了类似的问题,并通过在 tableView:willDisplayCell:forRowAtIndexPath: 中设置约束来解决它:而不是 tableView:cellForRowAtIndexPath:。似乎他们正在对尚未完全初始化的值进行操作。 【参考方案1】:

你应该删除这行,它会正常工作:

cell.contentView.translatesAutoresizingMaskIntoConstraints = NO;

您只需为自己添加的子视图将其设置为 NO。

另外,我注意到您在 cellForRowAtIndexPath 中注册了 nib(如果您使用的是 nib)——您不应该这样做,因为 cellForRowAtIndexPath 被多次调用。您应该将该代码放在 viewDidLoad 中。

另一件事——你应该简化你的约束代码。使用可视化格式语言的一大优势是可以在同一个语句中设置多个约束,因此可以将你的 4 个语句组合成 2 个:

cell.contentView addConstraints:[NSLayoutConstraint
                                          constraintsWithVisualFormat:@"V:|-7-[field]-6-|"
                                          options:0
                                          metrics:nil
                                          views:objs]];

cell.contentView addConstraints:[NSLayoutConstraint
                                          constraintsWithVisualFormat:@"H:|-20-[field]-20-|"
                                          options:0
                                          metrics:nil
                                          views:objs]];

【讨论】:

以上是关于UITableViewCell 中的 UITextField 使用自动布局的主要内容,如果未能解决你的问题,请参考以下文章

根据内容大小属性设置 UIText 视图的宽度

从 UIText 字段的用户输入更改 UIView 框架的高度和宽度

无法更改 UIText 视图的字体(使用 Web 服务时)

如何从 UITextfields UIMenuController 中删除不需要的 UIMenuItems?

UITableViewCell 中的 UIDatePicker 更新 UITableViewCell 文本标签

更改 UITableViewCell 中的对象也更改了重用 UITableViewCell 的对象