2009-11-16 65 views
2

我有一個NSTextView,我想要顯示一個水平滾動條。在互聯網上的一些線索後,我的大部分工作,除了我有垂直滾動條的問題。如何在水平調整包含NSTextView的大小時將NSScrollView從滾動頂部停止?

我所做的是找到最長行的寬度(以給定字體的像素爲單位),然後適當調整NSTextContainer和NSTextView的大小。這樣水平滾動條代表寬度,向右滾動將滾動到最長行文本的末尾。

完成這項工作之後,我注意到我的NSScrollView會在我輸入時顯示和隱藏垂直滾動條。我通過在調整大小之前將autohidesScrollers設置爲NO,然後在YES之後「修復」了這個問題。但是,仍然存在另一個問題,在我輸入時,垂直滾動條thumb跳轉到滾動條的頂部並返回到我輸入的正確位置。我輸入'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]; 
     } 
    } 
} 

回答

2

由於在Cocoa-Dev list羅斯卡特的post,我解決了這個問題。

答:你必須設置你的文本視圖,支持水平滾動:

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

B.你必須更新文本視圖的寬度,因爲它的變化,否則,水平滾動條沒有按」 t更新正確:

- (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]; 
    } 
} 
相關問題