UITableViewCell错误的高度如果只出现一个项目

时间:2015-01-05 10:57:13

标签: ios objective-c uitableview

我有一个带有自定义单元格的UITableView,一开始都是空的。

我的UITableViewCell有一个UITextView,当我点击屏幕时,我创建了一个新的单元格,然后点亮它:

#import "MemoViewController.h"
#import "MemoViewCell.h"
#import "MemoModel.h"

static NSString *CellIdentifier = @"MemoCell";

@interface MemoViewController () <UITextViewDelegate>

@property (nonatomic, strong) MemoModel *model;
@property (nonatomic, strong) NSMutableDictionary *offscreenCells;

@end

@implementation MemoViewController
{
    NSIndexPath *currentIndexPath;
}

-(id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        self.model = [[MemoModel alloc] init];
        //[self.model populateDataSource];
        self.offscreenCells = [NSMutableDictionary dictionary];
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    [self.tableView registerClass:[MemoViewCell class] forCellReuseIdentifier:CellIdentifier];

    self.tableView.rowHeight = UITableViewAutomaticDimension;

    UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(insertNewRow:)];
    gestureRecognizer.cancelsTouchesInView = NO;
    [self.tableView addGestureRecognizer:gestureRecognizer];
    currentIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];

    UIBarButtonItem *editButton = [[UIBarButtonItem alloc]
                                   initWithTitle:@"Modifica"
                                   style:UIBarButtonItemStyleBordered
                                   target:self
                                   action:@selector(editButtonPressed:)];
    self.navigationItem.rightBarButtonItem = editButton;
}

-(IBAction)editButtonPressed:(UIBarButtonItem *)sender
{
    if ([sender.title isEqualToString:@"Fine"]) {
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[self.model.dataSource count] - 1 inSection:0];
        MemoViewCell *cell = (MemoViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];
        [cell.bodyLabel resignFirstResponder];
    }
}

-(void)insertNewRow:(UIGestureRecognizer *)gestureRecognizer
{
    CGPoint point = [gestureRecognizer locationInView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:point];

    if (indexPath == nil) {
        [self.model addObject];
        [self.tableView reloadData];
        indexPath = [NSIndexPath indexPathForRow:[self.model rowsCount] - 1 inSection:0];
    }

    [self.navigationItem.rightBarButtonItem setTitle:@"Fine"];

    MemoViewCell *cell = (MemoViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];
    [cell.bodyLabel becomeFirstResponder];
}

-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contentSizeCategoryChanged:) name:UIContentSizeCategoryDidChangeNotification object:nil];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

-(void)contentSizeCategoryChanged:(NSNotification *)notification
{
    [self.tableView reloadData];
}


#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.model.dataSource count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    MemoViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if ([self.model.dataSource count] > 0) {
        NSDictionary *dataSourceItem = [self.model.dataSource objectAtIndex:indexPath.row];
        cell.bodyLabel.text = [dataSourceItem valueForKey:@"body"];
    }

    cell.bodyLabel.delegate = self;

    [cell setNeedsUpdateConstraints];
    [cell updateConstraintsIfNeeded];


    return cell;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *reuserIdentifier = CellIdentifier;

    if ([self.model.dataSource count] > 0) {
        MemoViewCell *cell = [self.offscreenCells objectForKey:reuserIdentifier];

        if (!cell) {
            cell = [[MemoViewCell alloc] init];
            [self.offscreenCells setObject:cell forKeyedSubscript:reuserIdentifier];
        }

        [cell updateFonts];
        NSDictionary *dataSourceItem = [self.model.dataSource objectAtIndex:indexPath.row];
        cell.bodyLabel.text = [dataSourceItem valueForKey:@"body"];

        [cell setNeedsUpdateConstraints];
        [cell updateConstraintsIfNeeded];

        cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(cell.bounds));
        [cell setNeedsLayout];
        [cell layoutIfNeeded];

        CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

        height += 1;

        CGFloat toReturn = height + [self measureHeightOfUITextView:cell.bodyLabel] - 30;

        NSLog(@"Height for Row %li is %f", (long)indexPath.row, toReturn);

        return toReturn;
    } else {
        return 44.0;
    }
}

-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 44.0;
}
/*
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    MemoViewCell *cell = (MemoViewCell *)[tableView cellForRowAtIndexPath:indexPath];
    cell.bodyLabel.userInteractionEnabled = YES;
    [cell.bodyLabel becomeFirstResponder];
}
*/
#pragma mark - Text View Delegate
- (void)textViewDidBeginEditing:(UITextView*)textView
{
    MemoViewCell* cell = (MemoViewCell *)[self parentCellFor:textView];
    if (cell)
    {
        NSIndexPath* indexPath = [self.tableView indexPathForCell:cell];
        currentIndexPath = indexPath;
        [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
    }
}
/*
-(BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
    MemoViewCell *cell = (MemoViewCell *)[self.tableView cellForRowAtIndexPath:currentIndexPath];
    [cell.bodyLabel becomeFirstResponder];
    [self.tableView selectRowAtIndexPath:currentIndexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
    return YES;
}
*/

- (UITableViewCell*)parentCellFor:(UIView*)view
{
    if (!view)
        return nil;
    if ([view isMemberOfClass:[MemoViewCell class]])
        return (UITableViewCell*)view;
    return [self parentCellFor:view.superview];
}

-(void)textViewDidChange:(UITextView *)textView
{
    NSMutableDictionary *dataSourceItem = [self.model.dataSource objectAtIndex:currentIndexPath.row];
    [dataSourceItem setObject:textView.text forKey:@"body"];
    [self.model.dataSource replaceObjectAtIndex:currentIndexPath.row withObject:dataSourceItem];

    if ([textView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height != textView.frame.size.height) {
        [self.tableView beginUpdates];
        [self.tableView endUpdates];
    }
}

-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    return YES;
}

- (CGFloat)measureHeightOfUITextView:(UITextView *)textView
{
    if ([textView respondsToSelector:@selector(snapshotViewAfterScreenUpdates:)])
    {
        CGRect frame = textView.bounds;

        UIEdgeInsets textContainerInsets = textView.textContainerInset;
        UIEdgeInsets contentInsets = textView.contentInset;

        CGFloat leftRightPadding = textContainerInsets.left + textContainerInsets.right + textView.textContainer.lineFragmentPadding * 2 + contentInsets.left + contentInsets.right;
        CGFloat topBottomPadding = textContainerInsets.top + textContainerInsets.bottom + contentInsets.top + contentInsets.bottom;

        frame.size.width -= leftRightPadding;
        frame.size.height -= topBottomPadding;

        NSString *textToMeasure = textView.text;
        if ([textToMeasure hasSuffix:@"\n"])
        {
            textToMeasure = [NSString stringWithFormat:@"%@-", textView.text];
        }

        NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
        [paragraphStyle setLineBreakMode:NSLineBreakByWordWrapping];

        NSDictionary *attributes = @{ NSFontAttributeName: textView.font, NSParagraphStyleAttributeName : paragraphStyle };

        CGRect size = [textToMeasure boundingRectWithSize:CGSizeMake(CGRectGetWidth(frame), MAXFLOAT)
                                                  options:NSStringDrawingUsesLineFragmentOrigin
                                               attributes:attributes
                                                  context:nil];

        CGFloat measuredHeight = ceilf(CGRectGetHeight(size) + topBottomPadding);
        return measuredHeight;
    }
    else
    {
        return textView.contentSize.height;
    }
}

@end

使用此代码(insertNewRow :)我首先在dataModel上创建一个新对象,我重新加载数据以设置所有表,然后我将第一个响应者设置为我最后添加的UITextView。

在textViewDidChange上:委托我更新表以将行展开到UITextViewContent。

如果我至少有2行,那么一切正常。如果我只有一行,则所有行都采用相同的宽度。

1 个答案:

答案 0 :(得分:0)

如果你的细胞高度是固定的,那么只需使用此方法返回。

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

但是如果您的单元格的高度是动态的,那么您需要进行一些计算,然后返回单元格的正确高度。