2011-04-25 2 views
2

내용을 클립하지 않도록 내 scrollview를 설정할 수있는 방법이 있습니까? (NSTextView)내용보기가 분리 된 NSScrollView?

NSScrollView의 하위 클래스가 있는데 그 내용이 이 아니고이 경계로 잘 리기를 원합니다. 내가 시도 오버라이드 (override) :

- (BOOL) wantsDefaultClipping{ 
    return NO; 
} 
MyScrollView

및 영향없이 MytextView에서

. iOS에서 나는 단순히 다음을 할 것입니다. myuitextView.clipsToBounds=NO; 어떻게 코코아에서이 작업을 수행 할 수 있습니까?

편집

이 내가 무엇을 달성하고자하는의 예입니다하지만 맥 에있는 ScrollView는 스크롤러는 경계의 외측에 가지 않을 것입니다 흰색이지만 텍스트는 내가 한 이후 않습니다 myuitextView.clipsToBounds=NO

See picture here

EDIT2

I @ 조쉬가 제안한 것처럼 내 생각을 정리하지 않을 것이다.

normal NSScrollView with NSTextView

당신이 첫 번째 줄에 절단되고있다 단어 ***** 편집 *****를 볼 수행하지만 내가하고 싶은 실제 동작은이 사진과 함께 설명 될 수있다 ? 이 방법으로 텍스트를 잘라내지 말고 완전히 표시하고 싶습니다. 그러면 프레임 밖에있을 때 반투명 한 이미지가 나타나서 희미 해 보입니다.

Q : 원하는대로 보이도록 반투명 NSImageView를 놓는 것이 어떨까요? A : 1.Scroller도 희미해질 것이기 때문에. 스크롤러가 잘 보일 정도로 반투명 한 NSImageView를 배치하더라도 커서/캐럿이 반투명 NSImageView 아래로 갈 수있게되어 다시 잘 보이지 않습니다.

NSClipView에 의해 잘리는 부분을 제어하고 싶습니다. 나는 그것이 내 문제를 해결할 것이라고 생각한다. 내가 가지고있는 대안이 있습니까? 어쩌면 캐럿 위치 또는 스크롤 위치를 NSTextView를 통해 제어 할 수 있으므로 캐럿이 위쪽/아래쪽 프레임 제한 가까이에 가지 않을 것입니다. 또는 어떤 work-around?

모든 조언을 주시면 감사하겠습니다.

답변

0

문서보기의 frame을 관찰하고 문서의 크기를 조정할 때 스크롤보기의 frame과 일치 시키려고합니다.

+0

문서의 크기가 조정되지 않은 경우에도이를 수행하고 싶습니다 ... 예를 들어 사용자가 많이 입력 할 때 scrollview는 내용을 클립하지 않아야합니다. scrollview 프레임 안에 들어 가지 않는 텍스트는 scrollview 범위 밖에 있어야합니다. – nacho4d

0

실제 모양을 벗어나지 않고이 모양을 구현하려면 반투명 레이어를 사용하는 것이 좋습니다. iOS의 규칙은 확실하지 않지만 Mac에서는 그 경계를 벗어난보기가 주변 그림에 간섭을 일으킬 수 있습니다.

- (void)drawRect:(NSRect)dirtyRect { 

    [NSGraphicsContext saveGraphicsState]; 
    [[NSBezierPath bezierPathWithRect:[[self documentView] frame]] setClip]; 

    //... 

    [NSGraphicsContext restoreGraphicsState]; 
} 

(당신이 요청 이후) 그것은 가능할 수는 NSClipView 하위 클래스에서이 코드를 사용 :

그러나, 당신은 당신이 당신의 스크롤 뷰 서브 클래스의 drawRect:-[NSBezierPath setClip:]를 사용하여 내부에 원하는대로로 클리핑 영역을 설정할 수 있습니다 , 그러나 그것에 대한 많은 정보가 아니며, 스크롤보기와 적절하게 상호 작용하기가 힘들다고 생각합니다. 그것이 나라면, 나는 NSScrollView을 먼저 하위 클래스 화하려고 시도 할 것입니다.

+0

NSClipView의 하위 클래스에이 코드를 삽입하면 어떻게 될지 알 수 있습니까? 나는 그것이 매우 분명하지 않기 때문에 내 질문을 업데이트했다. – nacho4d

+0

@ nacho4d : 아니, 잘 모르겠습니다. NSClipView에 대한 많은 정보가 없으므로 서브 클래스를 만들면 스크롤 뷰와 적절하게 상호 작용할 수 있습니다. 그것이 나 였다면, NSScrollView를 서브 클래스하려고 시도 할 것이지만, 확실히 NSScrollView를 시도 할 수 있습니다. –

+0

@nacho : "... 확실히 NSClipView'를 시도했다는 것을 의미합니다. 물론 –

0

약간 털이 있습니다. AFAIK, NSViews 자신의 프레임 외부로 그릴 수 없습니다. 어쨌든 나는 그것을 한 번도 본 적이 없으며 UIView가 기본적으로 허용한다는 것을 깨달았을 때 다소 놀랐습니다. 하지만 여기에서해야 할 일은 자르기 직사각형을 조작하지 않는 것입니다 (NSScrollView 내에서 그런 일을하는 것은 아마도 여러분이 원하거나 기대하는 것을하지 않을 것입니다). 대신 수직으로 잘린 텍스트 라인을 덮어 쓰거나 배경과 같은 색. 아마도 NSClipView를 서브 클래스 화하고 viewBoundsChanged : 및/또는 viewFrameChanged :를 재정 의하여 텍스트보기가 언제 이동되는지 알아보고 이에 따라 "음영"을 조정할 수 있습니다.

+0

입니다.하지만 그렇게하면 캐럿은 여전히"음영 "아래에있을 수 있습니다. 예를 들어 타이핑을 시작할 때 등. 올바르게 처리 했습니까? . 그건 내가 피할 수없는 일이다. 내 현재 접근 방식입니다 : "음영"scrollview 및 서브 클래 싱 NSScroller 슬롯 프레임 크기를 조정할 수 있도록 내 세로 스크롤러 "음영"에 의해 숨겨져 있지 않습니다. 그것은 여전히 ​​같은 캐럿 문제가 있습니다. ; ( – nacho4d

+0

사실, 캐럿은 사라질 수 있지만 정상적인 경우에도 항상 그럴 가능성이 있습니다. 캐럿이 사라지도록 스크롤 할 수 있습니다. 약간의 경우를 감추기 때문에 캐럿이 사라질 수도 있습니다. 픽셀. –

+0

'NSView'는 프레임 외부에 _definitely_ 드로잉 할 수 있습니다. 즉, 'drawRect :'에서 클립 rect를 변경하면 윈도우의 콘텐트 뷰 내부 어디에서나 그릴 수 있습니다. 사용자 지정 포커스 링과 같은 작업을 수행하는 데 약간의 작업을 수행 할 수 있습니다.) 다행히도 창에 "더 단단한"클립이 있습니다. 시스템이 사용자가 무엇을 말하더라도 활성 창 외부에서 다시 그려지는 일이 없기 때문일 수 있습니다 그것. –

1

2016 년 이었으므로 전체 크기의 콘텐츠보기가있는 활발한 제목 표시 줄을 사용하고 있습니다. 누군가가이를 수행 할 수있는 방법에 대한 생각을 추가하겠습니다. 바라기를 바란다면, 도움이 될 수있는 여기에 온 사람들에게 도움이 될 것입니다.

제목 표시 줄 아래로 스크롤하는 것과 관련하여 질문에 대답하지만,이 기술을 수정하여 인세 트 및 캐럿 위치를 사용하여 다른 것들을 스크롤 할 수 있습니다.

은, 당신이 사용할 수있는 (또는 그것의 내부를 NSTextView없이)를 제목 표시 줄 뒤에 스크롤 스크롤 뷰를 얻으려면 :

// For transparent title. 
    window.titlebarAppearsTransparent = true 
    window.styleMask = window.styleMask | NSFullSizeContentViewWindowMask 
    window.appearance = NSAppearance(named: NSAppearanceNameVibrantLight) 

이 효과적으로 창의있는 contentView 위에 NSWindow 표시의 제목 표시 줄을 오버레이. (

// Make a constraint for SOMEVIEW to the top layout guide of the window: 
let topEdgeConstraint = NSLayoutConstraint(
item: SOMEVIEW, attribute: NSLayoutAttribute.Top, 
relatedBy: NSLayoutRelation.Equal, 
toItem: window.contentLayoutGuide, 
attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0.0) 

// Turn the constraint on automatically:  
topEdgeConstraint.active = true 

이것은 당신이 제목 표시 줄의 맨 아래에 요소의 상단을 제한 할 수 있으며 또는 도구 모음 + 하나를 :

는 제목 표시 줄의 높이를 모른 채 창 상단에 뭔가를 제한하려면 액세서리보기). 이는 2015 년 WWDC에서 나타났다 : https://developer.apple.com/videos/play/wwdc2014/220/

은, 제목 표시 줄 아래로 스크롤하지만 윈도우의 unobscured 일부 내부의 스크롤 막대를 표시 할 수있는 ScrollView를 얻을 수 IB 또는 코드를 통해 콘텐츠 뷰의 상단에 고정하려면 이는 제목 표시 줄 아래에 표시됩니다. 마지막으로

scrollView.automaticallyAdjustsContentInsets = true 

당신은 당신의 윈도우를 서브 클래 싱 커서/캐럿 위치를 처리 할 수 ​​있습니다 다음, 그것은 자동으로 세트의 업데이트 할 말해. 스크롤 뷰의 내용 인세 트 위 또는 아래로 이동할 때 scrollview가 항상 커서/캐럿으로 스크롤하지 않도록하는 버그 (또는 개발자 측 오류)가 있습니다.

이 문제를 해결하려면 수동으로 캐럿 위치를 찾고 선택 항목이 변경되면 스크롤하여보아야합니다. 내 끔찍한 코드를 용서해 줘.하지만 일을 끝내는 것 같아. 이 코드는 NSWindow 서브 클래스에 속하므로 self이 창을 참조합니다.

// MARK: NSTextViewDelegate 
func textViewDidChangeSelection(notification: NSNotification) { 
    scrollIfCaretIsObscured() 
    textView.needsDisplay = true // Prevents a selection rendering glitch from sticking around 
} 

// MARK: My Scrolling Functions 

func scrollIfCaretIsObscured() { 
    let rect = caretRectInWindow() 
    let y: CGFloat = caretYPositionInWindow() - rect.height 
    // Todo: Make this consider the text view's ruler height, if present: 
    let tbHeight: CGFloat 
    if textView.rulerVisible { 
     // Ruler is shown: 
     tbHeight = (try! titlebarHeight()) + textViewRulerHeight 
    } else { 
     // Ruler is hidden 
     tbHeight = try! titlebarHeight() 
    } 
    if y <= tbHeight { 
     scrollToCursor() 
    } 
} 

func caretYPositionInWindow() -> CGFloat { 
    let caretRectInWin: NSRect = caretRectInWindow() 
    let caretYPosInWin: CGFloat = self.contentView!.frame.height - caretRectInWin.origin.y 
    return caretYPosInWin 
} 

func caretRectInWindow() -> CGRect { 
    // My own version of something based off of an old, outdated 
    // answer on stack overflow. 
    // Credit: http://stackoverflow.com/questions/6948914/nspopover-below-caret-in-nstextview 
    let caretRect: NSRect = textView.firstRectForCharacterRange(textView.selectedRange(), actualRange: nil) 
    let caretRectInWin: NSRect = self.convertRectFromScreen(caretRect) 
    return caretRectInWin 
} 

/// Scrolls to the current caret position inside the text view. 
/// - Parameter textView: The specified text view to work with. 
func scrollToCursor() { 
    let caretRectInScreenCoords = textView.firstRectForCharacterRange(textView.selectedRange(), actualRange: nil) 
    let caretRectInWindowCoords = self.convertRectFromScreen(caretRectInScreenCoords) 
    let caretRectInTextView = textView.convertRect(caretRectInWindowCoords, fromView: nil) 
    textView.scrollRectToVisible(caretRectInTextView) 
} 

enum WindowErrors: ErrorType { 
    case CannotFindTitlebarHeight 
} 

/// Calculates the combined height of the titlebar and toolbar. 
/// Don't try this at home. 
func titlebarHeight() throws -> CGFloat { 
    // Try the official way first: 
    if self.titlebarAccessoryViewControllers.count > 0 { 
     let textViewInspectorBar = self.titlebarAccessoryViewControllers[0].view 
     if let titlebarAccessoryClipView = textViewInspectorBar.superview { 
      if let view = titlebarAccessoryClipView.superview { 
       if let titleBarView = view.superview { 
        let titleBarHeight: CGFloat = titleBarView.frame.height 
        return titleBarHeight 
       } 
      } 
     } 
    } 
    throw WindowErrors.CannotFindTitlebarHeight 
} 

희망이 있습니다.

관련 문제