Comment arrêter NSScrollView de défilement vers le haut lors du redimensionnement horizontal NSTextView contenue?

StackOverflow https://stackoverflow.com/questions/1744945

Question

J'ai NSTextView que je veux afficher une barre de défilement horizontale. Après quelques pistes sur Internet, j'ai la plus grande partie de travail, sauf que je rencontre des problèmes avec la barre de défilement vertical.

Ce que je l'ai fait est de trouver la largeur de la ligne la plus longue (en pixels avec la police donnée) puis je redimensionner la NSTextContainer et la NSTextView appropriée. De cette façon, la barre de défilement horizontale est représentative de la largeur et le défilement vers la droite défiler jusqu'à la fin de la plus longue ligne de texte.

Après avoir fait ce travail, je remarquai que mon NSScrollView montrerait et cacher la barre de défilement verticale comme je l'ai tapé. Je suis « fixe » ce problème en réglant autohidesScrollers NO avant la Redimensionner puis YES après. Cependant, il reste encore un autre problème où, comme je tape, la barre de défilement vertical pouce saute au-dessus de la barre de défilement et de retour à la place que je tape. Type I « a » , il saute vers le haut, j'appuie sur la touche nouveau et il saute à l'emplacement approprié.

Toutes les pensées?

Voici quelques exemples de code:

- (CGFloat)longestLineOfText
{
    CGFloat longestLineOfText = 0.0;

    NSRange lineRange;

    NSString* theScriptText = [myTextView string];

    NSDictionary* attributesDict = [NSDictionary dictionaryWithObject:scriptFont forKey:NSFontAttributeName]; //scriptFont is a instance variable

    NSUInteger characterIndex = 0;
    NSUInteger stringLength = [theScriptText length];

    while (characterIndex < stringLength) {
        lineRange = [theScriptText lineRangeForRange:NSMakeRange(characterIndex, 0)];

        NSSize lineSize = [[theScriptText substringWithRange:lineRange] sizeWithAttributes:attributesDict];
        longestLineOfText = max(longestLineOfText, lineSize.width);

        characterIndex = NSMaxRange(lineRange);
    }

    return longestLineOfText;

}

// ----------------------------------------------------------------------------

- (void)updateMyTextViewWidth
{
    static CGFloat previousLongestLineOfText = 0.0;

    CGFloat currentLongestLineOfText = [self longestLineOfText];
    if (currentLongestLineOfText != previousLongestLineOfText) {
        BOOL shouldStopBlinkingScrollBar = (previousLongestLineOfText < currentLongestLineOfText);
        previousLongestLineOfText = currentLongestLineOfText;

        NSTextContainer* container = [myTextView textContainer];
        NSScrollView* scrollView = [myTextView enclosingScrollView];
        if (shouldStopBlinkingScrollBar) {
            [scrollView setAutohidesScrollers:NO];
        }

        CGFloat padding = [container lineFragmentPadding];

        NSSize size = [container containerSize];
        size.width = currentLongestLineOfText + padding * 2;
        [container setContainerSize:size];

        NSRect frame = [myTextView frame];
        frame.size.width = currentLongestLineOfText + padding * 2;
        [myTextView setFrame:frame];

        if (shouldStopBlinkingScrollBar) {
            [scrollView setAutohidesScrollers:YES];
        }
    }   
}
Était-ce utile?

La solution

Merci à Ross Carter après le liste Cocoa-Dev , je résolu cette question.

A. Vous devez configurer votre point de vue de texte pour soutenir le défilement horizontal:

- (void)awakeFromNib {
    [myTextView setHorizontallyResizable:YES];
    NSSize tcSize = [[myTextView textContainer] containerSize];
    tcSize.width = FLT_MAX;
    [[myTextView textContainer] setContainerSize:tcSize];
    [[myTextView textContainer] setWidthTracksTextView:NO];
}

B. Vous devez mettre à jour la largeur de la vue texte tel qu'il change, sinon la barre de défilement horizontale ne met pas à jour correctement:

- (void)textDidChange:(NSNotification *)notification
{
    [self updateTextViewWidth];
}

- (CGFloat)longestLineOfText
{
    CGFloat longestLineOfText = 0.0;

    NSLayoutManager* layoutManager = [myTextView layoutManager];

    NSRange lineRange;
    NSUInteger glyphIndex = 0;
    NSUInteger glyphCount = [layoutManager numberOfGlyphs];
    while (glyphIndex < glyphCount) {

        NSRect lineRect = [layoutManager lineFragmentUsedRectForGlyphAtIndex:glyphIndex
                                                              effectiveRange:&lineRange
                                                     withoutAdditionalLayout:YES];

        longestLineOfText = max(longestLineOfText, lineRect.size.width);

        glyphIndex = NSMaxRange(lineRange);
    }

    return longestLineOfText;

}

// ----------------------------------------------------------------------------

- (void)updateTextViewWidth
{
    static CGFloat previousLongestLineOfText = 0.0;

    CGFloat currentLongestLineOfText = [self longestLineOfText];
    if (currentLongestLineOfText != previousLongestLineOfText) {
        previousLongestLineOfText = currentLongestLineOfText;

        NSTextContainer* container = [myTextView textContainer];
        CGFloat padding = [container lineFragmentPadding];

        NSRect frame = [myTextView frame];
        frame.size.width = currentLongestLineOfText + padding * 2;
        [myTextView setFrame:frame];
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top