首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >UITextView firstRectForRange返回错误帧

UITextView firstRectForRange返回错误帧
EN

Stack Overflow用户
提问于 2014-08-05 19:31:08
回答 7查看 3.4K关注 0票数 2

编辑

简单的解决方案是将任何帧计算从viewDidLoad移到viewDidAppear:

我很难让下面的代码正常工作

该代码返回给定NSRange在UITextView中的第一个帧。

如果没有换行,它就能工作,但是当我在UITextView中添加换行时,我会得到一些奇怪的行为。

代码语言:javascript
复制
@implementation UITextView (TextFrame)

- (CGRect)frameOfTextRange:(NSRange)range {
    UITextPosition *beginning = self.beginningOfDocument;
    UITextPosition *start = [self positionFromPosition:beginning offset:range.location];
    UITextPosition *end = [self positionFromPosition:start offset:range.length];
    UITextRange *textRange = [self textRangeFromPosition:start toPosition:end];
    CGRect rect = [self firstRectForRange:textRange];

    return [self convertRect:rect fromView:self.textInputView];
}

@end

@implementation DetailViewController

- (void)viewDidLoad 
{
    [super viewDidLoad];
   if (self.searchString) {
        CGRect rect = [self.textView frameOfTextRange:[self.textView.text rangeOfString:self.searchString]];
        ...
    }
}
EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2014-08-19 17:19:04

很明显,firstRectForRange:似乎不在viewDidLoad工作

将计算从viewDidLoad转移到viewDidAppear: 解决了问题

旧码

代码语言:javascript
复制
- (void)viewDidLoad 
{
    [super viewDidLoad];

    if (self.searchString) {
        CGRect rect = [self.textView frameOfTextRange:[self.textView.text rangeOfString:self.searchString]];
        [self.textView scrollRangeToVisible:[self.textView.text rangeOfString:self.searchString]];
        UIView *markerView = [[UIView alloc] initWithFrame:rect];
        markerView.backgroundColor = [UIColor colorWithRed:0.810 green:0.735 blue:0.000 alpha:0.660];
        [self.textView addSubview:markerView];
        _searchString = nil;
    }
}

新代码和工作代码

代码语言:javascript
复制
- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    if (self.searchString) {
        CGRect rect = [self.textView frameOfTextRange:[self.textView.text rangeOfString:self.searchString]];
        [self.textView scrollRangeToVisible:[self.textView.text rangeOfString:self.searchString]];
        UIView *markerView = [[UIView alloc] initWithFrame:rect];
        markerView.backgroundColor = [UIColor colorWithRed:0.810 green:0.735 blue:0.000 alpha:0.660];
        [self.textView addSubview:markerView];
        _searchString = nil;
    }
}
票数 3
EN

Stack Overflow用户

发布于 2015-04-11 11:16:53

我找到了下面的解决方案。不使用只返回一个rect的firstRectForRange:,而是使用selectionRectsForRange:,然后遍历所有rect并使用CGRectUnion组合它们。

代码语言:javascript
复制
- (CGRect)frameOfTextRange:(NSRange)range
{
   UITextPosition *beginning = self.beginningOfDocument;
   UITextPosition *start = [self positionFromPosition: beginning offset: range.location];
   UITextPosition *end = [self positionFromPosition: start offset: range.length];

   UITextRange *textRange = [self textRangeFromPosition: start toPosition: end];

   CGRect  rect = CGRectZero;

   NSArray *selectionRects = [self selectionRectsForRange: textRange];

   for (UITextSelectionRect *selectionRect in selectionRects)
   {
      rect = CGRectUnion(rect, selectionRect.rect);
   }

   return rect;
}
票数 8
EN

Stack Overflow用户

发布于 2014-08-21 05:12:43

可以强制self.textView确保在以下情况下立即进行布局:

代码语言:javascript
复制
[self.textView.layoutManager ensureLayoutForTextContainer:self.textView.textContainer];

将其放置在frameOfTextRange:电话前将使您正确地重新定位。

当然,您可以在frameOfTextRange:方法中调用它:

代码语言:javascript
复制
- (CGRect)frameOfTextRange:(NSRange)range {
    [self.layoutManager ensureLayoutForTextContainer:self.textContainer];
    ...

这使得可以安全地从任何地方调用frameOfTextRange:方法。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25146850

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档