【问题标题】:UITextView starts at Bottom or Middle of the textUITextView 从文本的底部或中间开始
【发布时间】:2015-02-21 17:13:57
【问题描述】:

我会马上解决的。我有一个UItextView 放置在我的视图中,当需要滚动查看所有文本时(当 textView 中存在大量文本时),textView 有时从文本中间开始,有时从文本底部开始.

textView 上未启用编辑。我需要一种方法来强制 textView 每次都从顶部开始。我看到一些类似这样的问题,其他人使用内容偏移,但我真的不知道它是如何工作的,或者它是否适用于这里。

感谢您的帮助。

【问题讨论】:

  • 你是用 UINavigationBar 作为标题,还是它的自定义视图?
  • @Mrunal 我不确定你的意思,但如果你问的是颜色,它是来自 push segue 的普通导航栏,只是在 appdelegate 中着色。
  • 您是否在 viewDidLoad 中设置文本?在主队列上做一个 dispatch_async 会解决这个问题。

标签: ios objective-c swift xcode cocoa-touch


【解决方案1】:

这对我有用!

目标 C:

[self.textView scrollRangeToVisible:NSMakeRange(0, 0)];

斯威夫特:

self.textView.scrollRangeToVisible(NSMakeRange(0, 0))

Swift 2(替代解决方案)

将此覆盖方法添加到您的 ViewController

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    textView.setContentOffset(CGPointZero, animated: false)
}

Swift 3 & 4(语法编辑)

override func viewDidLayoutSubviews() {
  super.viewDidLayoutSubviews()

  textView.contentOffset = .zero
}

【讨论】:

  • 效果很好!我仍然不明白为什么我们必须这样做。为什么它不自动从 0,0 开始?
  • 我认为因为它是一个用户输入区域,当你输入文本时,你的光标位于文本的末尾,如果你离开屏幕,你想继续输入从你回来时离开的地方。
  • 我发现scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO 效果更好,因为它避免了由隐式动画引起的初始渲染。
  • 这绝对不适合我。 @zeeple 提供的答案是有效的,但如果我们确实使用了答案,那么 textview 会在视图上执行的任何操作上向上滚动。希望能得到一些帮助。
  • 嗨 Manjul,我在我的实现中没有看到相同的行为。我可以在视图中触摸、摆动它等等,但它不会自动滚动到顶部。
【解决方案2】:

以上所有答案都对我不起作用。但是,秘诀是在 viewDidLayoutSubviews 的覆盖中实现您的解决方案,如下所示:

override func viewDidLayoutSubviews() {
  super.viewDidLayoutSubviews()

  welcomeText.contentOffset = .zero
}

HTH :)

【讨论】:

  • 也许是因为我使用的是笔尖,这是唯一对我有用的。
  • @RodrigoPedroso 使用故事板,这是唯一对我有用的方法
  • 这里也一样,这是唯一对我有用的解决方案。为了记录,我的文本视图在一个笔尖。不知道这是否会改变什么。
  • 我正在使用情节提要。这可能与iOS版本有关吗?
  • 我在viewDidLayoutSubviews() 中尝试过,尽管动画设置为 false,但当 ViewController 加载时,我看到 textView 滚动。我通过将 setContentOffset 放入 viewWillAppear 并将动画设置为 false 来解决它。
【解决方案3】:

在 Swift 2 中

您可以使用它使 textView 从顶部开始:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    myTextView.setContentOffset(CGPointZero, animated: false)
}

确认在 Xcode 7.2 中使用 Swift 2

【讨论】:

  • 在 Xcode 7.3 (7D175) / iOS 9.3 中完美地为我工作
【解决方案4】:

试试下面的代码 -

if ( [self respondsToSelector:@selector(setAutomaticallyAdjustsScrollViewInsets:)]){
     self.automaticallyAdjustsScrollViewInsets = NO;         
}

或者你也可以通过 StoryBoard 设置这个属性 -

选择 ViewController 然后选择属性检查器现在取消选中 Adjust Scroll View Insets

【讨论】:

  • 我在属性检查器中看不到 Adjust Scroll View Insets 的位置。
  • @zeeple 这是一个 ViewController 属性,在 Storyboard 中选择 ViewController 后,将显示在 Attributes Inspector 中 ViewController 的标题下方。请正确检查,希望您能找到。
【解决方案5】:

对于 Swift >2.2,我在使用上述方法时遇到了 iOS 8 和 iOS 9 的问题,因为没有一个可行的答案,所以这是我为使其适用于两者的方法。

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    if #available(iOS 9.0, *) {
        textView.scrollEnabled = false
    }

    self.textView.scrollRangeToVisible(NSMakeRange(0, 0))
}

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    if #available(iOS 9.0, *) {
        textView.scrollEnabled = true
    }
}

【讨论】:

  • 哇。我不敢相信那是我的问题。这样做有什么好处?
【解决方案6】:

将 UINavigationBar 的 translucent 属性更新为 NO

self.navigationController.navigationBar.translucent = NO;

这将修复视图在导航栏和状态栏下方的框架。

如果您必须显示和隐藏导航栏,请在 viewDidLoad 中使用以下代码

 if ([self respondsToSelector:@selector(edgesForExtendedLayout)])
    self.edgesForExtendedLayout = UIRectEdgeNone;   // iOS 7 specific

希望这会有所帮助。

【讨论】:

  • 这个也没有运气......文本视图仍然一直滚动到底部。可能与 automaticAdjustsScrollViewInsets 属性有关吗?因为我在启用此功能的情况下将文本视图放置在导航栏下方,所以导航栏不会使文本视图黯然失色。感谢您的回答。
  • 尝试自动评论AdjustsScrollViewInsets行并检查。
【解决方案7】:

Xcode 7.2 7c68; IOS 9.1

我的ViewController 包含UITextView 很复杂,在项目过程中发生了很大变化(IDE 版本也可能更改了 2~3 次)。

我已经尝试了以上所有解决方案,如果您遇到同样的问题,请耐心

解决三个可能的“秘密代码”:

  1. textView.scrollEnabled = false //then set text textView.scrollEnabled = true
  2. textView.scrollRangeToVisible(NSMakeRange(0, 0))
  3. textView.setContentOffset(CGPointZero, animated: false)

你可以把这些代码放在两个地方:

  1. viewDidLoad()
  2. viewDidLayoutSubviews()

组合它们,你会得到 3*2=6 的解决方案,正确的组合取决于你 ViewController 的复杂程度(相信我,删除 textView 上面的一个视图后,我需要找到一个新的组合)。

我发现:

当在viewDidLayoutSubviews() 中输入“密码”,但在viewDidLoad() 中输入textView.text = someStrings 时,textView 中的内容有时会“抖动”。所以,把它们放在同一个地方。

最后一句话:尝试 ALL 组合,这就是我在两个月内解决这个愚蠢错误超过 3 次的方法。

【讨论】:

  • 将 textview scrollEnabled 设置为 false 然后 true 对我有用。而且我不必将它放入 viewDidLoad 或 ViewDidLayoutSubviews 中。我在设置文本之前将 scrollEnabled = false 放入了一个完成处理程序中,以实现使 texView 出现的动画
【解决方案8】:

经过大量测试,我发现必须在 viewWillLayoutSubviews() 函数中添加以下内容,以确保 UITextView 从一开始就显示出来:

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()            
    textViewTerms.scrollRangeToVisible(NSMakeRange(0, 0))
}

【讨论】:

    【解决方案9】:

    UITextView 滚动似乎对很多人来说是个问题。从这里的答案(尤其是this)和 Apple Developer 文档中收集,使用我自己的一些智慧,这是一个适合我的解决方案。您可以修改代码以满足您的需要。

    我的用例如下:相同的UITextView用于不同的目的,在不同的情况下显示不同的内容。我想要的是,当内容发生变化时,旧的滚动位置会恢复,或者有时会滚动到最后。完成后我不想要太多动画。特别是我不希望视图像所有文本都是新的一样进行动画处理。此解决方案首先在没有动画的情况下恢复旧的滚动位置,然后根据需要滚动到动画的末尾。

    你需要做的(或者我应该说可以做的)是扩展 UITextView 如下:

    extension UITextView {
      func setText(text: String, storedOffset: CGPoint, scrollToEnd: Bool) {
        self.text = text
        let delayInSeconds = 0.001
        let popTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(delayInSeconds * Double(NSEC_PER_SEC)))
        dispatch_after(popTime, dispatch_get_main_queue(), {
          self.setContentOffset(storedOffset, animated: false)
          if scrollToEnd && !text.isEmpty {
            let popTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(delayInSeconds * Double(NSEC_PER_SEC)))
            dispatch_after(popTime, dispatch_get_main_queue(), {
              self.scrollRangeToVisible(NSMakeRange(text.lengthOfBytesUsingEncoding(NSUTF8StringEncoding) - 1, 0))
            })
          }
        })
      }
    }
    

    它的作用是更新文本,然后使用 UITextView.contentOffset 属性的存储值(或您作为参数传递的任何内容),并相应地设置视图的偏移量。如果需要,在此之后,它会滚动到新的、可能更改的内容的末尾。

    我是 iOS 编程的新手,我不知道为什么它工作得这么好,如果有人有这方面的一些信息,我会很高兴知道。此外,该方法可能并不完美,因此我也愿意接受改进的想法。

    当然还要感谢 NixonsBack 在上面的链接后面发布答案。

    我的第一篇文章 :),干杯!

    【讨论】:

    • 这正是我需要解决的问题。谢谢!
    【解决方案10】:

    将这一行代码放入ViewDidLoad

    self.automaticallyAdjustsScrollViewInsets = false
    

    【讨论】:

      【解决方案11】:

      下面的代码应该会给你想要的效果。

      [self.scrollView setContentOffset:CGPointMake(0, -self.scrollView.contentInset.top) animated:YES];
      

      您需要将“self.scrollView”替换为滚动视图的名称。您应该在设置滚动视图的文本后输入此代码。

      【讨论】:

      • 我尝试将[self.scrollView setContentOffset:CGPointMake(0, -self.scrollView.contentInset.top) animated:YES]; 放在多个地方:在我以编程方式设置代码之后,在 viewDidLoad 和 viewWillAppear 中,但没有运气。我认为这与我的导航栏有关?
      【解决方案12】:

      这对我有用:

       override func viewWillLayoutSubviews() {
          super.viewWillLayoutSubviews()
          textView.scrollRectToVisible(CGRect(origin: CGPointZero, size: CGSizeMake(1.0, 1.0)), animated: false)
      
      }
      

      【讨论】:

        【解决方案13】:

        这对我来说适用于 Xcode 8.3.3:

        -(void)viewWillLayoutSubviews
        {
            [super viewWillLayoutSubviews];
            [self.txtQuestion scrollRangeToVisible:NSMakeRange(0, 0)];
        }
        

        【讨论】:

          【解决方案14】:

          ViewController.swift 文件中为您的UITextView 创建一个出口。在ViewDidLoad 部分输入以下内容:

          斯威夫特:

          self.textView.contentOffset.y = 0
          

          我试过了:

          self.textView.scrollRangeToVisible(NSMakeRange(0, 0))
          

          【讨论】:

            【解决方案15】:

            我翻译了 zeeple 对 MonoTouch/Xamarin (C#) 的回答。

            public override void ViewDidLayoutSubviews()
            {
                base.ViewDidLayoutSubviews();
                myForm.SetContentOffset(new CoreGraphics.CGPoint(0,0), animated: false);
            }
            

            【讨论】:

              【解决方案16】:

              我必须在这里实现两个答案才能让我的视图按我的意愿工作:

              来自胡安·大卫·克鲁兹·塞拉诺:

              override func viewDidLayoutSubviews() {
                  super.viewDidLayoutSubviews()
                  textView.setContentOffset(CGPoint.zero, animated: false)
              }
              

              来自 Murat Yasar:

              automaticallyAdjustsScrollViewInsets = false
              

              这提供了一个 UITextView,它在顶部滚动加载,并且一旦滚动开始,插入就不会更改。很奇怪,这不是默认行为。

              【讨论】:

                【解决方案17】:

                要强制textView 每次都从顶部开始,请使用以下代码:

                Swift 4.2

                override func viewDidLayoutSubviews() {
                    textView.setContentOffset(CGPoint(x: 0, y: 0), animated: false)
                }
                

                Objective-C

                - (void)viewDidLayoutSubviews {
                    [self.yourTextView setContentOffset:CGPointZero animated:NO];
                }
                

                【讨论】:

                  【解决方案18】:

                  Swift 4.2 和 Swift 5

                  在设置文本之前和之后设置内容偏移量。 (在主线程上)

                  let animation = false //or whatever you want
                  self.mainTextView.setContentOffset(.zero, animated: animation)
                  self.mainTextView.attributedText = YOUR_ATTRIBUTED_TEXT
                  self.mainTextView.setContentOffset(.zero, animated: animation)
                  

                  【讨论】:

                    【解决方案19】:

                    在我的例子中,我在自定义 tableview 单元格中加载了一个 textView。下面是我为确保 textview 中的文本加载到我的自定义单元格中的 textview 中的文本顶部所做的操作。

                    1.) 在情节提要中,通过取消选中按钮来设置 textview ScrollEnabled = false。

                    2.) 在视图加载后,您在 textview 上将 isScrollEnabled 设置为 true。我将我的设置延迟如下:

                    override func awakeFromNib() {
                        super.awakeFromNib()
                    
                    let when = DispatchTime.now() + 1
                          DispatchQueue.main.asyncAfter(deadline: when){
                            self.textView.isScrollEnabled = true
                         }
                    
                    }
                    

                    不管你是否处于我的情况,尝试将 scrollEnabled 设置为 false,然后当视图加载时,将 scrollEnabled 设置为 true。

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2014-04-29
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2019-06-14
                      • 1970-01-01
                      相关资源
                      最近更新 更多