【问题标题】:Set position of nspopover设置nspopover的位置
【发布时间】:2017-09-03 10:33:04
【问题描述】:

我有一个视图控制器 (A),它将另一个视图控制器 (B) 显示为弹出框。

在我的 VC (A) 中是一个带有此 IBAction 的 NSButton:

self.presentViewController(vcPopover, asPopoverRelativeTo: myButton.bounds, of: myButton, preferredEdge: .maxX, behavior: .semitransient)

结果:

现在我想更改弹出框的位置 - 我想将其向上移动。

我试过这个:

let position = NSRect(origin: CGPoint(x: 100.0, y: 120.0), size: CGSize(width: 0.0, height: 0.0))
self.presentViewController(vcPopover, asPopoverRelativeTo: position, of: myButton, preferredEdge: .maxX, behavior: .semitransient)

但位置不变

另一个例子

我有一个分段控件。如果您单击段“1”,则会显示一个弹出框(与上面的代码相同)。但箭头指向分段“2”而不是分段“1”

【问题讨论】:

    标签: swift macos nsviewcontroller nspopover


    【解决方案1】:

    首先,确保您的弹出框确实是 NSPopover 而不仅仅是 NSViewController。假设您要包装在弹出框中的视图控制器的故事板 ID 为“vcPopover”,获取内容 vc 如下所示:

    let popoverContentController = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"), bundle: nil).instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "vcPopover")) as! NSViewController
    

    然后,将其包装在一个弹出框中:

    let popover = NSPopover()
    popover.contentSize = NSSize(width: 200, height: 200) // Or whatever size you want, perhaps based on the size of the content controller
    popover.behavior = .semitransient
    popover.animates = true
    popover.contentViewController = popoverContentController    
    

    然后,请致电show(relativeTo:of:preferredEdge:)

    vcPopover.show(relativeTo: myButton.bounds, of: myButton, preferredEdge: .maxX)
    

    这应该会更新弹出框的位置。

    更新:您很可能使用NSSegmentedControl,这意味着您需要特别注意您在show 中传递的rect。您需要在分段控件的坐标系中传递一个边界矩形,它描述了该段的区域。下面是一个详细的例子:

    // The view controller doing the presenting
    class ViewController: NSViewController {
    
        ...
    
        var presentedPopover: NSPopover?
    
        @IBAction func selectionChanged(_ sender: NSSegmentedControl) {
            let segment = sender.selectedSegment
    
            if let storyboard = storyboard {
                let contentVC = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("vcPopover")) as! NSViewController
    
                presentedPopover = NSPopover()
                presentedPopover?.contentSize = NSSize(width: 200, height: 200)
                presentedPopover?.behavior = .semitransient
                presentedPopover?.animates = true
                presentedPopover?.contentViewController = contentVC
            }
    
            presentedPopover?.show(relativeTo: sender.relativeBounds(forSegment: segment), of: sender, preferredEdge: .minY)
        }
    
    }
    
    extension NSSegmentedControl {
    
        func relativeBounds(forSegment index: Int) -> NSRect {
            // Assuming equal widths
            let segmentWidth = bounds.width / CGFloat(segmentCount)
    
            var rect = bounds
            rect.size.width = segmentWidth
            rect.origin.x = rect.origin.x + segmentWidth * CGFloat(index)
    
            return rect
        }
    
    }
    

    请注意,NSSegmentedControl 的扩展使用宽度计算线段的近似矩形。此方法假定宽度相等且不考虑边框。您可以修改此方法以解决您的需要。关于获取 iOS 段的帧的信息(类似)可以找到here

    只要视图控制器存在于同一故事板中,故事板标识符为“vcPopover”,此示例就可以正常工作。

    【讨论】:

    • 我这样声明了我的 vcPopover:let vcPopover = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"), bundle: nil).instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(rawValue: "vcPopover")) as! NSViewController。我收到错误:“NSViewController”类型的值没有成员“show”
    • @Ghost108 我用创建NSPopover 的说明更新了我的答案。
    • 我试过你的代码,但结果是一样的,如上图。弹出箭头将指向第二段而不是第一段。我使用了CGPoint(x: 100.0, y: 120.0) 的值,但没有任何改变
    • 您只是使用水平的NSButtons 还是NSSegmentedControl?在后者的情况下,你从哪里得到myButton
    • @Ghost108 我很抱歉。我创建了一个示例项目,并且能够让我的版本正常工作。我会将我的代码添加到我的答案中。
    猜你喜欢
    • 2012-06-01
    • 1970-01-01
    • 2016-01-16
    • 2012-04-16
    • 1970-01-01
    • 2019-10-07
    • 1970-01-01
    • 2021-12-17
    • 1970-01-01
    相关资源
    最近更新 更多