UITableViewCell z wysokością UITextView w iOS 7?

Jak mogę obliczyć wysokość UITableViewCell z UITextView w iOS 7?

Znalazłem wiele odpowiedzi na podobne pytania, ale sizeWithFont: bierze udział w każdym rozwiązaniu i ta metoda jest przestarzała!

Wiem, że muszę użyć - (CGFloat)tableView:heightForRowAtIndexPath: ale jak obliczyć wysokość, którą mój widok TextView musi wyświetlić cały tekst?

Author: MyJBMe, 2013-08-22

12 answers

Po pierwsze, bardzo ważne jest, aby zauważyć, że istnieje duża różnica między UITextView i UILabel, jeśli chodzi o sposób renderowania tekstu. Nie tylko UITextView ma wstawki na wszystkich obramowaniach, ale także układ tekstu wewnątrz niego jest nieco inny.

Dlatego {[10] } jest złym sposobem na uitextviews.

Zamiast UITextView ma funkcję o nazwie sizeThatFits:, która zwróci najmniejszy rozmiar potrzebny do wyświetlenia całej zawartości UITextView wewnątrz obwiedni, które możesz określić.

Poniżej będzie działać tak samo zarówno dla iOS 7, jak i starszych wersji i od tej chwili nie zawiera żadnych metod, które są przestarzałe.


Proste Rozwiązanie

- (CGFloat)textViewHeightForAttributedText: (NSAttributedString*)text andWidth: (CGFloat)width {
    UITextView *calculationView = [[UITextView alloc] init];
    [calculationView setAttributedText:text];
    CGSize size = [calculationView sizeThatFits:CGSizeMake(width, FLT_MAX)];
    return size.height;
}

Funkcja ta przyjmuje NSAttributedString i żądaną szerokość jako CGFloat i zwraca wymaganą wysokość


Szczegółowe Rozwiązanie

Ponieważ ostatnio zrobiłem coś podobnego, pomyślałem, że podzielę się również niektórymi rozwiązaniami dla connected Problemy, które napotkałem. Mam nadzieję, że to komuś pomoże.

Jest to o wiele bardziej dogłębne i obejmie następujące zagadnienia:]}
  • oczywiście: ustawienie wysokości UITableViewCell na podstawie rozmiaru potrzebnego do wyświetlenia pełnej zawartości zawartej UITextView
  • [57]}reaguj na zmiany tekstu (i Animuj zmiany wysokości wiersza)
  • trzymanie kursora wewnątrz widocznego obszaru i utrzymywanie pierwszej odpowiedzi na UITextView podczas zmiany rozmiaru UITableViewCell podczas edycja

jeśli pracujesz ze statycznym widokiem tabeli lub masz tylko znaną liczbę UITextView s, potencjalnie możesz znacznie uprościć Krok 2.

1. Po pierwsze, zastąp ścieżkę heightForRowAtIndexPath:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    // check here, if it is one of the cells, that needs to be resized
    // to the size of the contained UITextView
    if (  )             
        return [self textViewHeightForRowAtIndexPath:indexPath];
    else
    // return your normal height here:
            return 100.0;           
}

2. Zdefiniuj funkcję, która obliczała wymaganą wysokość:

Dodaj NSMutableDictionary (w tym przykładzie o nazwie textViews) jako zmienną instancji do podklasy UITableViewController.

Użyj tego słownika do przechowywania odniesień do danej osoby UITextViews tak:

W 1999 roku w ramach programu "Horyzont 2020" w ramach programu Horyzont 2020 w ramach programu Horyzont 2020 w ramach programu Horyzont 2020 w ramach programu Horyzont 2020 w ramach programu Horyzont 2020 "Horyzont 2020"]}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    // Do you cell configuring ...

    [textViews setObject:cell.textView forKey:indexPath];
    [cell.textView setDelegate: self]; // Needed for step 3

    return cell;
}

Funkcja obliczy teraz rzeczywistą wysokość:

- (CGFloat)textViewHeightForRowAtIndexPath: (NSIndexPath*)indexPath {
    UITextView *calculationView = [textViews objectForKey: indexPath];
    CGFloat textViewWidth = calculationView.frame.size.width;
    if (!calculationView.attributedText) {
        // This will be needed on load, when the text view is not inited yet

        calculationView = [[UITextView alloc] init];
        calculationView.attributedText = // get the text from your datasource add attributes and insert here
        textViewWidth = 290.0; // Insert the width of your UITextViews or include calculations to set it accordingly
    }
    CGSize size = [calculationView sizeThatFits:CGSizeMake(textViewWidth, FLT_MAX)];
    return size.height;
}

3. Włącz zmianę rozmiaru podczas edycji

Dla następnych dwóch funkcji ważne jest, aby delegat UITextViews został ustawiony na Twój UITableViewController. Jeśli potrzebujesz czegoś innego jako delegat, możesz obejść to, wykonując odpowiednie połączenia stamtąd lub używając odpowiedniego NSNotificationCenter haki.

- (void)textViewDidChange:(UITextView *)textView {

    [self.tableView beginUpdates]; // This will cause an animated update of
    [self.tableView endUpdates];   // the height of your UITableViewCell

    // If the UITextView is not automatically resized (e.g. through autolayout 
    // constraints), resize it here

    [self scrollToCursorForTextView:textView]; // OPTIONAL: Follow cursor
}

4. Śledź kursor podczas edycji

- (void)textViewDidBeginEditing:(UITextView *)textView {
    [self scrollToCursorForTextView:textView];
}

Spowoduje to przewinięcie UITableView do pozycji kursora, jeśli nie znajduje się on wewnątrz widocznego Rect widoku UITableView:

- (void)scrollToCursorForTextView: (UITextView*)textView {

    CGRect cursorRect = [textView caretRectForPosition:textView.selectedTextRange.start];

    cursorRect = [self.tableView convertRect:cursorRect fromView:textView];

    if (![self rectVisible:cursorRect]) {
        cursorRect.size.height += 8; // To add some space underneath the cursor
        [self.tableView scrollRectToVisible:cursorRect animated:YES];
    }
}

5. Dopasuj widoczne rect, ustawiając wstawki

Podczas edycji, części twojego UITableView mogą być zasłonięte przez klawiaturę. Jeśli wstawki tableviews nie są dostosowane, scrollToCursorForTextView: nie będzie można przewijać kursora, jeśli znajduje się on na dole ekranu tableview.

- (void)keyboardWillShow:(NSNotification*)aNotification {
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(self.tableView.contentInset.top, 0.0, kbSize.height, 0.0);
    self.tableView.contentInset = contentInsets;
    self.tableView.scrollIndicatorInsets = contentInsets;
}

- (void)keyboardWillHide:(NSNotification*)aNotification {
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:0.35];
    UIEdgeInsets contentInsets = UIEdgeInsetsMake(self.tableView.contentInset.top, 0.0, 0.0, 0.0);
    self.tableView.contentInset = contentInsets;
    self.tableView.scrollIndicatorInsets = contentInsets;
    [UIView commitAnimations];
}

I ostatnia część:

Wewnątrz widoku się załadował, zapisz się na powiadomienia o zmianach klawiatury przez NSNotificationCenter:

- (void)viewDidLoad
{
    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}

Proszę, nie złość się na mnie, że tak długo odpowiadam. Chociaż nie wszystko jest potrzebne, aby odpowiedzieć na to pytanie, wierzę, że są inni ludzie, którym te bezpośrednio związane kwestie będą pomocne.


Aktualizacja:

Jak zauważył Dave Haupert, zapomniałem dodać rectVisible funkcja:

- (BOOL)rectVisible: (CGRect)rect {
    CGRect visibleRect;
    visibleRect.origin = self.tableView.contentOffset;
    visibleRect.origin.y += self.tableView.contentInset.top;
    visibleRect.size = self.tableView.bounds.size;
    visibleRect.size.height -= self.tableView.contentInset.top + self.tableView.contentInset.bottom;

    return CGRectContainsRect(visibleRect, rect);
}

zauwaĺźyĺ 'em rĂłwnieĹź, Ĺźe scrollToCursorForTextView: wciÄ ... Ĺź zawiera bezpoĹ" rednie odniesienie do jednego z Textfieldăłw w moim projekcie. Jeśli masz problem z nie odnalezieniem bodyTextView, sprawdź zaktualizowaną wersję funkcji.

 423
Author: Tim Bodeit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:30

Istnieje nowa funkcja do zastąpienia sizeWithFont, która jest boundingRectWithSize.

Dodałem do mojego projektu następującą funkcję, która wykorzystuje nową funkcję na iOS7 i starą na iOS niższą niż 7. Ma zasadniczo taką samą składnię jak sizeWithFont:

    -(CGSize)text:(NSString*)text sizeWithFont:(UIFont*)font constrainedToSize:(CGSize)size{
        if(IOS_NEWER_OR_EQUAL_TO_7){
            NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                              font, NSFontAttributeName,
                                              nil];

            CGRect frame = [text boundingRectWithSize:size
                                              options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
                                           attributes:attributesDictionary
                                              context:nil];

            return frame.size;
        }else{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
            return [text sizeWithFont:font constrainedToSize:size];
#pragma clang diagnostic pop
        }
    }

Możesz dodać, że IOS_NEWER_OR_EQUAL_TO_7 na swoim prefiksie.plik pch w Twoim projekcie jako:

#define IOS_NEWER_OR_EQUAL_TO_7 ( [ [ [ UIDevice currentDevice ] systemVersion ] floatValue ] >= 7.0 )
 37
Author: manecosta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-21 08:20:55

Jeśli używasz UITableViewAutomaticDimension mam naprawdę proste (tylko iOS 8) rozwiązanie. W moim przypadku jest to statyczny widok tabeli, ale myślę, że można to dostosować do dynamicznych prototypów...

Mam ograniczenie wysokości widoku tekstu i zaimplementowałem następujące metody:

// Outlets

@property (weak, nonatomic) IBOutlet UITextView *textView;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *textViewHeight;


// Implementation

#pragma mark - Private Methods

- (void)updateTextViewHeight {
    self.textViewHeight.constant = self.textView.contentSize.height + self.textView.contentInset.top + self.textView.contentInset.bottom;
}

#pragma mark - View Controller Overrides

- (void)viewDidLoad {
    [super viewDidLoad];
    [self updateTextViewHeight];
}

#pragma mark - TableView Delegate & Datasource

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

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

#pragma mark - TextViewDelegate

- (void)textViewDidChange:(UITextView *)textView {
    [self.tableView beginUpdates];
    [self updateTextViewHeight];
    [self.tableView endUpdates];
}

Ale pamiętaj: widok tekstowy musi być przewijalny i musisz skonfigurować swoje ograniczenia tak, aby działały dla automatycznego wymiaru:

  • konfiguracja wszystkie widoki w komórce względem siebie, ze stałymi wysokościami (w tym wysokość widoku tekstowego, którą zmienisz programowo)
  • widok top most ma odstęp górny, a Widok bottom most ma odstęp dolny do Super widoku;

Najbardziej podstawowy przykład komórki To:

  • brak innych widoków w komórce poza textview
  • 0 marginesy wokół wszystkich stron widoku tekstowego i predefiniowane ograniczenie wysokości dla widoku tekstowego.
 9
Author: dec-vt100,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-08 12:11:04

Odpowiedź Tima Bodeita jest świetna. Użyłem kodu prostego rozwiązania, aby poprawnie uzyskać wysokość widoku tekstowego i użyć tej wysokości w heightForRowAtIndexPath. Ale nie używam reszty odpowiedzi do zmiany rozmiaru widoku tekstu. Zamiast tego piszę kod, aby zmienić frame widoku tekstowego w cellForRowAtIndexPath.

Wszystko działa w iOS 6 i poniżej, ale w iOS 7 tekst w widoku tekstowym nie może być w pełni pokazany, nawet jeśli frame widoku tekstowego jest rzeczywiście zmieniony rozmiar. (Nie używam Auto Layout). Powinno być powodem, że w iOS 7 jest TextKit, a pozycja tekstu jest kontrolowana przez NSTextContainer w UITextView. Tak więc w moim przypadku muszę dodać linię, aby ustawić someTextView, aby działało poprawnie w iOS 7.

    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
        someTextView.textContainer.heightTracksTextView = YES;
    }

Jak mówi dokumentacja, to co ta właściwość robi to:

Kontroluje, czy odbiornik dostosowuje wysokość obwiedni prostokąt po zmianie rozmiaru widoku tekstowego. Wartość domyślna: nie.

Jeśli pozostawisz go z wartością domyślną, po zmianie rozmiaru frame z someTextView, Rozmiar textContainer nie ulega zmianie, co prowadzi do tego, że tekst może być wyświetlany tylko w obszarze przed zmianą rozmiaru.

I być może konieczne jest ustawienie scrollEnabled = NO W przypadku, gdy jest więcej niż jeden textContainer, aby tekst zmieniał się z jednego textContainer do drugiego.

 5
Author: PowerQian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-30 07:46:08

Oto jeszcze jedno rozwiązanie, które ma na celu prostotę i szybkie prototypowanie :

Setup:

  1. Tabela z prototypowymi komórkami.
  2. każda komórka zawiera dynamiczny Rozmiar UITextView w / inne treści.
  3. komórki prototypowe są związane z TableCell.h.
  4. UITableView jest związane z TableViewController.h.

Rozwiązanie:

(1) Dodaj do TableViewController.m:

 // This is the method that determines the height of each cell.  
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    // I am using a helper method here to get the text at a given cell.
    NSString *text = [self getTextAtIndex:indexPath];

    // Getting the height needed by the dynamic text view.
    CGSize size = [self frameForText:text sizeWithFont:nil constrainedToSize:CGSizeMake(300.f, CGFLOAT_MAX)];

    // Return the size of the current row.
    // 80 is the minimum height! Update accordingly - or else, cells are going to be too thin.
    return size.height + 80; 
}

// Think of this as some utility function that given text, calculates how much 
// space would be needed to fit that text.
- (CGSize)frameForText:(NSString *)text sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size
{
    NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                          font, NSFontAttributeName,
                                          nil];
    CGRect frame = [text boundingRectWithSize:size
                                      options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
                                   attributes:attributesDictionary
                                      context:nil];

    // This contains both height and width, but we really care about height.
    return frame.size;
}

// Think of this as a source for the text to be rendered in the text view. 
// I used a dictionary to map indexPath to some dynamically fetched text.
- (NSString *) getTextAtIndex: (NSIndexPath *) indexPath
{
    return @"This is stubbed text - update it to return the text of the text view.";
}

(2) Dodaj do TableCell.m:

// This method will be called when the cell is initialized from the storyboard
// prototype. 
- (void)awakeFromNib
{
    // Assuming TextView here is the text view in the cell. 
    TextView.scrollEnabled = YES;
}

Explanation:

Dzieje się tak: każdy widok tekstowy jest związany z wysokością komórek tabeli za pomocą ograniczeń pionowych i poziomych - oznacza to, że gdy zwiększa się wysokość komórki tabeli, widok tekstowy również zwiększa swój rozmiar. Użyłem zmodyfikowanej wersji kodu @ manecosta, aby obliczyć wymaganą wysokość widoku tekstowego, aby zmieścić dany tekst w komórce. Oznacza to, że jeśli dany tekst ma X liczbę znaków, frameForText: zwróci rozmiar który będzie miał właściwość size.height, która odpowiada wymaganej wysokości widoku tekstowego.

Teraz pozostaje tylko uaktualnić wysokość komórki, aby dopasować wysokość wymaganego widoku tekstowego. I osiąga się to przy heightForRowAtIndexPath:. Jak wspomniano w komentarzach, ponieważ size.height jest tylko wysokością widoku tekstu, a nie całej komórki, powinno być do niej dodane przesunięcie. W przypadku przykładu wartość ta wynosiła 80.

 4
Author: Zorayr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-20 17:39:46

Jedną z metod, jeśli używasz autolayout, jest pozwolić silnikowi autolayout obliczyć rozmiar dla Ciebie. Nie jest to najskuteczniejsze podejście, ale jest całkiem wygodne (i prawdopodobnie najdokładniejsze). Staje się to wygodniejsze wraz ze wzrostem złożoności układu komórki - np. nagle masz dwa lub więcej widoków/pól tekstowych w komórce.

Odpowiedziałem na podobne pytanie z pełną próbką rozmiaru komórek tableview za pomocą automatycznego układu, tutaj:

Jak zmienić rozmiar superview, aby dopasować wszystkie podview z autolayout?

 3
Author: TomSwift,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:21

Kompletne rozwiązanie gładkie jest następujące.

Najpierw potrzebujemy klasy komórki z textView

@protocol TextInputTableViewCellDelegate <NSObject>
@optional
- (void)textInputTableViewCellTextWillChange:(TextInputTableViewCell *)cell;
- (void)textInputTableViewCellTextDidChange:(TextInputTableViewCell *)cell;
@end

@interface TextInputTableViewCell : UITableViewCell
@property (nonatomic, weak) id<TextInputTableViewCellDelegate> delegate;
@property (nonatomic, readonly) UITextView *textView;
@property (nonatomic) NSInteger minLines;
@property (nonatomic) CGFloat lastRelativeFrameOriginY;
@end


#import "TextInputTableViewCell.h"

@interface TextInputTableViewCell () <UITextViewDelegate> {
    NSLayoutConstraint *_heightConstraint;
}
@property (nonatomic) UITextView *textView;
@end

@implementation TextInputTableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        self.selectionStyle = UITableViewCellSelectionStyleNone;

        _textView = [UITextView new];
        _textView.translatesAutoresizingMaskIntoConstraints = NO;
        _textView.delegate = self;
        _textView.scrollEnabled = NO;
        _textView.font = CELL_REG_FONT;
        _textView.textContainer.lineFragmentPadding = 0.0;
        _textView.textContainerInset = UIEdgeInsetsZero;
        [self.contentView addSubview:_textView];

        [self.contentView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[view]-|" options:nil metrics:nil views:@{@"view": _textView}]];
        [self.contentView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[view]-|" options:nil metrics:nil views:@{@"view": _textView}]];

        _heightConstraint = [NSLayoutConstraint constraintWithItem: _textView
                         attribute: NSLayoutAttributeHeight
                         relatedBy: NSLayoutRelationGreaterThanOrEqual
                         toItem: nil
                         attribute: NSLayoutAttributeNotAnAttribute
                         multiplier: 0.0
                         constant: (_textView.font.lineHeight + 15)];
        _heightConstraint.priority = UILayoutPriorityRequired - 1;
        [_textView addConstraint:_heightConstraint];
    }
    return self;
}

- (void)prepareForReuse {
    [super prepareForReuse];    
    self.minLines = 1;
}

- (void)setMinLines:(NSInteger)minLines {
    _heightConstraint.constant = minLines * _textView.font.lineHeight + 15;
}

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    if ([self.delegate respondsToSelector:@selector(textInputTableViewCellTextWillChange:)]) {
        [self.delegate textInputTableViewCellTextWillChange:self];
    }
    return YES;
}

- (void)textViewDidChange:(UITextView *)textView {
    if ([self.delegate respondsToSelector:@selector(textInputTableViewCellTextDidChange:)]) {
        [self.delegate textInputTableViewCellTextDidChange:self];
    }
}

Następnie używamy go w TableViewController

@interface SomeTableViewController () <TextInputTableViewCellDelegate>
@end

@implementation SomeTableViewController

. . . . . . . . . . . . . . . . . . . .

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    TextInputTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: TextInputTableViewCellIdentifier forIndexPath:indexPath];
    cell.delegate = self;
    cell.minLines = 3;
    . . . . . . . . . .  
    return cell;
}

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

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

- (void)textInputTableViewCellWillChange:(TextInputTableViewCell *)cell {
    cell.lastRelativeFrameOriginY = cell.frame.origin.y - self.tableView.contentOffset.y;
}

- (void)textInputTableViewCellTextDidChange:(TextInputTableViewCell *)cell {
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];

    [UIView performWithoutAnimation:^{
        [self.tableView moveRowAtIndexPath:indexPath toIndexPath:indexPath];
    }];

    CGFloat contentOffsetY = cell.frame.origin.y - cell.lastRelativeFrameOriginY;
    self.tableView.contentOffset = CGPointMake(self.tableView.contentOffset.x, contentOffsetY);

    CGRect caretRect = [cell.textView caretRectForPosition:cell.textView.selectedTextRange.start];
    caretRect = [self.tableView convertRect:caretRect fromView:cell.textView];

    CGRect visibleRect = self.tableView.bounds;
    visibleRect.origin.y += self.tableView.contentInset.top;
    visibleRect.size.height -= self.tableView.contentInset.top + self.tableView.contentInset.bottom;
    BOOL res = CGRectContainsRect(visibleRect, caretRect);
    if (!res) {
        caretRect.size.height += 5;
        [self.tableView scrollRectToVisible:caretRect animated:NO];
    }
}
@end
  • Tutaj minLines pozwala ustawić minimalną wysokość dla textView (do minimalizacja wysokości oporu przez AutoLayout z UITableViewAutomaticDimension).

  • moveRowAtIndexPath:indexPath: z tą samą ścieżką indeksowania rozpoczyna się ponowne obliczanie wysokości i ponowne układanie tableViewCell.

  • performWithoutAnimation: usuwa efekt uboczny (zawartość tableView przesunięcie przeskoku przy rozpoczynaniu nowej linii podczas pisania).

  • Ważne jest, aby zachować relativeFrameOriginY (nie contentOffsetY!) podczas aktualizacji komórek, ponieważ contentSize z komórki przed zmianą bieżącej komórki przez autolayout calculus w nieoczekiwany sposób. Usuwa wizualne skoki przy dzieleniu wyrazów w systemie podczas pisania długich słów.

  • należy pamiętać, że nie należy ustawiać właściwości estimatedRowHeight! The podążanie nie praca

    self.tableView.estimatedRowHeight = UITableViewAutomaticDimension;
    

    użyj tylko metody tableViewDelegate.

==========================================================================

Jeśli nie przeszkadza ci słabe powiązanie pomiędzy tableView i tableViewCell i aktualizacja geometrii tableView z tableViewCell , możliwe jest uaktualnienie klasy TextInputTableViewCell powyżej:

@interface TextInputTableViewCell : UITableViewCell
@property (nonatomic, weak) id<TextInputTableViewCellDelegate> delegate;
@property (nonatomic, weak) UITableView *tableView;
@property (nonatomic, readonly) UITextView *textView;
@property (nonatomic) NSInteger minLines;
@end


#import "TextInputTableViewCell.h"

@interface TextInputTableViewCell () <UITextViewDelegate> {
    NSLayoutConstraint *_heightConstraint;
    CGFloat _lastRelativeFrameOriginY;
}
@property (nonatomic) UITextView *textView;
@end

@implementation TextInputTableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        self.selectionStyle = UITableViewCellSelectionStyleNone;

        _textView = [UITextView new];
        _textView.translatesAutoresizingMaskIntoConstraints = NO;
        _textView.delegate = self;
        _textView.scrollEnabled = NO;
        _textView.font = CELL_REG_FONT;
        _textView.textContainer.lineFragmentPadding = 0.0;
        _textView.textContainerInset = UIEdgeInsetsZero;
        [self.contentView addSubview:_textView];

        [self.contentView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[view]-|" options:nil metrics:nil views:@{@"view": _textView}]];
        [self.contentView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[view]-|" options:nil metrics:nil views:@{@"view": _textView}]];

        _heightConstraint = [NSLayoutConstraint constraintWithItem: _textView
                         attribute: NSLayoutAttributeHeight
                         relatedBy: NSLayoutRelationGreaterThanOrEqual
                         toItem: nil
                         attribute: NSLayoutAttributeNotAnAttribute
                         multiplier: 0.0
                         constant: (_textView.font.lineHeight + 15)];
        _heightConstraint.priority = UILayoutPriorityRequired - 1;
        [_textView addConstraint:_heightConstraint];
    }
    return self;
}

- (void)prepareForReuse {
    [super prepareForReuse];    
    self.minLines = 1;
    self.tableView = nil;
}

- (void)setMinLines:(NSInteger)minLines {
    _heightConstraint.constant = minLines * _textView.font.lineHeight + 15;
}

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {

    _lastRelativeFrameOriginY = self.frame.origin.y - self.tableView.contentOffset.y;
    return YES;
}

- (void)textViewDidChange:(UITextView *)textView {

    NSIndexPath *indexPath = [self.tableView indexPathForCell:self];
    if (indexPath == nil) return;

    [UIView performWithoutAnimation:^{
        [self.tableView moveRowAtIndexPath:indexPath toIndexPath:indexPath];
    }];

    CGFloat contentOffsetY = self.frame.origin.y - _lastRelativeFrameOriginY;
    self.tableView.contentOffset = CGPointMake(self.tableView.contentOffset.x, contentOffsetY);

    CGRect caretRect = [self.textView caretRectForPosition:self.textView.selectedTextRange.start];
    caretRect = [self.tableView convertRect:caretRect fromView:self.textView];

    CGRect visibleRect = self.tableView.bounds;
    visibleRect.origin.y += self.tableView.contentInset.top;
    visibleRect.size.height -= self.tableView.contentInset.top + self.tableView.contentInset.bottom;

    BOOL res = CGRectContainsRect(visibleRect, caretRect);
    if (!res) {
        caretRect.size.height += 5;
        [self.tableView scrollRectToVisible:caretRect animated:NO];
    }
}
@end
 1
Author: malex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-06 01:02:50
  1. Umieść UILabel za UITextView.
  2. Użyj tej odpowiedzi: https://stackoverflow.com/a/36054679/6681462 to UILabel you created
  3. daj im te same ograniczenia i czcionki
  4. Ustaw ten sam tekst;

Wysokość Twojej komórki będzie obliczana na podstawie zawartości UILabel, ale cały tekst będzie wyświetlany przez TextField.

 1
Author: Ильнур Хазиахметов,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-05 10:47:19
UITextView *txtDescLandscape=[[UITextView alloc] initWithFrame:CGRectMake(2,20,310,2)];

    txtDescLandscape.editable =NO;
    txtDescLandscape.textAlignment =UITextAlignmentLeft;
    [txtDescLandscape setFont:[UIFont fontWithName:@"ArialMT" size:15]];
    txtDescLandscape.text =[objImage valueForKey:@"imgdescription"];
    txtDescLandscape.text =[txtDescLandscape.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    [txtDescLandscape sizeToFit];
    [headerView addSubview:txtDescLandscape];

    CGRect txtViewlandscpframe = txtDescLandscape.frame;
    txtViewlandscpframe.size.height = txtDescLandscape.contentSize.height;
    txtDescLandscape.frame = txtViewlandscpframe;

Myślę, że w ten sposób możesz policzyć wysokość widoku tekstowego, a następnie zmienić rozmiar komórki tableview zgodnie z tą wysokością, aby móc wyświetlać pełny tekst w komórce

 0
Author: D-eptdeveloper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-22 12:07:21

Wersja Swift

func textViewHeightForAttributedText(text: NSAttributedString, andWidth width: CGFloat) -> CGFloat {
    let calculationView = UITextView()
    calculationView.attributedText = text
    let size = calculationView.sizeThatFits(CGSize(width: width, height: CGFloat.max))
    return size.height
}
 0
Author: Adam Smaka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-25 09:33:42

Jeśli chcesz automatycznie dopasować wysokość UITableViewCell na podstawie wysokości wewnętrznej wysokości UITextView. Zobacz moją odpowiedź tutaj: https://stackoverflow.com/a/45890087/1245231

Rozwiązanie jest dość proste i powinno działać od iOS 7. Upewnij się, że opcja Scrolling Enabled jest wyłączona dla UITextView wewnątrz UITableViewCell w Storyboardzie.

Następnie w uitableviewcontroller ' s viewDidLoad() Ustaw tableView.rowHeight = UITableViewAutomaticDimension i tableView.estimatedRowHeight > 0 na przykład:

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.estimatedRowHeight = 44.0
}

To jest to. Wysokość UITableViewCell zostanie automatycznie dostosowana w oparciu o wewnętrzną wysokość UITextView.

 0
Author: petrsyn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-28 12:02:49

Dla iOS 8 i nowszych możesz po prostu użyć

your_tablview.estimatedrowheight= minheight chcesz

your_tableview.rowheight=UItableviewautomaticDimension
 -2
Author: Sandy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-15 12:39:04