尽管已设置操作,但在单击片段时显示NSSegmentedControl菜单

Jus*_*ams 7 macos usability cocoa controls

我的UI上有一个带有4个按钮的NSSegmentedControl.控件连接到一个方法,该方法将根据单击的段调用不同的方法:

- (IBAction)performActionFromClick:(id)sender {
    NSInteger selectedSegment = [sender selectedSegment];
    NSInteger clickedSegmentTag = [[sender cell] tagForSegment:selectedSegment];

    switch (clickedSegmentTag) {
            case 0: [self showNewEventWindow:nil]; break;
            case 1: [self showNewTaskWindow:nil]; break;
            case 2: [self toggleTaskSplitView:nil]; break;
            case 3: [self showGearMenu]; break;
    }
}
Run Code Online (Sandbox Code Playgroud)

段4在awakeFromNib方法中附加了一个菜单.当用户点击细分时,我希望此菜单下拉.此时,只有当用户点击并按住菜单时,它才会下降.从我的在线研究来看,这是因为关联行动.

我现在通过使用一些代码来获取段控件的原点并使用NSMenu弹出上下文菜单来解决这个问题,popUpContextMenu:withEvent:forView但是相比于将菜单下拉到分段下方的标准行为,这是非常hacktastic并且看起来很糟糕对照细胞.

有没有一种方法可以让菜单下拉,因为它应该单击一下,而不是做hacky上下文菜单的事情?

小智 19

子类NSSegmentedCell,覆盖下面的方法,并替换IB中的单元格类.(不需要私有API).

- (SEL)action
{
    //this allows connected menu to popup instantly (because no action is returned for menu button)
    if ([self tagForSegment:[self selectedSegment]]==0) {
        return nil;
    } else {
        return [super action];
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 确实很好的解决方案.一个小建议:将if条件设置为`[self menuForSegment:[self chosenSegment]]!= nil`; 这样你就不必设置标签了. (3认同)

Mat*_*all 6

我不确定是否有任何内置方法可以做到这一点(尽管它确实是 NSSegmentedControl API 中的一个明显漏洞)。

我的建议是继续做你正在做的弹出上下文菜单。但是,您不仅可以使用分段控件的原点,还可以通过执行以下操作将其直接放置在分段下方(如您所愿):

NSPoint menuOrigin = [segmentedControl frame].origin;
menuOrigin.x = NSMaxX([segmentedControl frame]) - [segmentedControl widthForSegment:4];
// Use menuOrigin where you _were_ just using [segmentedControl frame].origin
Run Code Online (Sandbox Code Playgroud)

它不是完美或理想的,但它应该可以完成工作并提供用户期望的外观/行为。

(顺便一句,NSSegmentedControl确实需要一个-rectForSegment:方法)

  • 同意它很蹩脚,没有内置的方法来做到这一点。我在雷达上提交了它。欺骗:http://openradar.appspot.com/radar?id=61419 (2认同)

nsp*_*ire 5

这是J Hoover的答案的Swift版本和Adam Treble的mod版本。覆盖不如我想象的那样直观,因此希望可以对其他人有所帮助。

override var action : Selector {
        get {
            if self.menuForSegment(self.selectedSegment) != nil {
                return nil
            }
            return super.action
        }
        set {
            super.action = newValue
        }
    }
Run Code Online (Sandbox Code Playgroud)