水平に含まれるNSTextViewのサイズを変更する際トップにスクロールからNSScrollViewを停止する方法?

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

質問

私は、水平スクロールバーを表示したいNSTextViewを持っています。インターネット上のいくつかのリードに続いて、私はそれのほとんどは、私が垂直スクロールバーで問題がありますことを除いて、作業しています。

私が行っていることは(与えられたフォントとピクセル単位で)最長の線の幅を見つけることですし、私はNSTextContainerとNSTextView適切にサイズ変更します。このように水平スクロールバーの幅の代表とテキストの最長行の最後までスクロールします右にスクロールされます。

この仕事をした後、私は私が入力されたとして私NSScrollViewは、垂直スクロールバーを表示し、隠すということに気づきました。私は、サイズ変更前にして、YES、その後NOにautohidesScrollersを設定することで、この問題を「固定」しました。しかし、まだ私は入力として、垂直スクロールバーの親指がの適切な場所に戻ってスクロールバーの一番上にジャンプして、私が入力すると、別の問題が残っています。私は「A」を入力し、それが一番上にジャンプし、私は再び、を押すと、それが適切な場所に戻ってジャンプします。

任意の考え?

ここではいくつかのサンプルコードは、次のとおりです。

- (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];
        }
    }   
}
役に立ちましたか?

解決

ロス・カーターのポストの上に感謝ココア-devメーリングリストに、私はこの問題を解決します。

A。あなたは、水平スクロールをサポートするために、テキストビューを設定する必要があります:

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

B。あなたはそれ以外の場合は、水平スクロールバーが正しく更新されない、それが変わるとテキストビューの幅を更新する必要があります:

- (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];
    }
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top