NSSCrollView가 NSTEXTVIEW를 수평으로 크기로 변경할 때 NSSCrollView를 스크롤하여 상단으로 중지하는 방법은 무엇입니까?

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

문제

수평 스크롤 막대를 표시하고 싶은 nstextView가 있습니다. 인터넷에서 일부 리드에 따라 수직 스크롤 막대에 문제가 있다는 점을 제외하고는 대부분 작동합니다.

내가 한 일은 가장 긴 줄의 너비 (주어진 글꼴이있는 픽셀)를 찾은 다음 NstextContainer와 NstextView를 적절하게 크기를 조정하는 것입니다. 이런 식으로 수평 스크롤 막대는 너비를 대표하며 오른쪽으로 스크롤하면 가장 긴 텍스트 라인의 끝까지 스크롤됩니다.

이 작업을 수행 한 후 NSSCrollView가 입력 한대로 수직 스크롤 막대를 보여주고 숨길 것임을 알았습니다. AutoHidessCrollers를 크기를 조정하기 전에 NO로 설정 하여이 문제를 '고정'하고 나중에 그렇습니다. 그러나 여전히 수직 스크롤 바가 입력 한 또 다른 문제가 여전히 남아 있습니다. 무지 스크롤 바의 상단으로 점프하고 타이핑 할 때 적절한 위치로 돌아갑니다. 나는 'a'를 입력한다u003Cspace> , 그것은 상단으로 점프합니다.u003Cspace> 다시하고 그것은 적절한 위치로 돌아갑니다.

이견있는 사람?

다음은 샘플 코드입니다.

- (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];
        }
    }   
}
도움이 되었습니까?

해결책

로스 카터 덕분에 감사합니다 게시하다코코아 데브 목록, 나는이 문제를 해결했다.

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