Увеличить высоту uitableviewcell, одновременно увеличивая внутренний UITextView
Я создаю UITableView
с различными типами UITableViewCell
в зависимости от типа отображаемого содержимого. Одним из них является UITableViewCell
с внутри UITextView
, программно созданный таким образом:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
if([current_field.tipo_campo isEqualToString:@"text_area"])
{
NSString *string = current_field.valore;
CGSize stringSize = [string sizeWithFont:[UIFont boldSystemFontOfSize:15] constrainedToSize:CGSizeMake(320, 9999) lineBreakMode:UILineBreakModeWordWrap];
CGFloat height = ([string isEqualToString:@""]) ? 30.0f : stringSize.height+10;
UITextView *textView=[[UITextView alloc] initWithFrame:CGRectMake(5, 5, 290, height)];
textView.font = [UIFont systemFontOfSize:15.0];
textView.text = string;
textView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
textView.textColor=[UIColor blackColor];
textView.delegate = self;
textView.tag = indexPath.section;
[cell.contentView addSubview:textView];
[textView release];
return cell;
}
...
}
Поскольку текстовое представление доступно для редактирования, ячейка, которая содержит его, должна изменить высоту, чтобы правильно соответствовать размерам текстового вида. Первоначально я сделал это, изменив размер UITextView
внутри метода textViewDidChange
:, следующим образом:
- (void)textViewDidChange:(UITextView *)textView
{
NSInteger index = textView.tag;
Field* field = (Field*)[[self sortFields] objectAtIndex:index];
field.valore = textView.text;
[self.tableView beginUpdates];
CGRect frame = textView.frame;
frame.size.height = textView.contentSize.height;
textView.frame = frame;
newHeight = textView.contentSize.height;
[self.tableView endUpdates];
}
Я сохраняю новую высоту текстового представления в переменной, а затем, когда вызывается метод tableView:heightForRowAtIndexPath
:: я изменяю размер ячейки следующим образом:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
if ([current_field.tipo_campo isEqualToString:@"text_area"])
{
return newHeight +10.0f;
}
else
return 44.0f;
...
}
Таким образом, оба размера изменяются, но не выполняются синхронно, т.е. сначала изменяется размер TextView
, а затем изменяется высота ячейки, поэтому на мгновение пользователь видит, что текстовое представление больше, чем клетка. Как я могу исправить это плохое поведение?
Ответы
Ответ 1
Я создал одно демо для вашей проблемы, надеюсь, вам помогут.
В моей идее решения используется AutoResizingMask
of UITextView
.
Мой .h файл
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController<UITabBarDelegate, UITableViewDataSource, UITextViewDelegate>{
IBOutlet UITableView *tlbView;
float height;
}
@end
И мой .m файл (включает только необходимые методы)
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
height = 44.0;
}
- (void)textViewDidChange:(UITextView *)textView{
[tlbView beginUpdates];
height = textView.contentSize.height;
[tlbView endUpdates];
}
#pragma mark - TableView datasource & delegates
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 1;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.row==0) {
if (height>44.0) {
return height + 4.0;
}
}
return 44.0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CellIdentifier"];
UITextView *txtView = [[UITextView alloc] initWithFrame:CGRectMake(0.0, 2.0, 320.0, 40.0)];
[txtView setDelegate:self];
[txtView setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight]; // It will automatically resize TextView as cell resizes.
txtView.backgroundColor = [UIColor yellowColor]; // Just because it is my favourite
[cell.contentView addSubview:txtView];
return cell;
}
Надеюсь, это поможет вам.
Ответ 2
Чтобы изменить размер ячеек, вы должны использовать код, похожий на этот
- (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
CGRect frame = textView.frame;
frame.size.height = textView.contentSize.height;
textView.frame = frame;
if ((NSInteger)size.height != (NSInteger)[self tableView:nil heightForRowAtIndexPath:nil]) {
// if new size is different to old size resize cells.
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
return YES;
}
Ответ 3
Установите рамку TextView с анимацией.. так что она синхронизируется с анимацией ячейки с увеличением высоты
Ответ 4
Проверьте это: UIView Contentmode - играйте со значениями, например:
cell.contentMode = //...//
Ответ 5
- (void)textViewDidChange:(UITextView *)textView
{
UITableViewCell *cell = (UITableViewCell*)textView.superview.superview;
if (cell.frame.size.height < textView.contentSize.height) {
[self.tableView beginUpdates];
CGRect frame = textView.frame;
frame.size.height = textView.contentSize.height;
textView.frame = frame;
CGRect cellFrame = cell.frame;
cellFrame.size.height = textView.frame.size.height;
cell.frame = cellFrame;
[self.tableView endUpdates];
}
}
Ответ 6
Siba Prasad Хоть код, вероятно, будет делать трюк (вам нужна ссылка на представление таблицы с уровня ячейки), но у меня есть другой, более длинный подход. Я всегда делаю такие вещи таким образом, потому что мне нравится разделять все вещи (шаблон MVC).
Если бы я был вами, я бы сделал это так (код из головы):
Протокол родительских ячеек:
@protocol CellParent <NSObject>
@required
@property (nonatomic, strong) UITableView *tableView;
@end
Модель ячейки:
@interface CellModel
@property (nonatomic, assign) BOOL hasTextView;
@property (nonatomic, strong) NSString *textViewContent;
-(float)getCurrentHeightForCell;//implement calculating current height of cell. probably 2 * SOME_MARGIN + height of temporary textView with textViewContent variable
Cell
@interface MyCell
@property (nonatomic, strong) CellModel *dataModel;
@property (nonatomic, weak) id<CellParent> parent;
@property (nonatomic, strong) UITextView *textView;
- (id)initWithStyle:(UITableViewCellStyle)style andModel:(CellModel*) model;
с такими реализациями:
(id)initWithStyle:(UITableViewCellStyle)style andModel:(CellModel*) model
{
self = [super initWithStyle:style reuseIdentifier:@"MyCell"];
if (self)
{
[[NSBundle mainBundle] loadNibNamed:@"MyCell" owner:self options:nil];
self.dataModel = model;
}
return self;
}
-(void) setDataModel:(CellModel *)dataModel
{
_dataModel = dataModel;
if(_dataModel.hasTextView)
{
//show text view
}
else
{
//hide text view
}
//do other cell modifications
}
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
self.dataModel.textViewContent = textView.text;
[self.parent.tableView beginUpdates];
[self.parent.tableView endUpdates];
return YES;
}
Контроллер с табличным представлением
-(UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCell"];
if (cell == nil)
{
cell = [[MyCell alloc] initWithStyle:UITableViewCellStyleDefault andModel: [self.cellsModels objectAtIndex:indexPath.row]];
}
cell.dataModel = [self.cellsModels objectAtIndex:indexPath.row];
cell.parent = self;
return cell;
}
-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [((CellModel*)[self.tableContentArray objectAtIndex:indexPath.row]) getCurrentHeightForCell];
}
Ответ 7
Вы должны рассчитать newHeight для ячейки перед загрузкой ячейки. Вместо вычисления newHeight в textViewDidChange вычислите его в heightForRowAtIndexPath и вернетесь так же, как
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([current_field.tipo_campo isEqualToString:@"text_area"])
{
NSString *string = current_field.valore;
CGSize stringSize = [string sizeWithFont:[UIFont boldSystemFontOfSize:15] constrainedToSize:CGSizeMake(320, 9999) lineBreakMode:UILineBreakModeWordWrap];
CGFloat height = ([string isEqualToString:@""]) ? 30.0f : stringSize.height+10;
return height + 10.0f;
}
else
{
return 44.0f;
}
}
Ответ 8
Я бы не стал беспокоиться о высоте ячеек с помощью метода
(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
а скорее предоставил делегат текстового поля просмотра и обработал следующее событие следующим образом:
- (void) textFieldDidResize:(id)sender
{
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
Также убедитесь, что вы сделали следующее:
yourInputField.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
Тогда вам нужно только изменить размер текстового поля. Ваши ячейки в tableview примут размер внутреннего текстового поля. Просто добавьте его как subview в cell.contentView.