klc*_*r89 19 objective-c uitextview ios ios7
我有一个不可滚动的UITextView,它的layoutManager maximumNumberOfLines设置为9,工作正常,但是,我似乎无法在NSLayoutManager中找到一个限制文本不超出UITextView框架的方法.
例如,在此屏幕截图中,光标位于第9行(第1行被剪切在屏幕截图的顶部,因此请忽略它).如果用户继续键入新字符,空格或点击返回键,则光标将继续在屏幕外显示,并且UITextView的字符串将继续变长.

由于外来字符大小不同,我不想限制UITextView的字符数.
我一直试图解决这个问题几个星期; 我非常感谢任何帮助.
CustomTextView.h
#import <UIKit/UIKit.h>
@interface CustomTextView : UITextView <NSLayoutManagerDelegate>
@end
Run Code Online (Sandbox Code Playgroud)
CustomTextView.m
#import "CustomTextView.h"
@implementation CustomTextView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
self.backgroundColor = [UIColor clearColor];
self.font = [UIFont systemFontOfSize:21.0];
self.dataDetectorTypes = UIDataDetectorTypeAll;
self.layoutManager.delegate = self;
self.tintColor = [UIColor companyBlue];
[self setLinkTextAttributes:@{NSForegroundColorAttributeName:[UIColor companyBlue]}];
self.scrollEnabled = NO;
self.textContainerInset = UIEdgeInsetsMake(8.5, 0, 0, 0);
self.textContainer.maximumNumberOfLines = 9;
}
return self;
}
- (CGFloat)layoutManager:(NSLayoutManager *)layoutManager lineSpacingAfterGlyphAtIndex:(NSUInteger)glyphIndex withProposedLineFragmentRect:(CGRect)rect
{
return 4.9;
}
@end
Run Code Online (Sandbox Code Playgroud)
更新,仍未解决
我认为这是一个更好的答案.每当调用shouldChangeTextInRange委托方法时,我们调用我们的didFit:string:range函数来查看结果文本高度是否超出视图高度.如果是,我们返回NO以防止发生变化.
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
FLOG(@" called");
// allow deletes
if (text.length == 0)
return YES;
// Check if the text exceeds the size of the UITextView
return [self doesFit:textView string:text range:range];
}
- (float)doesFit:(UITextView*)textView string:(NSString *)myString range:(NSRange) range;
{
// Get the textView frame
float viewHeight = textView.frame.size.height;
float width = textView.textContainer.size.width;
NSMutableAttributedString *atrs = [[NSMutableAttributedString alloc] initWithAttributedString: textView.textStorage];
[atrs replaceCharactersInRange:range withString:myString];
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:atrs];
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize: CGSizeMake(width, FLT_MAX)];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
[layoutManager addTextContainer:textContainer];
[textStorage addLayoutManager:layoutManager];
float textHeight = [layoutManager
usedRectForTextContainer:textContainer].size.height;
FLOG(@" viewHeight = %f", viewHeight);
FLOG(@" textHeight = %f", textHeight);
if (textHeight >= viewHeight - 1) {
FLOG(@" textHeight >= viewHeight - 1");
return NO;
} else
return YES;
}
Run Code Online (Sandbox Code Playgroud)
编辑确定如果更改文本格式,还需要添加一些检查.在我的情况下,用户可以更改字体或使其变为粗体,更改段落样式等.所以现在任何这些更改也可能导致文本超出textView边框.
首先,您需要确保使用textViews undoManager注册这些更改.请参阅下面的示例(我只是复制整个attributedString,以便在调用undo时我可以将其放回去).
// This is in my UITextView subclass but could be anywhere
// This gets called to undo any formatting changes
- (void)setMyAttributedString:(NSAttributedString*) atstr {
self.attributedText = atstr;
self.selectedRange = _undoSelection;
}
// Before we make any format changes save the attributed string with undoManager
// Also save the current selection (maybe should save this with undoManager as well using a custom object containing selection and attributedString)
- (void)formatText:(id)sender {
//LOG(@"formatText: called");
NSAttributedString *atstr = [[NSAttributedString alloc] initWithAttributedString:self.textStorage];
[[self undoManager] registerUndoWithTarget:self
selector:@selector(setMyAttributedString:)
object:atstr];
// Remember selection
_undoSelection = self.selectedRange;
// Add text formatting attributes
...
// Now tell the delegate that something changed
[self.delegate textViewDidChange:self];
}
Run Code Online (Sandbox Code Playgroud)
现在检查委托中的大小,如果不适合则撤消.
-(void)textViewDidChange:(UITextView *)textView {
FLOG(@" called");
if ([self isTooBig:textView]) {
FLOG(@" text is too big so undo it!");
@try {
[[textView undoManager] undo];
}
@catch (NSException *exception) {
FLOG(@" exception undoing things %@", exception);
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9572 次 |
| 最近记录: |