2013-01-02 16 views
13

Tworzę UITableView z różnymi typami UITableViewCell w zależności od typu wyświetlanej treści. Jeden z to UITableViewCell z wewnątrz UITextView programowo utworzonego w ten sposób:Zwiększenie wysokości komórki widoku osobistego jednocześnie zwiększając wewnętrzną 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; 
    } 
    ... 
} 

Ponieważ widok tekst jest edytowalny komórka, która zawiera powinien zmienić jego wysokość, aby prawidłowo dopasować widoku tekst rozmiarów. Początkowo robiłem to przez zmianę rozmiaru UITextView wewnątrz metody textViewDidChange: w ten sposób:

- (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]; 
} 

zapisać nową wysokość widoku tekstu w zmiennej, a następnie, gdy tableView:heightForRowAtIndexPath: wywoływana jest metoda, zmianie rozmiaru komórkę w ten sposób:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    ... 
    if ([current_field.tipo_campo isEqualToString:@"text_area"]) 
    { 
     return newHeight +10.0f; 
    } 
    else 
    return 44.0f; 
... 
} 

w ten sposób oba są przeskalowane, ale nie odbywa się w synchronizacji, czyli najpierw TextView jest zmieniany, a następnie jest on zmieniany wysokość komórki, więc na chwilę użytkownikowi zobaczyć, że tekst widok jest większy niż komórka. Jak mogę naprawić to złe zachowanie?

+0

Na razie znajduję ścieżkę ustawiającą tło uitextview do clearColor. Jest trasparent i błąd jest niewidoczny. – LuckyStarr

+0

Everytime cellForRow ... zostaje wywołana, alokujesz, inicjalizujesz i dodajesz UITextView jako widok podrzędny. Dlaczego nie wykonać tej konfiguracji tylko raz, tworząc własną podklasę UITableViewCell? Wygląda na to, że sposób, w jaki to robisz spowodowałby problemy w wyniku dodania wielu UITextViews do komórki za każdym razem, gdy ta metoda zostanie wywołana, na przykład po ponownym wczytaniu danych. – ozz

+0

@ cdo zauważyłem ten błąd, więc zmodyfikowałem kod. Jeśli komórka jest zerowa, tworzę UITextView, w przeciwnym razie odzyskuję ją jako wyeksponowanie komórki. – LuckyStarr

Odpowiedz

20

stworzyłem jedną Demo dla twojego problemu, nadzieja ci pomoże.

Mój pomysł na rozwiązanie to: AutoResizingMask z UITextView.

mój plik .h

#import <UIKit/UIKit.h> 

@interface ViewController : UIViewController<UITabBarDelegate, UITableViewDataSource, UITextViewDelegate>{ 
    IBOutlet UITableView *tlbView; 
    float height; 
} 

@end 

A mój plik .m (zawiera tylko niezbędne metody)

- (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; 
} 

nadzieję, że będzie ci pomóc.

+0

To rozwiązanie, które zastosowałem. – LuckyStarr

1

to sprawdzić: UIView Contentmode - grać z wartościami takimi jak:

cell.contentMode = //...// 
+0

Próbowałem z całą wartością, ale mam taki sam wynik. – LuckyStarr

+0

Nie zmieniaj wysokości widoku tekstu, zmieniaj rozmiar komórki tylko za pomocą heightForRowAtIndexPath o dowolnej wysokości losowej. Sprawdź, czy podąża za nim tekst, czy nie. Jeśli tak, zmodyfikuj heightForRowAtIndexPath, aby zmienić wysokość komórki zgodnie z potrzebami. –

+0

Żaden UITextView nie zmienia się. Próbowałem z textView.autoresizingMask = UIViewAutoresizingFlexibleHeight; koniec wydaje się zadziałać: jeśli zmienię wysokość komórki zmieni się również wartość TextView. – LuckyStarr

1
- (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]; 
    } 

} 
4

Aby zmienić rozmiar komórek chcesz użyć kodu podobnego do tego

- (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; 
} 
kod
1

SIBA Prasad Hota prawdopodobnie będzie wykonaj lewę (potrzebujesz odwołania do widoku tabeli z poziomu komórki), ale mam inne, dłuższe podejście. Zawsze robię takie rzeczy w ten sposób, ponieważ lubię rozdzielać wszystkie rzeczy (wzór MVC). If I were you, chciałbym zrobić to jak ten (kod od głowy): protokół nadrzędnego

komórkowy: model

@protocol CellParent <NSObject> 
@required 
@property (nonatomic, strong) UITableView *tableView; 
@end 

komórkowy:

@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 

komórkę

@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; 

z wdrożeń takich jak ten:

(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; 
} 

Kontroler z widoku tabeli

-(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]; 
} 
1

Należy obliczyć newHeight do komórki przed komory ładunkowej. Zamiast obliczania newHeight w textViewDidChange, obliczyć ją w heightForRowAtIndexPath i wrócić sama jak

- (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; 
    } 
} 
2

Ustaw kadr TextView z animacją ..so że synchronizuje z animacją komórki rozbudowy wysokość

1

nie będę przejmować wysokości komórek stosując metodę

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

a raczej dokonaniu pole widzenia tekst delegata i obsługiwać następujące zdarzenie w sposób pokazany poniżej:

- (void) textFieldDidResize:(id)sender 
{ 
      [self.tableView beginUpdates]; 
      [self.tableView endUpdates]; 
} 

Również upewnić się, że Wykonałeś następujące czynności:

yourInputField.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 

Jedną z rzeczy, których potrzebujesz, jest zmiana rozmiaru twoje pole tekstowe. Twoje komórki w widoku tabeli przyjmą rozmiar wewnętrznego pola tekstowego. Po prostu dodaj go jako subview do cell.contentView.

Powiązane problemy