Есть ли способ обновить высоту ячейки без перезагрузки/перезагрузки?
Я делаю вид как imessage, просто ввод текста в нижний текстовый вид. Для этого я использую представление таблицы и текстовое представление в последней ячейке. когда я вводя длинный текст, который содержит более одной строки, мне нужен текстовый вид, а ячейка станет портной. поэтому мне нужно обновить высоту ячейки. но если я использую перезагрузку или перезагрузку таблицы, содержимое в текстовом представлении исчезнет, и клавиатура тоже исчезнет. Есть ли способ лучше исправить это?
Может быть, я должен использовать панель инструментов, чтобы сделать это легко? но я все еще сомневаюсь, что это может сделать табличный вид.
Ответы
Ответ 1
Ячейки будут плавно изменяться, когда вы вызываете beginUpdates
и endUpdates
. После этих вызовов tableView отправит tableView:heightForRowAtIndexPath:
для всех ячеек в таблице, когда tableView получит все высоты для всех ячеек, они оживят изменение размера.
И вы можете обновлять ячейки, не перезагружая их, напрямую устанавливая свойства ячейки. Нет необходимости привлекать tableView и tableView:cellForRowAtIndexPath:
Чтобы изменить размер ячеек, вы должны использовать код, похожий на этот
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
NSString *newText = [textView.text stringByReplacingCharactersInRange:range withString:text];
CGSize size = // calculate size of new text
if ((NSInteger)size.height != (NSInteger)[self tableView:nil heightForRowAtIndexPath:nil]) {
// if new size is different to old size resize cells.
// since beginUpdate/endUpdates calls tableView:heightForRowAtIndexPath: for all cells in the table this should only be done when really necessary.
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
return YES;
}
чтобы изменить содержимое ячейки без перезагрузки, я использую что-то вроде этого:
- (void)configureCell:(FancyCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
MyFancyObject *object = ...
cell.textView.text = object.text;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
FancyCell *cell = (FancyCell *)[tableView dequeueReusableCellWithIdentifier:@"CellWithTextView"];
[self configureCell:cell forRowAtIndexPath:indexPath];
return cell;
}
// whenever you want to change the cell content use something like this:
NSIndexPath *indexPath = ...
FancyCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
[self configureCell:cell forRowAtIndexPath:indexPath];
Ответ 2
Я написал подкласс UITableViewCell для обработки этой функции.
.h файл:
#import <UIKit/UIKit.h>
@protocol AECELLSizeableDelegate;
@interface AECELLSizeable : UITableViewCell
@property (weak, nonatomic) id <AECELLSizeableDelegate> delegate;
@property IBOutlet UIView *viewMinimized;
@property IBOutlet UIView *viewMaximized;
@property BOOL maximized;
@property CGFloat height;
- (IBAction)clickedConfirm:(id)sender;
- (IBAction)clickedCancel:(id)sender;
- (void)minimizeForTableview: (UITableView*)tableView;
- (void)maximizeForTableview: (UITableView*)tableView;
- (void)toggleForTableview: (UITableView*)tableView;
@end
@protocol AECELLSizeableDelegate <NSObject>
- (void)sizeableCellConfirmedForCell: (AECELLSizeable*)cell;
- (void)sizeableCellCancelledForCell: (AECELLSizeable*)cell;
@end
.m file:
#import "AECELLSizeable.h"
@implementation AECELLSizeable
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)minimizeForTableview: (UITableView*)tableView
{
self.maximized = NO;
[self.viewMinimized setHidden:NO];
[self.viewMaximized setHidden:YES];
self.height = self.viewMinimized.frame.size.height;
[tableView beginUpdates];
[tableView endUpdates];
}
- (void)maximizeForTableview: (UITableView*)tableView
{
self.maximized = YES;
[self.viewMinimized setHidden:YES];
[self.viewMaximized setHidden:NO];
self.height = self.viewMaximized.frame.size.height;
[tableView beginUpdates];
[tableView endUpdates];
}
- (void)toggleForTableview:(UITableView *)tableView
{
if (self.maximized) {
[self minimizeForTableview:tableView];
} else {
[self maximizeForTableview:tableView];
}
}
- (void)clickedConfirm:(id)sender
{
[self.delegate sizeableCellConfirmedForCell:self];
}
- (void)clickedCancel:(id)sender
{
[self.delegate sizeableCellCancelledForCell:self];
}
@end
Пример использования:
- Создайте UITableViewController со статическим UITableView в IB
- Добавить ячейку в представление таблицы, которое является AECELLSizeable (или подклассом)
- Создайте два UIView в этой ячейке. Один UIView будет использоваться для видимого содержимого, если он сведен к минимуму, другой будет использоваться для видимого контента, пока он будет максимальным. Убедитесь, что эти ячейки начинаются с 0 по оси y и что их высота равна высоте, которую вы хотите иметь ячейку для каждого состояния.
- Добавьте любые подзаголовки в эти два вида, которые вы хотели. При необходимости добавьте подтверждение и отмените UIButtons на максимальный UIView и подключите предоставленные IBActions для приема обратных вызовов делегатов в этих событиях.
- Установите контроллер табличного представления в соответствие с AECELLSizeableDelegate и установите свойство делегата ячейки контроллеру таблицы.
- Создайте IBOutlet в файле интерфейса UIViewController для ячейки AECELLSizeable.
- Вернитесь в IB, убедитесь, что начальная высота ячейки соответствует минимальной версии и подключается только что созданный IBOutlet.
-
Определите метод обратного вызова heightForRowAtIndexPath tableview в файле реализации контроллера tableview как таковой:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0) {
//Sizeable Cell
return self.cellSizeable.height;
} else {
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
}
-
В вашем методе viewDidLoad контроллера табличного вызова вызовите в своей ячейке minimForTableview, чтобы убедиться, что он начинает сбрасываться.
- Затем вызовите функцию maximizeForTableview: в ячейке, когда она выбрана с помощью обратного вызова didSelectRowAtIndexPath из tableview (или, как бы то ни было, вы бы хотели его обработать), и вызовите метод minimForTableview: в ячейке, когда вы получите отмененный/подтвержденный делегат обратные вызовы из ячейки (или, опять же, как бы вы хотели ее обрабатывать).
Ответ 3
Отметьте эту библиотеку. Это реализация сообщений с использованием UITableView
. Имейте в виду, что каждый раз, когда отображается ячейка, вызывается cellForRow:atIndexPath
и выделена ячейка.
ИЗМЕНИТЬ
Вы можете использовать heightForRowAtIndexPath
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
Messages *message = [self.messageList objectAtIndex:[indexPath row]];
CGSize stringSize = [message.text sizeWithFont:[UIFont fontWithName:@"HelveticaNeue-Light" size:13]
constrainedToSize:CGSizeMake(320, 9999) lineBreakMode:UILineBreakModeWordWrap];
return stringSize.height + 78;
}
Ответ 4
Ячейки просмотра таблицы не будут плавно изменять размер. Dot.
Однако, поскольку ваше текстовое представление находится в последней ячейке, вам повезло, потому что вы можете легко имитировать изменение размера строки. Наличие текстового представления в середине таблицы было бы намного сложнее.
Вот как я это сделаю: поставьте свой текстовый вид поверх представления таблицы. Синхронизируйте свою позицию с содержимымОфис таблицы TableView в scrollViewDidScroll:. И используйте animatable contentInset таблицыView, чтобы оставить место для textView, поскольку пользователь вводит в него. Возможно, вам придется убедиться, что ваш текст не прокручивается.