كيفية وقف NSScrollView من التمرير إلى أعلى عند أفقيا تغيير حجم الواردة NSTextView؟

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

سؤال

ولدي NSTextView أنني أريد أن عرض شريط التمرير الأفقي. وبعد بعض الخيوط على شبكة الانترنت، ولدي أكثر من ذلك العمل، إلا أنني أواجه مشاكل مع شريط التمرير العمودي.

وماذا فعلت هو العثور على عرض أطول خط (بالبكسل مع الخط معين) وبعد ذلك تغيير حجم NSTextContainer وNSTextView بشكل مناسب. بهذه الطريقة شريط التمرير الأفقي هو ممثل للعرض والتمرير إلى اليمين وانتقل إلى نهاية أطول خط من النص.

وبعد القيام بهذا العمل، لاحظت أن بلدي NSScrollView أن إظهار وإخفاء شريط التمرير العمودي لأنني كتبته. لقد "ثابتة" هذه المشكلة عن طريق وضع autohidesScrollers إلى NO قبل تغيير الحجم ثم YES بعد ذلك. ومع ذلك، لا يزال هناك مشكلة أخرى حيث، وأنا اكتب، شريط التمرير العمودي <م> الإبهام يقفز إلى أعلى شريط التمرير والعودة إلى المكان المناسب وأنا اكتب. أنا اكتب 'ا' <مساحة>، فإنه يقفز إلى الأعلى، واضغط على <مساحة> مرة أخرى، ويقفز مرة أخرى إلى الموقع الصحيح.

وأي أفكار؟

وهنا بعض نموذج التعليمات البرمجية:

- (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];
        }
    }   
}
هل كانت مفيدة؟

المحلول

آخر روس كارتر على الكاكاو ديف قائمة ، I حل هذه المشكلة.

و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