web-dev-qa-db-fra.com

UITextView contentOffset sur iOS 7

J'ai un UITextView dans mon application. J'ai besoin de changer son contenu de manière dynamique, chaque fois qu'une nouvelle chaîne est ajoutée. Le code ci-dessous fonctionne très bien sur iOS 6 et les versions antérieures, mais pas sur iOS 7.

CGPoint offset = CGPointMake(0, self.textView.contentSize.height - self.textView.frame.size.height);
[self.textView setContentOffset:bottomOffset animated:YES]; 

Avez-vous des idées pourquoi?

Que toi.

METTRE À JOUR

UITextView ne définit pas son contentOffset comme il se doit, ou quelque chose d'autre le dérange. Le résultat n'est pas celui attendu (comme sur iOS 6 ou les versions antérieures).

J'ai également essayé de définir la nouvelle propriété "textContainerInset" mais toujours aucun résultat ...

self.textView.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0)    

METTRE À JOUR

Comme je peux le voir dans la méthode déléguée didScroll, lorsque je passe une valeur positive pour le décalage de contenu, il fait défiler jusqu'à (0,0). Par exemple, je règle l'offset de contenu sur (0,35) et le défilement sur (0,0) ...

16
Mihai Ghete

Ok, d’après mes recherches et d’autres réponses, le problème était la hauteur du contenu de UITextView et non le défilement vers un décalage spécifique. Voici une solution qui fonctionne comme il le devrait pour iOS 7:

Tout d’abord, vous devez recréer le UITextView comme ceci:

    NSString *reqSysVer = @"7.0";
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
    BOOL osVersionSupported = ([currSysVer compare:reqSysVer  options:NSNumericSearch] != NSOrderedAscending);

    if (osVersionSupported) {

        NSLog(@"reset chatoutput");

        CGRect outputFrame = self.chatOutput.frame;

        [chatOutput removeFromSuperview];
        [chatOutput release];
        chatOutput = nil;

        NSTextStorage* textStorage = [[NSTextStorage alloc] init];
        NSLayoutManager* layoutManager = [NSLayoutManager new];
        [textStorage addLayoutManager:layoutManager];
        NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:self.view.bounds.size];
        [layoutManager addTextContainer:textContainer];
        chatOutput = [[UITextView alloc] initWithFrame: outputFrame
                                           textContainer: textContainer];
        // if using ARC, remove these 3 lines
        [textContainer release];
        [layoutManager release];
        [textStorage release];

        [self.view addSubview: chatOutput];
    }

Ensuite, utilisez cette méthode pour obtenir la hauteur de contenu UITextView:

- (CGFloat)textViewHeightForAttributedText:(NSAttributedString*)text andWidth:(CGFloat)width
{
     UITextView *calculationView = [[UITextView alloc] init];
     [calculationView setAttributedText:text];
     CGSize size = [calculationView sizeThatFits:CGSizeMake(width, FLT_MAX)];

     NSLog(@"size: %f", size.height) ;

     return size.height;
}

Maintenant, vous pouvez définir le décalage du contenu:

CGPoint bottomOffset;

bottomOffset = CGPointMake(0, [self textViewHeightForAttributedText: self.chatOutput.attributedText andWidth: self.chatOutput.frame.size.width] - self.chatOutput.frame.size.height);

[self.chatOutput setContentOffset:bottomOffset animated:YES];

METTRE À JOUR

J'ai lu ceci dans la documentation Apple pour NSAttributedString: "La police par défaut des objets NSAttributedString est Helvetica 12 points, qui peut être différente de la police système par défaut de la plate-forme."

En conclusion, si vous utilisez différentes polices de différentes tailles, vous devez également les définir sur l'instance NSAttributeString. Sinon, la hauteur retournée ne correspondra pas à vos attentes. Vous voudrez peut-être utiliser quelque chose comme ceci:

    NSDictionary *attrsDictionary = [NSDictionary dictionaryWithObject: [UIFont systemFontOfSize: 18.0] //or any other font or size
                                                                forKey: NSFontAttributeName];
    NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString: currentPost.postMessageText attributes: attrsDictionary];
    frame.size.height = [self textViewHeightForAttributedText: attributedString andWidth: 280.0];
    [attributedString release];
4
Mihai Ghete

La solution que j'ai trouvée n'est pas élégante du tout, mais ça marche:

Je règle le contentOffset de UITextView sur (0,0) avant de le régler sur le décalage souhaité. Je ne sais pas pourquoi cela fonctionne, mais pour l'instant, c'est la meilleure solution que j'ai trouvée.

CGPoint bottomOffset = CGPointMake(0, self.textView.contentSize.height - self.textView.frame.size.height);
[self.textView setContentOffset: CGPointMake(0,0) animated:NO]; 
[self.textView setContentOffset:bottomOffset animated:YES]; 
7
Mihai Ghete

Je viens de remarquer cela aujourd'hui. Dans mon cas, le problème est apparemment lié au fait que la vue texte est le premier contrôle de la vue. Je l'ai déplacé à la deuxième place dans le contour du document (après un UILabel par exemple) et le décalage est parti.

Très probablement, cela est fait exprès en raison du nouveau comportement de la barre de navigation dans iOS7.

5
vidonism

@ - vidonism's answer fonctionne mais c'est encore mieux.

// in -viewDidLoad of UIViewController
self.automaticallyAdjustsScrollViewInsets = NO;

Voir aussi le commentaire supérieur de la réponse acceptée sur cette question . Cela explique probablement le comportement d'un UIScrollView en tant que première sous-vue de la vue principale d'un ViewController.
Je ne peux pas tout à fait comprendre s'il s'agit d'un comportement attendu ou d'un bogue.

2
race_carr

Aucune des réponses précédentes n'a fonctionné pour moi, car j'avais [textView setScrollEnabled:NO]. Alors, j'ai fini avec ça:

[textView setScrollEnabled:YES]
[self.text setContentOffset:CGPointMake(0, page * self.text.frame.size.height) animated:NO];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [self.text setScrollEnabled:NO];
});
0
Artem

J'ai dû recourir à

[displayText scrollRangeToVisible:NSMakeRange([displayText.text length], 0)];

mais le gros problème avec cela, c'est qu'il commence par le haut du texte et défile jusqu'à la fin chaque fois que vous ajoutez du texte. La solution de Mihai le fait également.

0
Nelson Ko