UITextView从文本的底部或中间开始


75

我会正确的。我的UItextView观点是,当需要滚动以查看所有文本时(当textView中有很多文本时),textView有时在文本中间开始,而在其他时候则在文本底部开始。

在此处输入图片说明

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

谢谢你的帮助。


您是使用UINavigationBar作为那里的标题还是其自定义视图?
Mrunal 2014年

@Mrunal我不确定您的意思,但您要询问的是它的颜色,它是推送按钮中正常的导航栏,仅在appdelegate中着色。
亚历克斯·沃尔夫

2
您是否在viewDidLoad中设置文本?在主队列上执行dispatch_async将解决问题。
查理·吴

Answers:


169

那帮了我大忙!

目标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
}

9
很棒!我仍然不明白为什么我们必须这样做。为什么不自动从0,0开始?
mikemike396

6
我认为这是因为它是用户输入区域,所以当您键入文本时,光标会位于文本的末尾,并且如果您离开屏幕,则想从返回时的左边继续键入。
user2700551

2
我发现scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO效果更好,因为它避免了由隐式动画引起的初始渲染。
devios1 2015年

这绝对不适合我。@zeeple提供的答案是可行的,但是如果我们确实使用了答案,则textview会在对该视图执行的任何操作上向上滚动。希望能有所帮助。
mshrestha

嗨,Manjul,我在实现中没有看到相同的行为。我可以在视图中触摸,摆动它等等,并且它不会自动滚动到顶部。
zeeple '16

54

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

override func viewDidLayoutSubviews() {
  super.viewDidLayoutSubviews()

  welcomeText.contentOffset = .zero
}

HTH :)


2
也许是因为我在使用笔尖,所以这是唯一为我工作的笔尖。
罗德里戈·平托

3
@RodrigoPedroso使用情节提要,这也是唯一对我有用的方法
Patrick

1
同样在这里,这是唯一对我有用的解决方案。我的文本视图位于笔尖中,以供记录。不知道这是否会改变任何东西。
表格

我正在使用情节提要。可能与iOS版本有关吗?
米格尔·里贝罗

我尝试了一下viewDidLayoutSubviews(),尽管动画设置为false,但加载ViewController时,textView仍在滚动。我通过把解决它setContentOffsetviewWillAppearW /动画设置为false。
阿德里安

14

在Swift 2

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

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    myTextView.setContentOffset(CGPointZero, animated: false)
}

确认可在Swift 2的Xcode 7.2中使用


1
在Xcode 7.3(7D175)/ iOS 9.3中为我完美工作
JSmyth '16

13

试试下面的代码-

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

或者,您也可以通过StoryBoard设置此属性-

选择ViewController,然后选择现在未选中的属性检查器Adjust Scroll View Insets


我看不到“属性”检查器中“调整滚动视图插图”的位置。
zeeple

@zeeple这是一个ViewController属性,将在情节提要中选择ViewController后,将显示在Attributes Inspector中ViewController标题的下方。请正确检查,希望您能找到它。
keshav vishwkarma

8

对于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

希望这可以帮助。


1
运气不好……文本视图仍然一直滚动到底部。可能与automaticAdjustsScrollViewInsets属性有关吗?因为启用了此项,所以我将textview放置在导航栏下方,所以导航栏不会使textview黯然失色。感谢你的回答。
Alex Wulff 2014年

尝试自动注释评论AdjustsScrollViewInsets行并进行检查。
Mrunal 2014年

5

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()textView.text = someStrings在中viewDidLoad()textView有时中的内容会“晃动”。因此,将它们放在同一位置。

最后一句话:尝试所有组合,这就是我在两个月内解决此愚蠢错误三次的方法。


将textview scrollEnabled设置为false,然后设置为true是对我有用的。而且我不必将其放入viewDidLoad或ViewDidLayoutSubviews中。在设置文本之前,我先将scrollEnabled = false放进去,然后在完成处理程序中将scrollEnable = true放到使texView出现的动画中
Anna Harrison

5

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

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

4

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在上面的链接后面发布了答案。

我的第一篇文章:),加油!


这正是我需要解决的问题。谢谢!
BlueGuy


3

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

[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中放置了所有位置,但没有运气。我以为这与我的导航栏有关?
Alex Wulff 2014年

2

这对我有用:

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

}

2

这适用于Xcode 8.3.3:

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

2

UITextViewViewController.swift文件中为您创建一个出口。在本ViewDidLoad节中,输入以下内容:

迅速:

self.textView.contentOffset.y = 0

我试过了:

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

1

我将zeeple的答案翻译为MonoTouch / Xamarin(C#)。

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

0

我必须在此处实现两个答案,以使我的视图按需工作:

从Juan David Cruz Serrano:

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

从Murat Yasar那里:

automaticallyAdjustsScrollViewInsets = false

这样就提供了一个UITextView,该滚动条的顶部加载了UITextView,并且滚动开始后其中的插图不会更改。很奇怪,这不是默认行为。


0

要强制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];
}

0

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)

-1

就我而言,我正在自定义表格视图单元格中加载textView。以下是确保自定义单元格中textview中的文本加载到textview中文本顶部的操作。

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

2.)加载视图后,在文本视图上将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。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.