NSScrollView с незакрепленным просмотром контента? - PullRequest
2 голосов
/ 25 апреля 2011

Есть ли способ настроить прокрутку просмотра, чтобы не обрезать ее содержимое? (Который является NSTextView)

У меня есть подкласс NSScrollView, и я хочу, чтобы его содержимое не было обрезано до его границ. Я попытался переопределить:

- (BOOL) wantsDefaultClipping{
    return NO;
}

в MyScrollView и MytextView без какого-либо эффекта. В iOS я бы просто сделал: myuitextView.clipsToBounds=NO; как я могу сделать это в Какао?

EDIT

Это пример того, чего я хочу достичь, но в Mac Scrollview белый, скроллер никогда не выйдет за его пределы, но текст делает, так как я сделал myuitextView.clipsToBounds=NO

Смотри картинку здесь

EDIT2

Я не возражаю против того, чтобы обрезать свою точку зрения, как предложил Джош Но реальное поведение, которое я хотел бы иметь, можно объяснить с помощью этой картины:

normal NSScrollView with NSTextView

Вы видите слово ***** РЕДАКТИРОВАТЬ *****, которое было вырезано в самой первой строке? Я хочу, чтобы текст не обрезался таким образом, я хочу, чтобы он полностью отображался, и я добавлю полупрозрачное изображение, чтобы оно выглядело как исчезающее, когда оно находится за рамкой.

В: Почему бы мне просто не наложить полупрозрачный NSImageView, чтобы он выглядел так, как я хочу? A: Потому что 1.Scroller тоже исчезнет. Даже если я правильно размещу полупрозрачный NSImageView, чтобы скроллер выглядел нормально, курсор / каретка сможет снова оказаться под полупрозрачным NSImageView, но он не выглядит хорошо.

Я хотел бы иметь возможность контролировать область, обрезанную NSClipView. Я думаю, что это решило бы мою проблему. Есть ли у меня альтернатива? может быть, я могу контролировать позицию каретки или позицию прокрутки через NSTextView, чтобы каретка никогда не выходила за пределы верхнего / нижнего фрейма? или какой-нибудь обходной путь?

Любой совет приветствуется.

Ответы [ 4 ]

2 голосов
/ 05 апреля 2016

Теперь, когда наступил 2016 год, и мы используем яркие заголовки с полноразмерными представлениями контента, я добавлю свои мысли о том, как кто-то может это сделать. Надеюсь, это поможет всем, кто пришел сюда за помощью, так же, как и мне.

Это отвечает на вопрос о прокрутке под заголовком, но вы можете легко изменить эту технику для прокрутки под другими вещами, используя вставки и положение каретки.

Чтобы получить представление прокрутки (с или без NSTextView внутри него) для прокрутки за заголовком, вы можете использовать:

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

Это эффективно накладывает заголовок окна 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

Это позволяет ограничить верх элемента элементом нижней части строки заголовка (и / или панели инструментов + любые дополнительные виды, которые у него могут быть). Это было показано на WWDC в 2015 году: https://developer.apple.com/videos/play/wwdc2014/220/

Чтобы заставить представление прокрутки прокручиваться под заголовком , но отображать его полосы прокрутки внутри незатененной части окна , прикрепите его к верхней части представления содержимого в IB или с помощью кода, что приведет к быть под заголовком Затем скажите ему, чтобы он автоматически обновлял свои вставки :

scrollView.automaticallyAdjustsContentInsets = true

Наконец, вы можете создать подкласс своего окна и обработать положение курсора / каретки. Существует предполагаемая ошибка (или ошибка разработчика с моей стороны), из-за которой представление прокрутки не всегда прокручивается до курсора / каретки, когда оно находится выше или ниже вставок содержимого представления прокрутки.

Чтобы исправить это, вы должны вручную найти позицию каретки и прокрутить ее, чтобы увидеть, когда выбор изменится. Прости мой ужасный код, но, похоже, работа сделана. Этот код принадлежит подклассу 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: /6206250/nspopover-nizhe-karetki-v-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
}

Надеюсь, это поможет!

0 голосов
/ 25 апреля 2011

Вы можете рассмотреть возможность использования полупрозрачного слоя для достижения этого вида, фактически не рисуя за пределами вашего обзора.Я не уверен в правилах для iOS, но на Mac представление чертежа за его пределами может создавать помехи окружающему рисунку.

Однако вы можете установить область отсечения так, как вам нравится внутри вашегопрокрутка просмотра подкласса drawRect: с использованием -[NSBezierPath setClip:]:

- (void)drawRect:(NSRect)dirtyRect {

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

    //...

    [NSGraphicsContext restoreGraphicsState];
}

Возможно (так как вы просили) использовать этот код в подклассе NSClipView, но не так многоинформация об этом, и я думаю, вам может быть трудно заставить его правильно взаимодействовать с видом прокрутки.Если бы это был я, я бы сначала попытался создать подкласс NSScrollView.

0 голосов
/ 29 апреля 2011

Это немного волосато. AFAIK, NSViews не может рисовать вне своей рамки. Во всяком случае, я никогда не видел, чтобы это было сделано, и я был несколько удивлен, когда понял, что UIView позволяет это по умолчанию. Но то, что вы, вероятно, хотите здесь сделать, - это не манипулировать прямоугольниками отсечения (выполнение любой подобной вещи внутри NSScrollView, вероятно, не будет делать то, что вы хотите или ожидаете), а вместо этого попытаться прикрыть укороченные вертикально текстовые строки слоями или представлениями, которые тот же цвет, что и фон. Возможно, вы могли бы создать подкласс NSClipView и переопределить viewBoundsChanged: и / или viewFrameChanged: для того, чтобы заметить, когда текстовое представление смещается, и соответствующим образом настроить ваши «оттенки».

0 голосов
/ 25 апреля 2011

Я бы просто попытался наблюдать frame представления документа и сопоставить frame представления прокрутки при изменении размера документа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...