gpt4 book ai didi

cocoa - 当水平调整包含的 NSTextView 大小时,如何阻止 NSScrollView 滚动到顶部?

转载 作者:行者123 更新时间:2023-12-03 16:39:42 26 4
gpt4 key购买 nike

我有一个 NSTextView,我想显示水平滚动条。按照互联网上的一些线索,我的大部分功能都可以正常工作,除了垂直滚动条出现问题。

我所做的是找到最长线的宽度(以给定字体的像素为单位),然后适当调整 NSTextContainer 和 NSTextView 的大小。这样水平滚动条代表宽度,向右滚动将滚动到最长文本行的末尾。

完成这项工作后,我注意到我的 NSScrollView 会在我键入时显示和隐藏垂直滚动条。我通过在调整大小之前将 autohidesScrollers 设置为“否”,然后在调整大小之后设置为"is"来“修复”了这个问题。然而,仍然存在另一个问题,当我键入时,垂直滚动条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];
}
}
}

最佳答案

感谢罗斯·卡特的postCocoa-Dev list ,我解决了这个问题。

A.您必须设置 TextView 以支持水平滚动:

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

B.您必须在 TextView 的宽度发生变化时更新它,否则水平滚动条无法正确更新:

- (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];
}
}

关于cocoa - 当水平调整包含的 NSTextView 大小时,如何阻止 NSScrollView 滚动到顶部?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1744945/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com