【问题标题】:UITextView contentOffset on iOS 7iOS 7 上的 UITextView contentOffset
【发布时间】:2026-02-09 07:15:02
【问题描述】:

我的应用中有一个 UITextView。每次添加新字符串时,我都需要动态更改它的内容偏移量。下面的代码在 iOS 6 和更早的版本上运行良好,但在 iOS 7 上不行。

CGPoint offset = CGPointMake(0, self.textView.contentSize.height - self.textView.frame.size.height);
[self.textView setContentOffset:bottomOffset animated:YES]; 

你有什么想法吗?

比你。

更新

UITextView 没有按应有的方式设置它的 contentOffset,或者其他东西搞砸了。结果与预期不符(在 iOS 6 或更早版本上的情况)。

我也尝试设置新属性“textContainerInset”,但仍然没有结果...

self.textView.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0)    

更新

正如我在 didScroll 委托方法中看到的那样,当我为内容偏移传递一个正值时,它会滚动到 (0,0)。例如,我将内容偏移量设置为 (0,35) 并滚动到 (0,0)...

【问题讨论】:

  • 我已经更新了我的帖子。

标签: iphone uitextview ios7


【解决方案1】:

我找到的解决方案一点也不优雅,但它确实有效:

我将 UITextView 的 contentOffset 设置为 (0,0),然后再将其设置为所需的偏移量。我不知道为什么会这样,但目前是我找到的最佳解决方案。

CGPoint bottomOffset = CGPointMake(0, self.textView.contentSize.height - self.textView.frame.size.height);
[self.textView setContentOffset: CGPointMake(0,0) animated:NO]; 
[self.textView setContentOffset:bottomOffset animated:YES]; 

【讨论】:

    【解决方案2】:

    我今天才注意到这一点。在我的情况下,问题显然与文本视图是视图中的第一个控件有关。我将它移到文档大纲中的第二位(例如在 UILabel 之后)并且偏移量消失了。

    这很可能是故意这样做的,因为 iOS7 中导航栏的新行为。

    【讨论】:

    • 天啊!!!!!!这是有史以来最愚蠢的修复。但它有效!恰好在我的 UITextView 中有一个 contentOffset 为 -64.0
    • 感谢您为我们节省了一些痛苦的调试......和哈哈苹果
    【解决方案3】:

    好的,根据我的研究和其他答案,问题在于UITextView 的内容高度,而不是滚动到特定偏移量。这是一个适用于 iOS 7 的解决方案:

    首先,您需要像这样重新创建UITextView

        NSString *reqSysVer = @"7.0";
        NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
        BOOL osVersionSupported = ([currSysVer compare:reqSysVer  options:NSNumericSearch] != NSOrderedAscending);
    
        if (osVersionSupported) {
    
            NSLog(@"reset chatoutput");
    
            CGRect outputFrame = self.chatOutput.frame;
    
            [chatOutput removeFromSuperview];
            [chatOutput release];
            chatOutput = nil;
    
            NSTextStorage* textStorage = [[NSTextStorage alloc] init];
            NSLayoutManager* layoutManager = [NSLayoutManager new];
            [textStorage addLayoutManager:layoutManager];
            NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:self.view.bounds.size];
            [layoutManager addTextContainer:textContainer];
            chatOutput = [[UITextView alloc] initWithFrame: outputFrame
                                               textContainer: textContainer];
            // if using ARC, remove these 3 lines
            [textContainer release];
            [layoutManager release];
            [textStorage release];
    
            [self.view addSubview: chatOutput];
        }
    

    然后,使用此方法获取UITextView的内容高度:

    - (CGFloat)textViewHeightForAttributedText:(NSAttributedString*)text andWidth:(CGFloat)width
    {
         UITextView *calculationView = [[UITextView alloc] init];
         [calculationView setAttributedText:text];
         CGSize size = [calculationView sizeThatFits:CGSizeMake(width, FLT_MAX)];
    
         NSLog(@"size: %f", size.height) ;
    
         return size.height;
    }
    

    现在你可以设置内容偏移了:

    CGPoint bottomOffset;
    
    bottomOffset = CGPointMake(0, [self textViewHeightForAttributedText: self.chatOutput.attributedText andWidth: self.chatOutput.frame.size.width] - self.chatOutput.frame.size.height);
    
    [self.chatOutput setContentOffset:bottomOffset animated:YES];
    

    更新

    我在NSAttributedString 的 Apple 文档中阅读了此内容: "NSAttributedString 对象的默认字体是 Helvetica 12-point,可能与平台的默认系统字体不同。"

    总之,如果你使用不同大小的不同字体,你也必须将它们设置为NSAttributeString 实例。否则,返回的高度将不符合您的期望。你可能想使用这样的东西:

        NSDictionary *attrsDictionary = [NSDictionary dictionaryWithObject: [UIFont systemFontOfSize: 18.0] //or any other font or size
                                                                    forKey: NSFontAttributeName];
        NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString: currentPost.postMessageText attributes: attrsDictionary];
        frame.size.height = [self textViewHeightForAttributedText: attributedString andWidth: 280.0];
        [attributedString release];
    

    【讨论】:

    • 像魅力一样工作。干得好:)
    【解决方案4】:

    @vidonism 的answer 有效,但这更好。

    // in -viewDidLoad of UIViewController
    self.automaticallyAdjustsScrollViewInsets = NO;
    

    另请参阅此question 上已接受答案的顶部评论。这可能解释了 UIScrollView 作为 ViewController 主视图的第一个子视图的行为。
    我无法完全区分这是预期的行为还是错误。

    【讨论】:

    • 谢谢先生...这是我一直在寻找的答案,工程有效,但没有弹性,这个线程上的大多数 cmets 将在未来的 IOS 版本中被弃用,而不是你的。或者至少它会因为编译时错误而不是虚假设计和繁琐的调试而被弃用。
    【解决方案5】:

    我不得不求助

    [displayText scrollRangeToVisible:NSMakeRange([displayText.text length], 0)];
    

    但它的大问题是它从文本的顶部开始,每次附加到文本时都会滚动到末尾。米海的方案也是这样。

    【讨论】:

      【解决方案6】:

      以前的答案都不适合我,因为我有[textView setScrollEnabled:NO]。所以,我最终得到了这个:

      [textView setScrollEnabled:YES]
      [self.text setContentOffset:CGPointMake(0, page * self.text.frame.size.height) animated:NO];
      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
          [self.text setScrollEnabled:NO];
      });
      

      【讨论】: