Wie NSScrollView von Scrollen nach oben zu stoppen, wenn horizontal NSTextView enthalten resizing?
-
20-09-2019 - |
Frage
Ich habe eine NSTextView, dass ich eine horizontale Bildlaufleiste angezeigt werden soll. Nach einigen Leitungen im Internet, habe ich die meisten davon arbeiten, außer, dass ich Probleme mit der vertikalen Bildlaufleiste habe.
Was ich getan habe ist, die Breite der längsten Zeile zu finden (in Pixeln mit dem angegebenen Schrift) und dann die Größe ich die NSTextContainer und die NSTextView angemessen. Auf diese Weise der horizontale Bildlaufleiste ist repräsentativ für die Breite und Scrollen nach rechts bis zum Ende der längsten Textzeile scrollt.
Nachdem diese Arbeit tat, bemerkte ich, dass mein NSScrollView zeigen würde, und die vertikale Bildlaufleiste ausgeblendet, wie ich getippt. Ich habe ‚fixed‘ dieses Problem, indem autohidesScrollers zu NO vor der Größe ändern und dann YES danach einstellen. Allerdings gibt es immer noch ein weiteres Problem, wo, wie ich geben, die vertikale Bildlaufleiste Daumen springt an die Spitze der Scrollbar und zurück an die richtige Stelle, wie ich geben. Ich tippe ‚a‘
Alle Gedanken?
Hier ist ein Beispielcode:
- (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];
}
}
}
Lösung
Dank Ross Carter Post auf die Cocoa-Dev Liste , ich dieses Problem behoben.
A. Sie müssen Ihre Textansicht einrichten horizontales Scrollen unterstützen:
- (void)awakeFromNib {
[myTextView setHorizontallyResizable:YES];
NSSize tcSize = [[myTextView textContainer] containerSize];
tcSize.width = FLT_MAX;
[[myTextView textContainer] setContainerSize:tcSize];
[[myTextView textContainer] setWidthTracksTextView:NO];
}
B. Sie haben die Breite der Textansicht zu aktualisieren, da sie sich ändert, sonst wird die horizontale Scroll-Leiste nicht ordnungsgemäß aktualisiert werden:
- (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];
}
}