web-dev-qa-db-fra.com

UITextView n'est pas défilé vers le haut lorsqu'il est chargé

Lorsque j'ai un texte qui ne remplit pas UITextView, il défile vers le haut et fonctionne comme prévu. Lorsqu'il y a plus de texte que ce qui peut en contenir à l'écran, UITextView défile au centre du texte plutôt qu'au haut.

Voici quelques détails potentiellement pertinents:

Dans viewDidLoad pour donner un peu de remplissage en haut et en bas de UITextView:

self.mainTextView.textContainerInset = UIEdgeInsetsMake(90, 0, 70, 0);

UITextView utilise la mise en page automatique pour l'ancrer 20px du haut, du bas et de chaque côté de l'écran (en IB) afin de permettre différentes tailles et orientations d'écran.

Je peux toujours le faire défiler avec mon doigt une fois chargé.

EDIT J'ai constaté que le fait de supprimer les contraintes de mise en page automatique, puis de fixer la largeur, semble résoudre uniquement le problème, mais uniquement pour cette largeur d'écran.

38
Michael Campsall

UITextView est une sous-classe de UIScrollView, vous pouvez donc utiliser ses méthodes. Si tout ce que vous voulez faire est de vous assurer que le texte défile jusqu'en haut, alors, où que le texte soit ajouté, essayez:

[self.mainTextView setContentOffset:CGPointZero animated:NO];

EDIT: AutoLayout avec n'importe quel type de scrollview devient wickky rapidement. Ce réglage d'une largeur fixe résout, ce n'est pas surprenant. Si cela ne fonctionne pas dans -viewDidLayoutSubviews, alors c'est étrange. La définition manuelle d’une contrainte d’agencement peut fonctionner. Créez d'abord les contraintes dans IB: 

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *textViewWidthConstraint;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *textViewHeightConstraint;

puis dans le ViewController

    -(void)updateViewConstraints {
            self.textViewWidthConstraint.constant = self.view.frame.size.width - 40.0f;
            self.textViewHeightConstraint.constant = self.view.frame.size.height - 40.0f;
            [super updateViewConstraints];
        }

Peut-être encore nécessaire de définirContentOffset dans -viewDidLayoutSubviews.

(Une autre méthode consisterait à créer une contrainte de mise en page pour "'égales'" et "'égales" »entre textView et son superView, avec une constante de" -40 ". Elle n'est" égale "que si la constante est égale à zéro. sinon, la constante est ajustée, mais comme vous ne pouvez ajouter que cette contrainte à une vue qui contraint les deux vues, vous ne pouvez pas le faire dans IB.) 

Vous pouvez vous demander, si je dois faire cela, à quoi sert AutoLayout? J'ai étudié AutoLayout en profondeur et c'est une excellente question. 

17
Mike Sand

ajoutez la fonction suivante à votre classe de contrôleur de vue ... 

Swift 3

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

Swift 2.1

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

Objectif c

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

j'ai eu le même problème! Réinitialiser sur les contraintes suggérées et mettre juste (décalage y)

@IBOutlet weak var textContent: UITextView!

    override func viewDidLoad() {
        textContent.scrollsToTop = true
        var contentHeight = textContent.contentSize.height
        var offSet = textContent.contentOffset.x
        var contentOffset = contentHeight - offSet
        textContent.contentOffset = CGPointMake(0, -contentOffset)
    }
9
Ruso

Rapide

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

Objectif c

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

Pour iOS9 et les versions ultérieures, textview même sur viewWillAppear: arrive avec CGRect (0,0,1000,1000). Pour que cela fonctionne, vous devez appeler dans viewWillAppear:

[self.view setNeedsLayout];
[self.view layoutIfNeeded];
// * Your code here

Ensuite, textview disposera des données CGRect correctes et vous pourrez effectuer toutes les opérations de défilement dont vous pourriez avoir besoin.

6
iPav

Si vous ne voulez pas jouer avec les contraintes:

override func updateViewConstraints() {
    super.updateViewConstraints()
}

override func viewDidLayoutSubviews() {
    self.textLabel.setContentOffset(CGPointZero, animated: false)
}
1
Gustavo Severo

Le problème avec l'insertion de code dans viewDidLayoutSubviews et viewWillLayoutSubviews est que ces méthodes s'appellent beaucoup (lors de la rotation du périphérique, du redimensionnement des vues, etc.). Si vous lisez quelque chose à partir de la vue texte et que vous faites pivoter l'appareil, vous vous attendez à ce que la partie du contenu que vous visualisez reste à l'écran. Vous ne vous attendez pas à ce que cela revienne au début. Au lieu de faire défiler le contenu vers le haut, essayez de conserver la propriété scrollEnabled de la vue texte sur NO (false), puis réactivez-la dans viewDidAppear.

1
Jovan Stankovic

C'est un bug intéressant. Dans notre projet, cela ne se produit que sur les appareils dotés d'un écran de taille iPhone 5-. Il semble que textview contentOffset change à un moment donné au cours du cycle de vie du contrôleur de vue. Dans viewDidLoad et viewWillAppear, la contentOffset de textview est 0,0 et, par viewDidAppear, elle a changé. Vous pouvez le voir se passer dans viewWillLayoutSubviews. Les contraintes semblent être correctement configurées.

Cela garantira que vous n'appelez pas une méthode de défilement à moins que cela ne soit nécessaire:

if textView.contentOffset.y > 0 {
    textView.contentOffset = CGPoint(x: 0, y: 0)
    // Or use scrollRectToVisible, scrollRangeToVisible, etc.
}
1
Evan R

Rapide

override func viewDidLoad() {
    super.viewDidLoad()  
    textView.isScrollEnabled = false  
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    textView.isScrollEnabled = true
}
0