我有一个NSTextView,我想显示一个水平滚动条。在互联网上的一些线索之后,我的大部分工作都在工作,除了我遇到垂直滚动条的问题。
我所做的是找到最长行的宽度(以给定字体为单位的像素)然后我适当地调整NSTextContainer和NSTextView的大小。这样,水平滚动条代表宽度,向右滚动将滚动到最长文本行的末尾。
完成这项工作后,我注意到我的NSScrollView会在输入时显示和隐藏垂直滚动条。我通过在调整大小之前将autohidesScrollers设置为NO然后在之后设置为YES来“修复”此问题。但是,仍然存在另一个问题,当我键入时,垂直滚动条 thumb 跳转到滚动条的顶部并在我键入时返回到正确的位置。我输入'a'< space>,它跳到顶部,我按< space>再次,它跳回到正确的位置。
有什么想法吗?
以下是一些示例代码:
- (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];
}
}
}
答案 0 :(得分:2)
感谢{* 3}}上的Ross Carter post,我解决了这个问题。
一个。您必须设置文本视图以支持水平滚动:
- (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];
}
}