Ornilo
Ornilo

Reputation: 791

UITextView text content doesn't start from the top

I have a long text coming from my JSON file but when I click the link from my UITableViewCell to go to my UIViewController page, the UITextView text loads the string content but it does not show the content from the beginning and I have to scroll up all the time.

What I need to do?

Upvotes: 79

Views: 37832

Answers (22)

Mohit Kumar
Mohit Kumar

Reputation: 3086

Swift 3, 4, 5 solution:

Steps to solve the issue:

  • Disable the UITextView scroll
  • set scrollRectToVisible
  • enable UITextView scroll

Code:

yourTextView.isScrollEnabled = false
let rect:CGRect = CGRect(x: 0, y: 0, width: 1, height: 1)
yourTextView.scrollRectToVisible(rect, animated: false)
yourTextView.isScrollEnabled = true

This Worked for me. Hope that will help!

Upvotes: 1

Nimisha joshy
Nimisha joshy

Reputation: 336

Put this code on your class

override func viewDidLayoutSubviews() {
        self.About_TV.setContentOffset(.zero, animated: false) // About_TV : your text view name)
    }

Upvotes: 0

Dhaval H. Nena
Dhaval H. Nena

Reputation: 4130

Instead of setting content offset from viewDidLayoutSubviews you can write layoutIfNeeded from viewDidLoad to set the proper position of textview as below:

    self.textView.layoutIfNeeded()
    self.textView.setContentOffset(CGPoint.zero, animated: false)

Cheers !!

Upvotes: 3

iosjillian
iosjillian

Reputation: 2138

I had the same problem, and turns out I had to set the content offset in viewDidLayoutSubviews for it to take effect. I'm using this code to display attributed static text.

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

SWIFT 3:

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

Upvotes: 161

DanielZanchi
DanielZanchi

Reputation: 2768

This is the only way that worked for me. I disable the scroll of the UITextView before the view is loaded and then i enable it again:

  override func viewWillAppear(_ animated: Bool) {
        yourTextView.isScrollEnabled = false
    }

    override func viewDidAppear(_ animated: Bool) {
        yourTextView.isScrollEnabled = true
    }

Upvotes: 46

hall.keskin
hall.keskin

Reputation: 211

in swift 4 with attributed text any of answer does not help me and i combine some answers in topic.

override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
     uiTextview.isScrollEnabled = false
}

override func viewDidAppear(_ animated: Bool) {
     uiTextview.isScrollEnabled = true
     uiTextview.setContentOffset(CGPoint.zero, animated: false)
}

Upvotes: 1

myj
myj

Reputation: 11

add the following function to your view controller class...

Swift 3

override func viewDidLayoutSubviews() {
    self.mainTextView.setContentOffset(.zero, animated: false)
}
Swift 2.1

override func viewDidLayoutSubviews() {
    self.mainTextView.setContentOffset(CGPointZero, animated: false)
}
Objective C

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

或者 你在ViewDidAppear 里面加上滚动,这样用户会看到他往上滚动到第一行

Upvotes: 1

Warren
Warren

Reputation: 681

This worked the best for me! I placed this within viewDidLoad().

//TextView Scroll starts from the top
myTextView.contentOffset.y = 0

Upvotes: 2

MRustamzade
MRustamzade

Reputation: 1455

Swift 3.0

override func viewWillAppear(_ animated: Bool) {
    privacyText.isScrollEnabled = false
}

override func viewDidAppear(_ animated: Bool) {
    privacyText.isScrollEnabled = true
}

Upvotes: 2

kelsheikh
kelsheikh

Reputation: 1338

Swift Version

A combination of things will be needed:

1.) Set your outlet

  @IBOutlet var textView: UITextView!

2.) In storyboard on View Controller turn off "Adjust Scroll View Insets"

3.) Set content to zero top by adding below to your view controller

override func viewWillLayoutSubviews() {
   super.viewWillLayoutSubviews()
     myUITextView.setContentOffset(CGPointZero, animated: false)
}

Upvotes: 3

Aftab Baig
Aftab Baig

Reputation: 290

From storyboard, select the view controller on which you have you text view placed. In the attributes inspector, uncheck "Adjust Scroll View Insets". That's it.

Upvotes: 0

Rashwan L
Rashwan L

Reputation: 38833

Swift version:

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

Upvotes: 1

Swindler
Swindler

Reputation: 800

Here's another way to do it that always works for me. Objective-C:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self.textView setContentOffset:CGPointZero animated:NO];
}

And in Swift:

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

Upvotes: 1

danbretl
danbretl

Reputation: 644

Similar to some other answers, but with the added benefit that you won't cause a scroll to top on subsequent device rotations. Works well in Swift 2.2

/// Whether view has laid out subviews at least once before.
var viewDidLayoutSubviewsAtLeastOnce = false

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if !viewDidLayoutSubviewsAtLeastOnce {
        textView.setContentOffset(CGPoint(x: 0, y: -textView.contentInset.top), animated: false)
    }

    viewDidLayoutSubviewsAtLeastOnce = true
}

Upvotes: 4

Glenn
Glenn

Reputation: 189

The answers for the question Blank space at top of UITextView in iOS 10 provide a much cleaner end user experience.

In viewDidLoad of the view controller containing the text view:

 self.automaticallyAdjustsScrollViewInsets = false

Setting textView.setContentOffset(CGPointMake(0,0), animated: false) and some of these other suggestions do work when called in the viewDidLayoutSubviews() but on older devices like iPad 2 and older you will actually see the text get scrolled when the screen is displayed. That is not something you want the end user to see.

Upvotes: 13

Tatarasanu Victor
Tatarasanu Victor

Reputation: 654

This is how i did it. I subclassed textview, and:

override func willMoveToSuperview(newSuperview: UIView?) {
    self.scrollEnabled = false
}

override func layoutSubviews() {
    super.layoutSubviews()
    self.scrollEnabled = true
}

Upvotes: 0

Subathra D
Subathra D

Reputation: 399

By Programmatically before loading the content disable the scrolling property of textview textview.scrollenabled = NO;

And after loading enable the scrolling of textview textview.scrollenabled = YES;

As well check the XIB, always non-check the scrolling enabled of Textview.

Upvotes: 19

Brian Ogden
Brian Ogden

Reputation: 19212

In Swift 2, Xcode 7 solution, to leave scroll Enabled as well as have the text start at the top, this is all you need:

@IBOutlet weak var myUITextView: UITextView!

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    //start scroll at top of text
    myUITextView.scrollRangeToVisible(NSMakeRange(0, 0))
}

Upvotes: 2

Igor
Igor

Reputation: 12303

For me fine works this code:

    textView.attributedText = newText //or textView.text = ...

    //this part of code scrolls to top
    textView.contentOffset.y = -64 //or = 0 if no Navigation Bar
    textView.scrollEnabled = false
    textView.layoutIfNeeded()
    textView.scrollEnabled = true

For scroll to exact position and show it on top of screen I use this code:

    var scrollToLocation = 50 //<needed position>
    textView.contentOffset.y = textView.contentSize.height
    textView.scrollRangeToVisible(NSRange.init(location: scrollToLocation, length: 1))

Setting contentOffset.y scrolls to the end of text, and then scrollRangeToVisible scrolls up to value of scrollToLocation. Thereby, needed position appears in first line of scrollView.

Upvotes: 4

Eva Hsueh
Eva Hsueh

Reputation: 61

Add code to the viewdidload

self.automaticallyAdjustsScrollViewInsets = NO;

Upvotes: -2

Mark Bridges
Mark Bridges

Reputation: 8448

I was still having problems after using these solutions. The problem definitely seems to relate to having transparent navigation bars and selecting to automatically adjust content insets on the view controller. If you don't care about your text scrolling underneath the navigation bar then it's best to leave these settings off and constrain the top of your textview to the bottom of the navigation bar, rather than to the top of the viewcontroller.

If like me you wanted it to appear underneath your navigation bar when you scroll down; then the solution that worked for me was to add this.

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    CGFloat offset = self.navigationController.navigationBar.frame.size.height+[UIApplication sharedApplication].statusBarFrame.size.height;

    [self.textView setContentOffset:CGPointMake(0, -offset) animated:NO];
}

This just looks for the height of the navigation bar and status bar and adjusts the content offset accordingly.

Note that one downside of this approach is that when the device rotates you'll end up scrolling back to the top.

Upvotes: 4

Liuk Smith
Liuk Smith

Reputation: 311

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

in viewDidLoad

Upvotes: 27

Related Questions