NScrollView в проблеме автоматического размещения NSPopover - PullRequest
0 голосов
/ 29 марта 2019

У меня есть NSPopover, который содержит NSViewController с содержащим NSScrollView.

Высота Popover должна быть либо высота содержимого NSScrollView или текущее окно.Как только он достигнет границ окна, он должен прокрутиться.

Использование Snapkit

Я добавил NSScrollView в контроллер:

view.addSubview(scrollView)
scrollView.snp.makeConstraints { (make) in
   make.edges.equalTo(view)
   make.height.equalTo(mainView.content.snp.height)
}

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

Я опустилсямаршрут удаления ограничения высоты и в viewDidLayout попробуйте обновить высоту, но это не работает.

Если нужно больше примеров кода, дайте мне знать.

1 Ответ

1 голос
/ 30 марта 2019

Наконец-то добрались до сути вопроса и нашли разумное решение.

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

class PopoverService: NSObject {

    enum PopoverType {
        case subscription, edit
    }

    //================================================================================
    // MARK: - Properties
    //================================================================================

    private var dismissingPopover = false
    private lazy var currentPopover: NSPopover = {
        let popover = NSPopover()
        popover.delegate = self
        return popover
    }()

    private var nextPopoverType: PopoverType?
    private var currentView: NSView!

    public static var delegate: PopoverServiceDelegate?

    //================================================================================
    // MARK: - Singleton
    //================================================================================

    static let shared = PopoverService()

    //================================================================================
    // MARK: - Helpers
    //================================================================================

    public static func increaseHeight(_ height: CGFloat) {
        shared.currentPopover.contentSize.height = height
    }

    public static func isDisplayingType(_ type: PopoverType) -> Bool {
        switch type {
        case .edit:
            return shared.currentPopover.contentViewController is EditEntryController
        case .language:
            return shared.currentPopover.contentViewController is CodeTypeController
        default:
            return false
        }
    }

    public static func displayPopover(type: PopoverType, fromView view: NSView) {
        shared.nextPopoverType = type
        shared.currentView = view

        switch type {
        case .subscription:
            displaySubscriptionPopoverFrom(view)
        // Create functions to display your popovers
        }
    }

    static func dismissPopover(clearUpcoming: Bool = true) {
        if clearUpcoming {
            shared.nextPopoverType = nil
        }

        shared.currentPopover.performClose(nil)
        if shared.currentPopover.contentViewController == nil {
            shared.dismissingPopover = false; return
        }
    }

}

extension PopoverService: NSPopoverDelegate {

    func popoverDidClose(_ notification: Notification) {
        currentPopover.contentViewController = nil
        dismissingPopover = false

        guard let nextPopoverType = nextPopoverType else { return }
        PopoverService.displayPopover(
            type: nextPopoverType,
            fromView: currentView,
            entry: currentEntry
        )
    }

}

Для обновления текущего поповера есть функция increaseHeight, которая принимает и CGFloat и обновляет текущую высоту поповеров.

В NSViewController переопределить viewDidLayout():

    override func viewDidLayout() {
        super.viewDidLayout()

        let windowFrameHeight = view.window?.frame.size.height ?? 0
        let contentHeight = scrollView.content.frame.height
        let adjustment = contentHeight > windowFrameHeight ? windowFrameHeight : contentHeight
        PopoverService.increaseHeight(adjustment)

        if contentHeight > 0 && firstLayout {
            if let documentView = scrollView.documentView {
                documentView.scroll(NSPoint(x: 0, y: documentView.bounds.size.height))
            }
        }
    }

scrollView нужно будет переместиться вверх, поэтому есть переменная firstLayout, которую вы можете установить в true в viewDidAppear

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