Como impedir que o NSSCROLLVIEW rolate para o topo quando o redimensionamento horizontal continha o NSTEXTVIEL?
-
20-09-2019 - |
Pergunta
Eu tenho um nstextview que quero exibir uma barra de rolagem horizontal. Seguindo alguns leads na Internet, tenho a maior parte do trabalho, exceto que estou tendo problemas com a barra de rolagem vertical.
O que fiz é encontrar a largura da linha mais longa (em pixels com a fonte fornecida) e depois redimenso o NSTEXTCONTAINER e o NSTEXTVIEW adequadamente. Dessa forma, a barra de rolagem horizontal é representativa da largura e a rolagem para a direita rolará até o final da linha de texto mais longa.
Depois de fazer esse trabalho, notei que meu NSSCROLLVIEW mostraria e ocultaria a barra de rolagem vertical conforme eu digitei. Eu 'corrigi' esse problema definindo o AutoHidessCrollers como NO antes do redimensionamento e depois sim depois. No entanto, ainda há outro problema em que, como eu digito, a barra de rolagem vertical dedão Salta para o topo da barra de rolagem e volta para o lugar apropriado enquanto eu digito. Eu digito 'a'u003Cspace> , ele pula para o topo, eu pressiono ou003Cspace> Novamente e ele salta de volta para o local adequado.
Alguma ideia?
Aqui está algum código de exemplo:
- (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];
}
}
}
Solução
Graças ao Ross Carter's publicar no Lista de cacau-dev, Eu resolvi esse problema.
R. Você precisa configurar sua visualização de texto para apoiar a rolagem horizontal:
- (void)awakeFromNib {
[myTextView setHorizontallyResizable:YES];
NSSize tcSize = [[myTextView textContainer] containerSize];
tcSize.width = FLT_MAX;
[[myTextView textContainer] setContainerSize:tcSize];
[[myTextView textContainer] setWidthTracksTextView:NO];
}
B. Você deve atualizar a largura da visualização do texto à medida que ela muda, caso contrário, a barra de rolagem horizontal não atualiza corretamente:
- (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];
}
}