UITableViewCell在iOS中具有长长内容的扩展

时间:2017-03-20 10:28:03

标签: ios uitableview

1.当单元格内的内容太长,单元格扩展,或者收缩时,UITableView将滚动到单元格位置的后面。

2.我希望单元格回滚到它开始扩展的位置。

我的代码:

    ((PartnershipsTableViewCell *)cell).commentSpreadButtonClickHandler = ^() {
       // just call - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
        [weakSelf.tableView beginUpdates];
        [weakCell configUI];
        [weakSelf.tableView endUpdates];

        // if here use "[weakSelf.tableView reloadData]", 
        // it can be correct, 
        // Unless on the first cell which have the expansion button.
    };

然后更新uitableview单元格的高度。但结果不是我想要的

- (void)configUI {
    if ([self.baseModel isKindOfClass: [UserWorldDynamicModel class]]) {
        self.model = (id)self.baseModel;
    }
    [self setupValue];
}

- (void)setupValue {
    // setup the property value, and update the constraints with masonry
}


// the button : read less or read more
- (void)setSpreadButton {
    NSString *text = self.model.isContentOpen ? @"read less" : @"read more";
    if (!self.spreadButton) {
        self.spreadButton = [MYSUtil createButtonWithTitle: text target: self sel: @selector(spreadButtonClick:) image: nil font: Font14 color: DarkBlueTextColor cornerRadius: 0];
        self.spreadButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
    }
    if (self.model.shouldShowSpreadButton) {
        if (!self.spreadButton.superview) {
            [self.whiteBackgroudView addSubview: self.spreadButton];
        }
        [self.spreadButton setTitle: text forState: UIControlStateNormal];
        self.spreadButton.selected = [self.model.isSpreadState intValue];
        self.spreadButton.frame = CGRectMake(CGRectGetMinX(self.contentLabel.frame), CGRectGetMaxY(self.contentLabel.frame), 80, 30);
        self.tempView = self.spreadButton;
    } else {
        if (self.spreadButton.superview) {
            [self.spreadButton removeFromSuperview];
        }
    }
}

    // calculate the height of the label and compare it with the fixed value
    NSMutableAttributedString *string = [self createMutableAttibuteStringWithNSString: text withFont: font];
    self.contentLabel.attributedText = string;

    // here calculate maxContentLabelHeight with
    CGFloat maxContentLabelHeight = self.contentLabel.font.pointSize * (numberOfLines + 1) + 16;

    // here calculate the NSMutableAttributedString's height
    YYTextContainer *container = [YYTextContainer containerWithSize:CGSizeMake(width, MAXFLOAT)];
    YYTextLayout *textLayout = [YYTextLayout layoutWithContainer:container text: string];
    CGSize size = textLayout.textBoundingSize;
    CGFloat height = size.height;

    // then compare the NSMutableAttributedString's height with the fixed value. if true, show the spreadButton
    if (height > maxContentLabelHeight) {
        self.model.shouldShowSpreadButton = YES;
        // storage the real height and temp height, use to calculate the tableView's contentOffset, when cell from expansion state to shrinking state in block.
        self.model.contentHeight = height;
        self.model.tempContentHeight = maxContentLabelHeight;
    }

    // if height > maxContentLabelHeight and the property "isContentOpen" of the viewModel, the height value is maxContentLabelHeight, Or not, the height value is height
    if (!self.model.isContentOpen && height > maxContentLabelHeight) {
        height = maxContentLabelHeight;
    }

    // no matter cell is expansion state or shrinking state, reset label's frame.
    self.contentLabel.frame = CGRectMake(x, CGRectGetMaxY(self.headerImageView.frame) + Margin_Top, width, height);

1 个答案:

答案 0 :(得分:0)

readMore / readLess块

在mainQueue上的tableView reloadData之前,记录它的contentOffset,用于计算需要滚动的tableView的位置。像这样:

 CGPoint point = weakSelf.tableView.contentOffset;

reloadData:刷新tableView在mainQueue上。 当reloadData完成时,将tableView滚动到展开的位置。当tableView从扩展状态到收缩状态,并且扩展状态的高度大于屏幕高度的70%时,滚动tableView(70%是ma条件,你可以根据你的情况改变)

- (UITableViewCell *)tableView:(UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath {
    // here is your code
    PartnershipsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: cellIdentifierString];
    [cell config];
    ((PartnershipsTableViewCell *)cell).spreadButtonClickHandler = ^() {
        CGPoint point = weakSelf.tb.contentOffset;
        [weakSelf.tb reloadData];
        if (!baseModel.isContentOpen && baseModel.contentHeight > SCREEN_HEIGHT * 0.7) {
            point.y -= baseModel.contentHeight - baseModel.tempContentHeight;
            dispatch_async(dispatch_get_main_queue(), ^{
                weakSelf.tb.contentOffset = point;
            });
        }
    };
    return cell;
}


- (CGFloat)tableView:(UITableView *) tableView heightForRowAtIndexPath:(NSIndexPath *) indexPath {
    return 70;
}

在我的问题中,当你在代码中使用follow方法时,我发现另一个有趣的问题。如果你的细胞有很大的变化,特别是细胞的高度。当你使用方法[tableView reloadData]时,你最好不要使用follow方法。

 - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
        return 70;
  }

然后使用方法[tableView reloadData]刷新UI,tableView将滚动到任何位置,所以我删除它。因为,这个方法用来估计单元格的高度,然后用来估计tableView的contentSize,如果估计和实际之间的高度差较大,使用方法[tableView reloadData],会导致tableView滚动到任何地方。(不要问我怎么知道,这对我来说是一个痛苦的过程。)

我已经解决了这个问题,给自己留下了一些笔记,并为每个人留下了一些笔记,并希望我的解决方案也可以为你提供帮助。

感谢@pckill和@Theorist,没有你的建议,我无法解决我的问题如此完美,非常感谢你。

@Theorist我在脑海里重新编写了我的代码。也许,可读性现在更好。