Come fermare NSScrollView da scorrimento verso l'alto quando il ridimensionamento orizzontale contenuta NSTextView?

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

Domanda

Ho un NSTextView che voglio visualizzare una barra di scorrimento orizzontale. Dopo qualche porta su internet, ho la maggior parte di esso di lavoro, se non che io sto avendo problemi con la barra di scorrimento verticale.

Quello che ho fatto è quello di trovare la larghezza della linea più lunga (in pixel con il font data) e poi ho ridimensionare il NSTextContainer e la NSTextView in modo appropriato. In questo modo la barra di scorrimento orizzontale rappresentativa della larghezza e lo scorrimento a destra si scorrere fino alla fine della riga di testo più lunga.

Dopo aver fatto questo lavoro, ho notato che la mia NSScrollView sarebbe mostrare e nascondere la barra di scorrimento verticale, come ho digitato. Ho 'fixed' questo problema impostando autohidesScrollers a NO prima del ridimensionamento e poi YES dopo. Tuttavia, rimane ancora un altro problema in cui, mentre sto scrivendo, la barra di scorrimento verticale pollice salta alla parte superiore della barra di scorrimento e di nuovo al posto adeguato mentre scrivo. I tipo 'a' , salta verso l'alto, premo il di nuovo e ritorna nella posizione corretta.

Qualche idea?

Ecco alcuni esempi di codice:

- (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];
        }
    }   
}
È stato utile?

Soluzione

Grazie a Ross Carter posta sulla Cocoa Dev-list , ho risolto questo problema.

A. È necessario impostare la visualizzazione del testo per supportare lo scorrimento orizzontale:

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

B. È necessario aggiornare la larghezza della visualizzazione del testo come cambia, altrimenti la barra di scorrimento orizzontale non aggiorna correttamente:

- (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];
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top