NSSCrollView가 NSTEXTVIEW를 수평으로 크기로 변경할 때 NSSCrollView를 스크롤하여 상단으로 중지하는 방법은 무엇입니까?
-
20-09-2019 - |
문제
수평 스크롤 막대를 표시하고 싶은 nstextView가 있습니다. 인터넷에서 일부 리드에 따라 수직 스크롤 막대에 문제가 있다는 점을 제외하고는 대부분 작동합니다.
내가 한 일은 가장 긴 줄의 너비 (주어진 글꼴이있는 픽셀)를 찾은 다음 NstextContainer와 NstextView를 적절하게 크기를 조정하는 것입니다. 이런 식으로 수평 스크롤 막대는 너비를 대표하며 오른쪽으로 스크롤하면 가장 긴 텍스트 라인의 끝까지 스크롤됩니다.
이 작업을 수행 한 후 NSSCrollView가 입력 한대로 수직 스크롤 막대를 보여주고 숨길 것임을 알았습니다. AutoHidessCrollers를 크기를 조정하기 전에 NO로 설정 하여이 문제를 '고정'하고 나중에 그렇습니다. 그러나 여전히 수직 스크롤 바가 입력 한 또 다른 문제가 여전히 남아 있습니다. 무지 스크롤 바의 상단으로 점프하고 타이핑 할 때 적절한 위치로 돌아갑니다. 나는 'a'를 입력한다u003Cspace> , 그것은 상단으로 점프합니다.u003Cspace> 다시하고 그것은 적절한 위치로 돌아갑니다.
이견있는 사람?
다음은 샘플 코드입니다.
- (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];
}
}
}
해결책
로스 카터 덕분에 감사합니다 게시하다 에 코코아 데브 목록, 나는이 문제를 해결했다.
A. 수평 스크롤을 지원하려면 텍스트보기를 설정해야합니다.
- (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];
}
}
제휴하지 않습니다 StackOverflow