¿Cómo detener NSScrollView de desplazamiento hacia arriba cuando el cambio de tamaño horizontal contenida NSTextView?
-
20-09-2019 - |
Pregunta
Tengo un NSTextView que quiero mostrar una barra de desplazamiento horizontal. Después de algunos conductores en el Internet, tengo la mayor parte de trabajo, excepto que estoy teniendo problemas con la barra de desplazamiento vertical.
Lo que he hecho es encontrar el ancho de la línea más larga (en píxeles con la fuente dada) y luego cambiar el tamaño de la NSTextContainer y la NSTextView adecuadamente. De esta manera la barra de desplazamiento horizontal es representativa de la anchura y el desplazamiento a la derecha, se desplazará hasta el final de la línea más larga de texto.
Después de hacer este trabajo, me di cuenta de que mi NSScrollView sería mostrar y ocultar la barra de desplazamiento vertical mientras escribía. He 'fijo' este problema estableciendo autohidesScrollers a NO antes del cambio de tamaño y luego SÍ después. Sin embargo, todavía existe otro problema en que, mientras escribo, la barra de desplazamiento vertical pulgar salta a la parte superior de la barra de desplazamiento y de vuelta al lugar apropiado mientras se escribe. Me tipo 'A'
¿Alguna idea?
Aquí hay algunos ejemplos de código:
- (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];
}
}
}
Solución
Gracias a Ross Carter puesto en el Cacao-Dev lista , que resuelve este problema.
A. Usted tiene que configurar su vista de texto para apoyar el desplazamiento horizontal:
- (void)awakeFromNib {
[myTextView setHorizontallyResizable:YES];
NSSize tcSize = [[myTextView textContainer] containerSize];
tcSize.width = FLT_MAX;
[[myTextView textContainer] setContainerSize:tcSize];
[[myTextView textContainer] setWidthTracksTextView:NO];
}
B. Usted tiene que actualizar el ancho de la vista de texto a medida que cambia, de lo contrario la barra de desplazamiento horizontal no actualiza correctamente:
- (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];
}
}