Динамично изменяющий размеры UITableViewCell на основе ввода текста

Я пытаюсь динамично изменить размеры немного UITableViewCell на основе высоты UITextView содержавший в них. Есть множество решений этого, держа указатель на UITextView , и добираясь это - размер содержания в heightForRowAtIndexPath , однако, когда целая таблица составлена динамично с неизвестным количеством рядов и неизвестным количеством их, ряды содержат UITextView , это просто не возможно. Было бы легко, если я мог бы подвергнуть сомнению клетку во время heightForRowAtIndexPath , но это вызывает бесконечный цикл и катастрофу, как этот метод называют перед любой клеткой даже создаются. Какие-либо другие решения?

Я использую UITableViewCell подкласс для моей камеры как это:

- (void)initalizeInputView {
   //Initialization code
    self.selectionStyle = UITableViewCellSelectionStyleNone;
    self.textView = [[UITextView alloc] initWithFrame:CGRectZero];
    self.textView.autocorrectionType = UITextAutocorrectionTypeDefault;
    self.textView.autocapitalizationType = UITextAutocapitalizationTypeNone;
    self.textView.textAlignment = NSTextAlignmentRight;
    self.textView.textColor = [UIColor lightBlueColor];
    self.textView.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:17];
    self.textView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    self.textView.keyboardType = UIKeyboardTypeDefault;
    [self addSubview:self.textView];

    self.textView.delegate = self;
}

- (BOOL)resignFirstResponder {
    if (_delegate && [_delegate respondsToSelector:@selector(tableViewCell:didEndEditingWithLongString:)]) {
        [_delegate tableViewCell:self didEndEditingWithLongString:self.stringValue];
    }
    return [super resignFirstResponder];
}

- (void)setKeyboardType:(UIKeyboardType)keyboardType
{
    self.textView.keyboardType = keyboardType;
}

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        [self initalizeInputView];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self initalizeInputView];
    }
    return self;
}

- (void)setSelected:(BOOL)selected {
    [super setSelected:selected];
    if (selected) {
        [self.textView becomeFirstResponder];
    }
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];
    if (selected) {
        [self.textView becomeFirstResponder];
    }
}

- (void)setStringValue:(NSString *)value {
    self.textView.text = value;
}

- (NSString *)stringValue {
    return self.textView.text;
}

- (void)textViewDidBeginEditing:(UITextView *)textView
{
   //For keyboard scroll
    UITableView *tableView = (UITableView *)self.superview;
    AppSetupViewController *parent = (AppSetupViewController *)_delegate;
    parent.activeCellIndexPath = [tableView indexPathForCell:self];
}

- (void)textViewDidChange:(UITextView *)textView
{
    if (textView.contentSize.height > contentRowHeight) {

        contentRowHeight = textView.contentSize.height;

        UITableView *tableView = (UITableView *)self.superview;
        [tableView beginUpdates];
        [tableView endUpdates];

        [textView setFrame:CGRectMake(0, 0, 300.0, textView.contentSize.height)];
    }
}

- (void)textViewDidEndEditing:(UITextView *)textView
{
    if (_delegate && [_delegate respondsToSelector:@selector(tableViewCell:didEndEditingWithLongString:)]) {
        [_delegate tableViewCell:self didEndEditingWithLongString:self.stringValue];
    }
    UITableView *tableView = (UITableView *)self.superview;
    [tableView deselectRowAtIndexPath:[tableView indexPathForCell:self] animated:YES];
}

- (void)layoutSubviews {
    [super layoutSubviews];
    CGRect editFrame = CGRectInset(self.contentView.frame, 10, 10);

    if (self.textLabel.text && [self.textLabel.text length] != 0) {
        CGSize textSize = [self.textLabel sizeThatFits:CGSizeZero];
        editFrame.origin.x += textSize.width + 10;
        editFrame.size.width -= textSize.width + 10;
        self.textView.textAlignment = NSTextAlignmentRight;
    } else {
        self.textView.textAlignment = NSTextAlignmentLeft;
    }

    self.textView.frame = editFrame;
}

Который создается в cellForRowAtIndexPath как это:

else if ([paramType isEqualToString:@"longString"]) {
            MyIdentifier = @"AppActionLongString";

            LongStringInputTableViewCell *cell = (LongStringInputTableViewCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
            cell.textLabel.text = [[[_selectedAction objectForKey:@"parameters"] objectAtIndex:indexPath.row] objectForKey:@"name"];
            cell.params = [[_selectedAction objectForKey:@"parameters"] objectAtIndex:indexPath.row];

            cell.textView.text = [results objectAtIndex:indexPath.row];

            return cell;
        }

Просто пасуя назад высоту к переменной в моем ViewController бесполезен, потому что как я сказал, могло быть несколько из этих клеток в столе.

Спасибо

2
It' s для ввода данных пользователем. В данный момент я передаю его обратно в ViewController, используя метод делегата после завершения и храню каждого во Множестве. Когда я получу работу изменения размеров, я назову метод делегата после каждого ключевого входа, чтобы проверить на изменение размеров.
добавлено автор Darren, источник
от того, где вы получаете текст для TextView?
добавлено автор Rox, источник

9 ответы

просто комментарий

if (cell == nil)

Надежда, это поможет вам.

2
добавлено

просто комментарий

if (cell == nil)

Надежда, это поможет вам.

2
добавлено

Используйте этот метод, чтобы динамично изменить размеры вашего tableviewCell. Сначала сохраните ввод данных пользователем во Множестве NSMutable и после этого перезагрузите стол. Надежда это поможет вам.

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

    NSString *msg =[self.messages objectAtIndex:indexPath.row];
    CGSize  textSize = { 120, 10000.0 };
    CGSize size = [msg sizeWithFont:[UIFont systemFontOfSize:15]
                  constrainedToSize:textSize
                      lineBreakMode:UILineBreakModeWordWrap];


return size.height+20;

}

1
добавлено
Спасибо. Я попробовал что-то вроде этого ранее. Проблема здесь состоит в том, что вы установили ширину в 120. Мой width' s динамичные, поскольку TextView сначала собирается CGRectZero с UIViewAutoresizingFlexibleWidth , таким образом, это заполняет пространство, перенесенное Названием. Я can' t заставляют ссылку на клетку захватывать ширину.
добавлено автор Darren, источник
У клетки есть этикетка названия слева и textView справа. Ширина textView зависит от ширины этикетки названия.
добавлено автор Darren, источник
Ага, да я должен быть в состоянии сделать это. I' попытка ll настолько вскоре. Спасибо
добавлено автор Darren, источник
Ваша высота должна быть гибкой, но можно зафиксировать размер ширины. это может быть 320
добавлено автор Rox, источник
Может u получать ширину этикетки названия, если это динамично. тогда вычтите его ширину из своей ширины по умолчанию и установите свою textview ширину.
добавлено автор Rox, источник
хорошо, сообщите мне, что это помогает.
добавлено автор Rox, источник

Было бы легко, если я мог бы подвергнуть сомнению клетку во время heightForRowAtIndexPath, но это вызывает бесконечный цикл и катастрофу, как этот метод называют перед любой клеткой даже создаются. Какие-либо другие решения?

Вы можете. Я предположил бы, что вы пытаетесь звонить cellForRowAtIndexPath , который вызовет бесконечный цикл. Но необходимо скорее быть dequeuing, клетка непосредственно, звоня dequeueReusableCellWithIdentifier .

Посмотрите делегат табличного представления внедрение из TLIndexPathTools. heightForRowAtIndexPath метод похож на это:

( РЕДАКТИРУЮТ , Первоначально забыл включать метод prototypeForCellIdentifier что на самом деле dequeues клетка.)

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    id item = [self.dataModel itemAtIndexPath:indexPath];
    NSString *cellId = [self cellIdentifierAtIndexPath:indexPath];
    if (cellId) {
        UITableViewCell *cell = [self prototypeForCellIdentifier:cellId];
        if ([cell conformsToProtocol:@protocol(TLDynamicSizeView)]) {
            id v = (id)cell;
            id data;
            if ([item isKindOfClass:[TLIndexPathItem class]]) {
                TLIndexPathItem *i = (TLIndexPathItem *)item;
                data = i.data;
            } else {
                data = item;
            }
            CGSize computedSize = [v sizeWithData:data];
            return computedSize.height;
        } else {
            return cell.bounds.size.height;
        }
    }

    return 44.0;
}

- (UITableViewCell *)tableView:(UITableView *)tableView prototypeForCellIdentifier:(NSString *)cellIdentifier
{
    UITableViewCell *cell;
    if (cellIdentifier) {
        cell = [self.prototypeCells objectForKey:cellIdentifier];
        if (!cell) {
            if (!self.prototypeCells) {
                self.prototypeCells = [[NSMutableDictionary alloc] init];
            }
            cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
            //TODO this will fail if multiple tables are being used and they have
            //overlapping identifiers. The key needs to be unique to the table
            [self.prototypeCells setObject:cell forKey:cellIdentifier];
        }
    }
    return cell;
}

Это использует протокол TLDynamicSizeView , который любая клетка может осуществить, чтобы иметь, это - высота, вычисленная автоматически. Вот работа проект в качестве примера. Внедрение клетки протокола похоже на это:

@implementation DynamicHeightCell

- (void)awakeFromNib
{
    [super awakeFromNib];
    self.originalSize = self.bounds.size;
    self.originalLabelSize = self.label.bounds.size;
}

- (void)configureWithText:(NSString *)text
{
    self.label.text = text;
    [self.label sizeToFit];
}

#pragma mark - TLDynamicSizeView

- (CGSize)sizeWithData:(id)data
{
    [self configureWithText:data];
    //the dynamic size is calculated by taking the original size and incrementing
    //by the change in the label's size after configuring
    CGSize labelSize = self.label.bounds.size;
    CGSize size = self.originalSize;
    size.width += labelSize.width - self.originalLabelSize.width;
    size.height += labelSize.height - self.originalLabelSize.height;
    return size;
}

@end
0
добавлено

Было бы легко, если я мог бы подвергнуть сомнению клетку во время heightForRowAtIndexPath, но это вызывает бесконечный цикл и катастрофу, как этот метод называют перед любой клеткой даже создаются. Какие-либо другие решения?

Вы можете. Я предположил бы, что вы пытаетесь звонить cellForRowAtIndexPath , который вызовет бесконечный цикл. Но необходимо скорее быть dequeuing, клетка непосредственно, звоня dequeueReusableCellWithIdentifier .

Посмотрите делегат табличного представления внедрение из TLIndexPathTools. heightForRowAtIndexPath метод похож на это:

( РЕДАКТИРУЮТ , Первоначально забыл включать метод prototypeForCellIdentifier что на самом деле dequeues клетка.)

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    id item = [self.dataModel itemAtIndexPath:indexPath];
    NSString *cellId = [self cellIdentifierAtIndexPath:indexPath];
    if (cellId) {
        UITableViewCell *cell = [self prototypeForCellIdentifier:cellId];
        if ([cell conformsToProtocol:@protocol(TLDynamicSizeView)]) {
            id v = (id)cell;
            id data;
            if ([item isKindOfClass:[TLIndexPathItem class]]) {
                TLIndexPathItem *i = (TLIndexPathItem *)item;
                data = i.data;
            } else {
                data = item;
            }
            CGSize computedSize = [v sizeWithData:data];
            return computedSize.height;
        } else {
            return cell.bounds.size.height;
        }
    }

    return 44.0;
}

- (UITableViewCell *)tableView:(UITableView *)tableView prototypeForCellIdentifier:(NSString *)cellIdentifier
{
    UITableViewCell *cell;
    if (cellIdentifier) {
        cell = [self.prototypeCells objectForKey:cellIdentifier];
        if (!cell) {
            if (!self.prototypeCells) {
                self.prototypeCells = [[NSMutableDictionary alloc] init];
            }
            cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
            //TODO this will fail if multiple tables are being used and they have
            //overlapping identifiers. The key needs to be unique to the table
            [self.prototypeCells setObject:cell forKey:cellIdentifier];
        }
    }
    return cell;
}

Это использует протокол TLDynamicSizeView , который любая клетка может осуществить, чтобы иметь, это - высота, вычисленная автоматически. Вот работа проект в качестве примера. Внедрение клетки протокола похоже на это:

@implementation DynamicHeightCell

- (void)awakeFromNib
{
    [super awakeFromNib];
    self.originalSize = self.bounds.size;
    self.originalLabelSize = self.label.bounds.size;
}

- (void)configureWithText:(NSString *)text
{
    self.label.text = text;
    [self.label sizeToFit];
}

#pragma mark - TLDynamicSizeView

- (CGSize)sizeWithData:(id)data
{
    [self configureWithText:data];
    //the dynamic size is calculated by taking the original size and incrementing
    //by the change in the label's size after configuring
    CGSize labelSize = self.label.bounds.size;
    CGSize size = self.originalSize;
    size.width += labelSize.width - self.originalLabelSize.width;
    size.height += labelSize.height - self.originalLabelSize.height;
    return size;
}

@end
0
добавлено

Было бы легко, если я мог бы подвергнуть сомнению клетку во время heightForRowAtIndexPath, но это вызывает бесконечный цикл и катастрофу, как этот метод называют перед любой клеткой даже создаются. Какие-либо другие решения?

Вы можете. Я предположил бы, что вы пытаетесь звонить cellForRowAtIndexPath , который вызовет бесконечный цикл. Но необходимо скорее быть dequeuing, клетка непосредственно, звоня dequeueReusableCellWithIdentifier .

Посмотрите делегат табличного представления внедрение из TLIndexPathTools. heightForRowAtIndexPath метод похож на это:

( РЕДАКТИРУЮТ , Первоначально забыл включать метод prototypeForCellIdentifier что на самом деле dequeues клетка.)

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    id item = [self.dataModel itemAtIndexPath:indexPath];
    NSString *cellId = [self cellIdentifierAtIndexPath:indexPath];
    if (cellId) {
        UITableViewCell *cell = [self prototypeForCellIdentifier:cellId];
        if ([cell conformsToProtocol:@protocol(TLDynamicSizeView)]) {
            id v = (id)cell;
            id data;
            if ([item isKindOfClass:[TLIndexPathItem class]]) {
                TLIndexPathItem *i = (TLIndexPathItem *)item;
                data = i.data;
            } else {
                data = item;
            }
            CGSize computedSize = [v sizeWithData:data];
            return computedSize.height;
        } else {
            return cell.bounds.size.height;
        }
    }

    return 44.0;
}

- (UITableViewCell *)tableView:(UITableView *)tableView prototypeForCellIdentifier:(NSString *)cellIdentifier
{
    UITableViewCell *cell;
    if (cellIdentifier) {
        cell = [self.prototypeCells objectForKey:cellIdentifier];
        if (!cell) {
            if (!self.prototypeCells) {
                self.prototypeCells = [[NSMutableDictionary alloc] init];
            }
            cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
            //TODO this will fail if multiple tables are being used and they have
            //overlapping identifiers. The key needs to be unique to the table
            [self.prototypeCells setObject:cell forKey:cellIdentifier];
        }
    }
    return cell;
}

Это использует протокол TLDynamicSizeView , который любая клетка может осуществить, чтобы иметь, это - высота, вычисленная автоматически. Вот работа проект в качестве примера. Внедрение клетки протокола похоже на это:

@implementation DynamicHeightCell

- (void)awakeFromNib
{
    [super awakeFromNib];
    self.originalSize = self.bounds.size;
    self.originalLabelSize = self.label.bounds.size;
}

- (void)configureWithText:(NSString *)text
{
    self.label.text = text;
    [self.label sizeToFit];
}

#pragma mark - TLDynamicSizeView

- (CGSize)sizeWithData:(id)data
{
    [self configureWithText:data];
    //the dynamic size is calculated by taking the original size and incrementing
    //by the change in the label's size after configuring
    CGSize labelSize = self.label.bounds.size;
    CGSize size = self.originalSize;
    size.width += labelSize.width - self.originalLabelSize.width;
    size.height += labelSize.height - self.originalLabelSize.height;
    return size;
}

@end
0
добавлено

Мне была нужна динамическая ширина ячеек табличного представления на основе суммы текста, который будет показан в той клетке. Я решил его таким образом:

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        if (!isLoading)
        {

            if ([self.conditionsDataArray count]>0)
            {
                Conditions *condition =[self.conditionsDataArray objectAtIndex:indexPath.row];

                int height;

                UITextView *textview = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 236, 0)];   //you can set your frame according to your need

                textview.text  = condition.comment;

                textview.autoresizingMask = UIViewAutoresizingFlexibleHeight;

                [tableView addSubview:textview];

                textview.hidden = YES;

                height = textview.contentSize.height;

                NSLog(@"TEXT VIEW HEIGHT %f", textview.contentSize.height);

                [textview removeFromSuperview];

                [textview release];

                return height;
       }

       return 55;  //Default height, if data is in loading state
}

Заметьте, что текстовое Представление было добавлено как Подпредставление и затем сделано скрытое, поэтому удостоверьтесь, что вы добавляете его как SubView иначе, это - высота, не будет рассмотрен.

0
добавлено

Мне была нужна динамическая ширина ячеек табличного представления на основе суммы текста, который будет показан в той клетке. Я решил его таким образом:

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        if (!isLoading)
        {

            if ([self.conditionsDataArray count]>0)
            {
                Conditions *condition =[self.conditionsDataArray objectAtIndex:indexPath.row];

                int height;

                UITextView *textview = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 236, 0)];   //you can set your frame according to your need

                textview.text  = condition.comment;

                textview.autoresizingMask = UIViewAutoresizingFlexibleHeight;

                [tableView addSubview:textview];

                textview.hidden = YES;

                height = textview.contentSize.height;

                NSLog(@"TEXT VIEW HEIGHT %f", textview.contentSize.height);

                [textview removeFromSuperview];

                [textview release];

                return height;
       }

       return 55;  //Default height, if data is in loading state
}

Заметьте, что текстовое Представление было добавлено как Подпредставление и затем сделано скрытое, поэтому удостоверьтесь, что вы добавляете его как SubView иначе, это - высота, не будет рассмотрен.

0
добавлено

Мне была нужна динамическая ширина ячеек табличного представления на основе суммы текста, который будет показан в той клетке. Я решил его таким образом:

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        if (!isLoading)
        {

            if ([self.conditionsDataArray count]>0)
            {
                Conditions *condition =[self.conditionsDataArray objectAtIndex:indexPath.row];

                int height;

                UITextView *textview = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 236, 0)];   //you can set your frame according to your need

                textview.text  = condition.comment;

                textview.autoresizingMask = UIViewAutoresizingFlexibleHeight;

                [tableView addSubview:textview];

                textview.hidden = YES;

                height = textview.contentSize.height;

                NSLog(@"TEXT VIEW HEIGHT %f", textview.contentSize.height);

                [textview removeFromSuperview];

                [textview release];

                return height;
       }

       return 55;  //Default height, if data is in loading state
}

Заметьте, что текстовое Представление было добавлено как Подпредставление и затем сделано скрытое, поэтому удостоверьтесь, что вы добавляете его как SubView иначе, это - высота, не будет рассмотрен.

0
добавлено
Mobile Dev Jobs — вакансии и аналитика
Mobile Dev Jobs — вакансии и аналитика
6 187 участник(ов)

Публикуем вакансии и запросы на поиск работы по направлению iOS, Android, Xamarin и т.д. ВАЖНО: Правила публикации и правила канала: Ссылка – https://telegra.ph/Pravila-oformleniya-vakansij-i-rezyume-11-09-2

iOS Developers — русскоговорящее сообщество
iOS Developers — русскоговорящее сообщество
2 400 участник(ов)

Общаемся на темы, посвященным iOS-разработке, Swift, Objective-C, SDK, Rx, Cocoa и т.д.