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ć?

Ornilo
źródło
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)
}
iosjillian
źródło
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
    }
DanielZanchi
źródło
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
27
[self.textView scrollRangeToVisible:NSMakeRange(0, 1)];

w viewDidLoad

Liuk Smith
źródło
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.

Subathra D
źródło
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.

Glenn
źródło
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.

Mark Bridges
źródło
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.

Igor
źródło
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
}
danbretl
źródło
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)
}
kelsheikh
źródło
„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 !!

Dhaval H. Nena
źródło
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))
}
Brian Ogden
źródło
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
}
MRustamzade
źródło
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
Królikarnia
źródło
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)
}
Oszust
źródło
1

Wersja Swift:

override func viewDidLayoutSubviews() {
    yourTextView.setContentOffset(CGPointZero, animated: false)
}
Rashwan L.
źródło
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 里面 加上 滚动 , 这样 用户 会 看到 他 往上 滚动 到 第一 行

myj
źródło
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)
}
hall.keskin
źródło
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!

Mohit Kumar
źródło
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
}
Tatarasanu Victor
źródło
0

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

Aftab Baig
źródło
0

Umieść ten kod na swojej klasie

override func viewDidLayoutSubviews() {
        self.About_TV.setContentOffset(.zero, animated: false) // About_TV : your text view name)
    }
Nimisha joshy
źródło
-2

Dodaj kod do pliku viewdidload

self.automaticallyAdjustsScrollViewInsets = NO;
Eva Hsueh
źródło