MyJ*_*BMe 121 height cocoa-touch uitableview ios7
如何在iOS 7中使用UITextView计算UITableViewCell的高度?
我在类似的问题上找到了很多答案,但sizeWithFont:
参与了每个解决方案,这个方法已被弃用!
我知道我必须使用- (CGFloat)tableView:heightForRowAtIndexPath:
但是如何计算TextView显示整个文本所需的高度?
Tim*_*eit 428
首先,需要注意的是,UITextView和UILabel在文本呈现方式上存在很大差异.UITextView不仅在所有边框上都有插图,而且其中的文本布局也略有不同.
因此,sizeWithFont:
使用UITextViews是一种不好的方法.
相反,UITextView
它本身有一个函数sizeThatFits:
,它将返回显示UITextView
边界框内部所有内容所需的最小尺寸,您可以指定.
以下内容同样适用于iOS 7及更早版本,并且目前不包含任何已弃用的方法.
- (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;
}
Run Code Online (Sandbox Code Playgroud)
此功能将a NSAttributedString
和所需的宽度作为a CGFloat
并返回所需的高度
由于我最近做了类似的事情,我想我也会分享一些我遇到的连接问题的解决方案.我希望它会对某人有所帮助.
这更深入,将涵盖以下内容:
UITableViewCell
根据显示包含的全部内容所需的大小来设置a的高度UITextView
UITextView
调整的时候UITableViewCell
,同时编辑如果您正在使用静态表视图或只有已知数量的UITextView
s,则可以使步骤2更加简单.
- (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;
}
Run Code Online (Sandbox Code Playgroud)
NSMutableDictionary
在textViews
您的UITableViewController
子类中添加一个(在此示例中称为)实例变量.
使用此字典存储对个人的引用,UITextViews
如下所示:
(是的,indexPaths是字典的有效键)
- (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;
}
Run Code Online (Sandbox Code Playgroud)
此功能现在将计算实际高度:
- (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;
}
Run Code Online (Sandbox Code Playgroud)
对于接下来的两个函数,重要的UITextViews
是,将该委托的代理设置为您的UITableViewController
.如果您需要其他人作为代理,您可以通过从那里进行相关调用或使用适当的NSNotificationCenter挂钩来解决此问题.
- (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
}
Run Code Online (Sandbox Code Playgroud)
- (void)textViewDidBeginEditing:(UITextView *)textView {
[self scrollToCursorForTextView:textView];
}
Run Code Online (Sandbox Code Playgroud)
这将使UITableView
滚动到光标的位置,如果它不在UITableView的可见Rect内:
- (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];
}
}
Run Code Online (Sandbox Code Playgroud)
编辑时,部分UITableView
键盘可能会被覆盖.如果未调整tableviews insets,scrollToCursorForTextView:
则无法滚动到光标,如果它位于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];
}
Run Code Online (Sandbox Code Playgroud)
最后一部分:
您的视图内部确实已加载,请通过以下方式注册键盘更改通知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];
}
Run Code Online (Sandbox Code Playgroud)
正如Dave Haupert指出的那样,我忘了包含这个rectVisible
功能:
- (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);
}
Run Code Online (Sandbox Code Playgroud)
我还注意到,它scrollToCursorForTextView:
仍然包含对我项目中的一个TextField的直接引用.如果您bodyTextView
找不到问题,请检查该功能的更新版本.
man*_*sta 37
有一个新函数可以替换sizeWithFont,它是boundingRectWithSize.
我在我的项目中添加了以下函数,它使用了iOS7上的新函数和iOS 7以下的旧函数.它与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
}
}
Run Code Online (Sandbox Code Playgroud)
您可以在项目的prefix.pch文件中添加IOS_NEWER_OR_EQUAL_TO_7,如下所示:
#define IOS_NEWER_OR_EQUAL_TO_7 ( [ [ [ UIDevice currentDevice ] systemVersion ] floatValue ] >= 7.0 )
Run Code Online (Sandbox Code Playgroud)
如果你正在使用UITableViewAutomaticDimension,我有一个非常简单的(仅限iOS 8)解决方案.在我的情况下,它是一个静态表视图,但我想你可以适应动态原型...
我有一个文本视图高度的约束出口,我已经实现了以下方法:
// 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];
}
Run Code Online (Sandbox Code Playgroud)
但请记住:文本视图必须是可滚动的,您必须设置约束,使它们适用于自动维度:
最基本的单元格示例是:
Tim Bodeit的答案很棒.我使用Simple Solution的代码正确获取文本视图的高度,并使用该高度heightForRowAtIndexPath
.但我不会使用其余的答案来调整文本视图的大小.相反,我编写代码来更改frame
文本视图cellForRowAtIndexPath
.
一切都在iOS 6及更低版本中运行,但在iOS 7中,即使frame
文本视图确实已调整大小,也无法完全显示文本视图中的文本.(我没用Auto Layout
).这应该是在iOS 7中存在的原因,TextKit
并且文本的位置由NSTextContainer
in 控制UITextView
.所以在我的情况下,我需要添加一行来设置someTextView
,以使其在iOS 7中正常工作.
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
someTextView.textContainer.heightTracksTextView = YES;
}
Run Code Online (Sandbox Code Playgroud)
正如文档所说,该财产的作用是:
控制接收器在调整文本视图大小时是否调整其边界矩形的高度.默认值:NO.
如果使用默认值,离开它,之后调整frame
的someTextView
,的大小textContainer
没有改变,导致的结果是,该文本只能调整之前显示在该地区.
也许需要设置scrollEnabled = NO
万一以上textContainer
,以便文本将从一个回流textContainer
到另一个.
归档时间: |
|
查看次数: |
89089 次 |
最近记录: |