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?
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 zawartejUITextView
[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 rozmiaruUITableViewCell
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:
- (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.
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 )
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.
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.
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:
- Tabela z prototypowymi komórkami.
- każda komórka zawiera dynamiczny Rozmiar
UITextView
w / inne treści. - komórki prototypowe są związane z
TableCell.h
. -
UITableView
jest związane zTableViewController.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.
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?
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
(niecontentOffsetY
!) 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 pracaself.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
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
- Umieść UILabel za UITextView.
- Użyj tej odpowiedzi: https://stackoverflow.com/a/36054679/6681462 to UILabel you created
- daj im te same ograniczenia i czcionki
- 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.
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
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
}
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
.
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
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