Treść tekstowa UITextView nie zaczyna się od góry


79

Mam długi tekst pochodzący z mojego pliku JSON, ale kiedy klikam łącze z mojego UITableViewCell, aby przejść do mojej strony UIViewController, tekst UITextView ładuje zawartość ciągu, ale nie pokazuje zawartości od początku i muszę przewijać wszystko w górę czas.

Co muszę zrobić?


Czy próbowałeś ustawić contentOffset na (0,0)?
rdelmar

Możesz edytować to pytanie. Pod tagami widzisz „edytuj”. kliknij, aby edytować. Otrzymałem sugestię zmiany, ale uważam, że użytkownik powinien edytować pytanie.
LanternMike

sprawdź tę stronę i sprawdź, czy jedno z tych rozwiązań działa dla Ciebie. Prawie wszystko, co tu jest, jest tam i więcej stackoverflow.com/questions/1234242/… Jeśli masz pytania, sprecyzuj, co się dzieje, działa, nie działa, co próbowałeś.
LanternMike

Oto link do mojego problemu: link
Ornilo

jedyne rozwiązanie, które zadziałało, pochodziło z tego z innego postu
Andriy Bas

Odpowiedzi:


160

Miałem ten sam problem i okazało się, że musiałem ustawić przesunięcie zawartości w viewDidLayoutSubviews, aby zadziałało. Używam tego kodu do wyświetlania przypisanego tekstu statycznego.

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

SWIFT 3:

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

4
Ze wszystkich odpowiedzi ta działa najlepiej. Ponadto, jeśli tekst UITextView zaczyna się gdzieś w kierunku pionowego środka widoku tekstu, dodanie następującego elementu do viewDidLoad również to naprawi: self.automaticallyAdjustsScrollViewInsets = false
Wizkid

Ciekawostką jest to, że rozwiązanie offuttjillian zadziałało dla mnie, ale rozwiązanie podane przez Ciebie @Wizkid i Glenn sprawia, że ​​jest jeszcze gorzej na iOS 9.1 W każdym razie działa teraz i to mnie cieszy ^^
Frozn

2
chociaż jest to działające rozwiązanie, niestety ma duży efekt uboczny brzydkie widoczne przewijanie w górę, nawet jeśli używasz viewWillLayoutSubviews: /
Hofi

Próbując prawie 6 sposobów rozwiązania problemu, ta odpowiedź zadziałała tylko dla mnie w iOS9.x.
KoreanXcodeWorker

działa dobrze, nawet jeśli ustawisz go po przypisaniu tekstu do UITextView
Hassy

46

To jedyny sposób, który zadziałał dla mnie. Wyłączam przewijanie UITextView przed załadowaniem widoku, a następnie włączam go ponownie:

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

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

2
najlepsze rozwiązanie, aby uzyskać jak najmniejszy widoczny efekt wizualny
rozwijającego

Działało dobrze dla mnie
thibaut noah

Miałem pewne problemy z bałaganem podczas przewijania na iPadzie, korzystając z tego rozwiązania.
Cudzoziemcy


19

Przez Programowo przed załadowaniem treści wyłącz właściwość przewijania textview textview.scrollenabled = NO;

A po załadowaniu włącz przewijanie widoku tekstu textview.scrollenabled = YES;

Ponadto sprawdź XIB, zawsze nie zaznaczaj przewijania włączonego w Textview.


wielkie dzięki, ale jeśli mamy ten uitextview w widoku kolekcji lub widoku tabeli, to nie zadziała
Amr Angry

12

Odpowiedzi na pytanie Puste miejsce u góry UITextView w systemie iOS 10 zapewnia znacznie czystsze wrażenia użytkownika końcowego.

W viewDidLoadkontrolerze widoku zawierającym widok tekstu:

 self.automaticallyAdjustsScrollViewInsets = false

Ustawienia textView.setContentOffset(CGPointMake(0,0), animated: false)i niektóre z tych innych sugestii działają po wywołaniu, viewDidLayoutSubviews()ale na starszych urządzeniach, takich jak iPad 2 i starsze, tekst zostanie przewinięty po wyświetleniu ekranu. To nie jest coś, co chciałbyś zobaczyć dla użytkownika końcowego.


4

Po zastosowaniu tych rozwiązań nadal miałem problemy. Wydaje się, że problem zdecydowanie dotyczy posiadania przezroczystych pasków nawigacji i automatycznego dostosowywania wstawek zawartości na kontrolerze widoku. Jeśli nie zależy Ci na przewijaniu tekstu pod paskiem nawigacyjnym, najlepiej pozostawić te ustawienia wyłączone i ograniczyć górną część widoku tekstu do dołu paska nawigacyjnego, a nie do góry kontrolera widoku.

Jeśli tak jak ja chciałeś, aby pojawiał się pod twoim paskiem nawigacyjnym podczas przewijania w dół; wtedy rozwiązaniem, które zadziałało, było dodanie tego.

- (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];
}

To tylko szuka wysokości paska nawigacji i paska stanu i odpowiednio dostosowuje przesunięcie zawartości.

Zwróć uwagę, że jedną wadą tego podejścia jest to, że gdy urządzenie się obraca, przewijasz z powrotem do góry.


Dziękuję - to ostatecznie doprowadziło mnie do dobrego pomysłu :)
HannahCarney

4

Dla mnie dobrze działa ten kod:

    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

Aby przewinąć do dokładnej pozycji i pokazać ją na górze ekranu, używam tego kodu:

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

Ustawienie contentOffset.y powoduje przewijanie do końca tekstu, a następnie scrollRangeToVisible przewija w górę do wartości scrollToLocation. W ten sposób potrzebna pozycja pojawia się w pierwszym wierszu scrollView.


4

Podobnie jak w przypadku niektórych innych odpowiedzi, ale z dodatkową korzyścią, że nie spowodujesz przewijania do góry przy kolejnych obrotach urządzenia. Działa dobrze w 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
}

Po wypróbowaniu kilku różnych odpowiedzi, ta zadziałała najlepiej. Zgodnie z odpowiedzią Swindlera możesz użyć CGPointZero dla CGPoint.
Mitch Downey

Ważne jest, aby zrobić to w tej metodzie - viewDidLayoutSubviews. Wiele odpowiedzi sprawi, że zrobisz to na widokuWillPear, ale to jest złe. viewDidLayoutSubviews to miejsce do zrobienia tego. Dzięki.
geekyaleks

3

Szybka wersja

Potrzebna będzie kombinacja rzeczy:

1.) Ustaw gniazdko

  @IBOutlet var textView: UITextView!

2.) W scenorysie na Kontrolerze widoku wyłącz opcję „Dostosuj wstawki widoku przewijania”

3.) Ustaw zawartość na zero u góry, dodając poniżej do kontrolera widoku

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

„CGPointZero” jest niedostępne w Swift
ali

3

Zamiast ustawiać zawartość odsunięty od viewDidLayoutSubviews można napisać layoutIfNeeded z viewDidLoad aby ustawić właściwą pozycję TextView jak poniżej:

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

Twoje zdrowie !!


2

W rozwiązaniu Swift 2, Xcode 7, aby pozostawić przewijanie włączone, a tekst zaczynać się od góry, to wszystko, czego potrzebujesz:

@IBOutlet weak var myUITextView: UITextView!

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

1
dzięki! działało to idealnie dla mnie z Swift 2.2. Żadne z innych rozwiązań nie działało tak płynnie i prosto.
Natalia

2

Swift 3.0

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

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

Wyłącz przewijanie w Storyboard! I włącz w kodzie. override func viewDidAppear (_ animated: Bool) {privacyText.isScrollEnabled = true}
Vitaliy A

2

To działało najlepiej dla mnie! Umieściłem to w viewDidLoad ().

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

1
Wyrażenia nie można przypisać.
Bhumesh Purohit,

1

Oto inny sposób na zrobienie tego, który zawsze działa dla mnie. Cel C:

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

A w Swift:

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

1

Wersja Swift:

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

1

dodaj następującą funkcję do swojej klasy kontrolera widoku ...

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 里面 加上 滚动 , 这样 用户 会 看到 他 往上 滚动 到 第一 行


czy mógłbyś przetłumaczyć ostatnie zdanie na angielski?
Gilles Gouaillardet

1

w swift 4 z przypisanym tekstem żadna odpowiedź nie pomaga mi i łączę niektóre odpowiedzi w temacie.

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)
}

a co jeśli uittextview jest w widoku kolekcji lub widoku tabeli
Amr Angry

@AmrAngry nie mam pojęcia, po prostu używali go do widoku tekstu
hall.keskin

dzięki, używam tetxview.scrollRangeToVisible (NSMakeRange (0, 0))
Amr Angry

1

Rozwiązanie Swift 3, 4, 5:

Kroki, aby rozwiązać problem:

  • Wyłącz przewijanie UITextView
  • ustaw scrollRectToVisible
  • włącz przewijanie UITextView

Kod:

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

To zadziałało dla mnie. Mam nadzieję, że to pomoże!


Dzięki Mohit za wygodne, łatwe wyjaśnienie.
Praveen Kumar Verma

0

Tak to zrobiłem. Podklasowałem textview i:

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

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

0

W scenorysie wybierz kontroler widoku, na którym masz umieszczony widok tekstu. W inspektorze atrybutów odznacz „Dopasuj wstawki widoku przewijania”. Otóż ​​to.


0

Umieść ten kod na swojej klasie

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

-2

Dodaj kod do pliku viewdidload

self.automaticallyAdjustsScrollViewInsets = NO;
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.