有没有办法“准确”限制目标iOS 5.0的UITextView中的行数?
因为我在堆栈溢出中搜索。我之前在下面的链接中发现了这些问题
In UITextView, how to get the point that next input will begin another line
Limit the number of lines for UITextview
Limit number of lines in UITextView
但当我试图决定是否在UITextView
中返回YES或NO时,我仍然无法在textView:shouldChangeTextInRange:replacementText:
中获得准确的行数。
我曾尝试使用代码Limiting text in a UITextView的答案,修改后的代码(在答案中删除-15)显示如下。
- (BOOL)textView:(UITextView *)aTextView shouldChangeTextInRange:(NSRange)aRange replacementText:(NSString*)aText
{
NSString* newText = [aTextView.text stringByReplacingCharactersInRange:aRange withString:aText];
// TODO - find out why the size of the string is smaller than the actual width, so that you get extra, wrapped characters unless you take something off
CGSize tallerSize = CGSizeMake(aTextView.frame.size.width,aTextView.frame.size.height*2); // pretend there's more vertical space to get that extra line to check on
CGSize newSize = [newText sizeWithFont:aTextView.font constrainedToSize:tallerSize lineBreakMode:UILineBreakModeWordWrap];
if (newSize.height > aTextView.frame.size.height)
{
[myAppDelegate beep];
return NO;
}
else
return YES;
}
我也找到了一种方法来获得UITextView
中的行数。方法是按contentSize
属性计算textView.contenSize.height/font.lineHeight
。此方法可以在UITextView
中获得准确的行数。但问题是contentSize
进入textView:shouldChangeTextInRange:replacementText:
而textViewDidChange:
是旧contentSize
。所以我仍然无法限制UITextView中的行数。
这是一种解决方法,但至少它有效。
首先,您需要创建一个与原始UITextView完全相同的临时新UITextView,但将临时UITextView设置为隐藏在.xib文件中。在此示例代码中,我将临时UITextView命名为tempTextInputView
将新的引用插座添加到.h文件中,如
@property (retain, nonatomic) IBOutlet UITextView *tempTextInputView;// Use to calculate the number of lines in UITextView with new text
在下面添加代码。
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
NSString *newText = [textView.text stringByReplacingCharactersInRange:range withString:text];
_tempTextInputView.text = newText;
// Calcualte the number of lines with new text in temporary UITextView
CGRect endRectWithNewText = [_tempTextInputView caretRectForPosition:_tempTextInputView.endOfDocument];
CGRect beginRectWithNewText = [_tempTextInputView caretRectForPosition:_tempTextInputView.beginningOfDocument];
float beginOriginY = beginRectWithNewText.origin.y;
float endOriginY = endRectWithNewText.origin.y;
int numberOfLines = (endOriginY - beginOriginY)/textView.font.lineHeight + 1;
if (numberOfLines > maxLinesInTextView) {// Too many lines
return NO;
}else{// Number of lines will not over the limit
return YES;
}
}
maxLinesInTextView
是一个int
变量,代表您想要的最大行数。textView:shouldChangeTextInRange:replacementText:
而不是textViewDidChange:
是因为我在使用全局NSString修改之前缓存文本时遇到了一些问题,并在textViewDidChange:
中用该全局NSString替换了UITextView.text 答案 0 :(得分:1)
以下是使用UITextViewDelegate
shouldChangeTextInRange:
方法将文本输入限制为文本视图高度的方法:
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
// Combine the new text with the old
let combinedText = (textView.text as NSString).stringByReplacingCharactersInRange(range, withString: text)
// Create attributed version of the text
let attributedText = NSMutableAttributedString(string: combinedText)
attributedText.addAttribute(NSFontAttributeName, value: textView.font, range: NSMakeRange(0, attributedText.length))
// Get the padding of the text container
let padding = textView.textContainer.lineFragmentPadding
// Create a bounding rect size by subtracting the padding
// from both sides and allowing for unlimited length
let boundingSize = CGSizeMake(textView.frame.size.width - padding * 2, CGFloat.max)
// Get the bounding rect of the attributed text in the
// given frame
let boundingRect = attributedText.boundingRectWithSize(boundingSize, options: NSStringDrawingOptions.UsesLineFragmentOrigin, context: nil)
// Compare the boundingRect plus the top and bottom padding
// to the text view height; if the new bounding height would be
// less than or equal to the text view height, append the text
if (boundingRect.size.height + padding * 2 <= textView.frame.size.height){
return true
}
else {
return false
}
}
答案 1 :(得分:0)
一个选项是在shouldChangeTextInRange
委托方法中自己修改textView并始终返回NO(因为您已经为它完成了工作)。
- (BOOL)textView:(UITextView *)aTextView shouldChangeTextInRange:(NSRange)aRange replacementText:(NSString*)aText
{
NSString* oldText = aTextView.text;
NSString* newText = [aTextView.text stringByReplacingCharactersInRange:aRange withString:aText];
aTextView.text = newText;
if(/*aTextView contentSize check herer for number of lines*/)
{
//If it's now too big
aTextView.text = oldText;
}
return NO
}
答案 2 :(得分:0)
正如我在回答here中提到的,我建议反对使用shouldChangeCharactersInRange:
,因为在文本实际更改之前调用了。
使用textViewDidChangeMethod:
更有意义,因为在之后调用文本实际上会发生变化。从那里你可以轻松决定下一步该做什么。