web-dev-qa-db-fra.com

UITextView commence en bas ou au milieu du texte

Je vais aller droit au but. J'ai une variable UItextView placée dans ma vue: lorsque vous avez besoin de faire défiler l'écran pour voir tout le texte (lorsqu'un lot de texte est présent dans textView), textView commence parfois au milieu du texte et au bas de celui-ci. 

 enter image description here

La modification n'est pas activée sur le textView. J'ai besoin d'un moyen de forcer le textView à commencer par le haut, à chaque fois. J'ai vu des questions un peu comme celle-ci où d'autres personnes utilisaient un contenu compensé, mais je ne sais pas vraiment comment cela fonctionne ou s'il serait même applicable ici. 

Merci de votre aide.

70
Alex Wulff

Cela a fait le tour pour moi! 

Objectif c:

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

Rapide:

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

Swift 2 (solution alternative)

Ajouter cette méthode de remplacement à votre ViewController

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

Swift 3 & 4 (modification de syntaxe)

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

Toutes les réponses ci-dessus n'ont pas fonctionné pour moi. Cependant, le secret consiste à implémenter votre solution dans le cadre d'une substitution de viewDidLayoutSubviews, comme dans:

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

HTH :)

51
zeeple

Dans Swift 2

Vous pouvez utiliser ceci pour faire démarrer textView depuis le haut:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    myTextView.setContentOffset(CGPointZero, animated: false)
}

Confirmation de l'utilisation de Xcode 7.2 avec Swift 2

14
Nick89

Essayez ce code ci-dessous -

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

Ou vous pouvez également définir cette propriété par StoryBoard -

Sélectionnez ViewController puis sélectionnez l'inspecteur d'attributs maintenant décochée Adjust Scroll View Insets.

12
keshav vishwkarma

Pour Swift> 2.2, j'ai eu des problèmes avec iOS 8 et iOS 9 en utilisant les méthodes ci-dessus car il n'y a pas de réponse unique qui fonctionne, donc voici ce que j'ai fait pour que cela fonctionne pour les deux.

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

Avec beaucoup de tests, j'ai trouvé qu'il faut ajouter ci-dessous dans la fonction viewWillLayoutSubviews () pour s'assurer que UITextView s'affiche dès le début:

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

Mettez à jour la propriété translucent de votre UINavigationBar sur NO:

self.navigationController.navigationBar.translucent = NO;

Cela empêchera la vue d'être encadrée sous la barre de navigation et la barre d'état.

Si vous devez afficher et masquer la barre de navigation, utilisez le code ci-dessous dans votre viewDidLoad

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

J'espère que cela t'aides.

5
Mrunal

UITextView défiler semble être un problème pour beaucoup de gens. Rassemblant à partir des réponses fournies ici (en particulier this ) et de la documentation du développeur Apple, en utilisant une partie de mon esprit, voici une solution qui fonctionne pour moi. Vous pouvez modifier le code en fonction de vos besoins.

Mon cas d'utilisation est le suivant: la même UITextView est utilisée à des fins différentes, affichant un contenu variable dans différentes circonstances. Ce que je veux, c'est que lorsque le contenu change, l'ancienne position de défilement soit restaurée, ou parfois défilée jusqu'à la fin. Je ne veux pas trop d'animation lorsque cela est fait. En particulier, je ne veux pas que la vue s'anime comme si tout le texte était nouveau. Cette solution rétablit d’abord l’ancienne position de défilement sans animation, puis défile jusqu’à la fin animée, si vous le souhaitez.

Ce que vous devez faire (ou devrais-je dire can do) est d’étendre UITextView comme suit:

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

Cela met à jour le texte, utilise ensuite une valeur stockée de la propriété UITextView.contentOffset (ou tout ce que vous transmettez en tant que paramètre) et définit le décalage de la vue en conséquence. Si vous le souhaitez, il passe ensuite à la fin du nouveau contenu potentiellement modifié.

Je suis nouveau dans la programmation iOS et je ne sais pas pourquoi cela fonctionne si bien. Si quelqu'un a quelques informations à ce sujet, il serait bon de le savoir. De plus, l'approche peut ne pas être parfaite, alors je suis également ouvert aux idées d'amélioration.

Et bien sûr, merci à NixonsBack pour avoir posté la réponse derrière le lien ci-dessus.

Mon premier post :), à la vôtre!

4
ipe

Le code suivant devrait vous donner l'effet que vous voulez.

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

Vous devrez remplacer "self.scrollView" par le nom de votre vue de défilement. Vous devez insérer ce code après avoir défini le texte de la vue de défilement.

3
Gary Riches

Mettez cette ligne de code dans ViewDidLoad

self.automaticallyAdjustsScrollViewInsets = false
3
Murat Yasar

Cela a fonctionné pour moi: 

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

}
2
bpolat

Cela a fonctionné pour moi avec Xcode 8.3.3:

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

Créez un point de vente pour votre UITextView dans le fichier ViewController.Swift. Dans la section ViewDidLoad, indiquez ce qui suit:

Rapide:

self.textView.contentOffset.y = 0

J'ai essayé:

self.textView.scrollRangeToVisible(NSMakeRange(0, 0))
2
J.Bury

J'ai traduit la réponse de zeeple en MonoTouch/Xamarin (C #).

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

J'ai dû implémenter deux réponses ici pour que mon point de vue fonctionne comme je le souhaite:

De Juan David Cruz Serrano:

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

Et de Murat Yasar:

automaticallyAdjustsScrollViewInsets = false

Cela a donné une UITextView qui se charge avec le défilement tout en haut et où les incrustations ne sont pas modifiées une fois le défilement lancé. Très étrange que ce n'est pas le comportement par défaut.

0
Leon

Swift 4.2 & Swift 5

définir le contenu du décalage avant et après la définition du texte. (sur le fil principal)

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)
0
Amirca

Pour forcer la textView à commencer en haut à chaque fois, utilisez le code suivant:

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
ARGeo