【问题标题】:How can I round the corners of only one side of an NSButton in Swift 4?如何在 Swift 4 中仅圆角 NSButton 的一侧?
【发布时间】:2019-08-07 04:37:56
【问题描述】:

总的来说,我是 Swift 和 Stack Overflow 的新手,所以我希望我不会要求太多。

我正在尝试实现可在 Finder 或 XCode 编辑器工具栏中找到的“分组”按钮样式,like these two button groups。在第一组按钮中可以看到,左键只在左侧圆角,中间键根本不圆角,右键只在右侧圆角。同样的事情也适用于第二组按钮。我想完成这样的事情,但我不确定如何实现。

在网上搜索了解决方案(包括 iOS 教程)后,我尝试为 NSButton 类提供扩展,并像这样手动舍入左两个角:

// Extensions.swift

extension NSButton {
    func roundLeftCorners() {
        self.layer?.maskedCorners = [.layerMinXMinYCorner, .layerMinXMaxYCorner]
        self.layer?.cornerRadius = 20.0   // Some arbitrary number, just wanted to make the rounded corner visible
        self.layer?.masksToBounds = true
    }
}

然后,在我的视图控制器的viewDidLoad() 函数上,我尝试调用这个成员:

// MyViewController.swift

class MyViewController: NSViewController {
    @IBOutlet weak var leftButton: NSButton!

    override func viewDidLoad() {
        super.viewDidLoad()
        leftButton.roundLeftCorners()
    }

    // ...
}

...但这对我不起作用。一些简单的调试表明self.layerOptional 值是nil,所以我不确定那里发生了什么。

接下来,我尝试创建自己的自定义类并使用上面相同的代码覆盖draw(_ dirtyRect:) 函数,如下所示:

// LeftButton.swift

class LeftButton: NSButton {
    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)

        self.layer?.maskedCorners = [.layerMinXMinYCorner, .layerMinXMaxYCorner]
        self.layer?.cornerRadius = 20.0
        self.layer?.masksToBounds = true
    }
}

// MyViewController.swift

class MyViewController: NSViewController {
    @IBOulet weak var leftButton: LeftButton!

    // ...
}

...但这并没有删除右侧的圆角。奇怪的是,新的cornerRadius 值只有在数字约为50.0 或更大时才会明显;少一点,左角看起来和其他NSButton一模一样。

一些答案​​提到手动在NSBezierPath 的路径中绘制点,但它并没有达到我想要的效果。我在情节提要编辑器上也找不到任何相关的属性/属性。也许我对这个看似简单的问题的方法过于复杂,或者也许我没有以正确的方式看待它,但我希望有人能帮助我解决这个问题。提前致谢!

【问题讨论】:

  • 链接图片中的控件不是自定义的分段控件吗?
  • @Magnas Ahh,也许他们就是这么用的!不知道那个物体的存在????‍♂️。不过,我想知道如何自定义这样的按钮以供将来参考(如果可能的话)
  • 是的,当一次只能选择一个选项时,分段控件非常有用。我最近不需要定制一个,但是网上有很多很好的教程。
  • 在 Cocoa 中,它是正在绘制的单元格。在这种情况下,它是 NSButtonCell(NSActionCell 的子类)。更简单的是覆盖 drawBezelWithFrame:(NSRect)frame inView:(NSView*)controlView,但是如果你想绘制所有内容 - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView;我认为它显示在显示的 Paintcode 应用程序中的某处(查找按钮等系统资源)
  • 我也忘记了,如果你改变绘图几何,你应该调整焦点环并且它正在绘图,例如用于几何的 focusRingMaskBoundsForFrame

标签: swift macos cocoa nsbutton nssegmentedcontrol


【解决方案1】:

1) 您展示的图像使用的是简单的 NSSegmentedControl。没有什么需要定制的。

2) 你试图做的无论如何都行不通;如果它可以机械地工作,它最终会做的只是将绘制的内容剪裁在左角。它不会神奇地填充右侧的绘图,并创建适当的控件边框等。

AppKit 控件不仅仅是填充了诸如边框、背景等属性的 CALayers。它们几乎都是使用 Core Graphics 通过经典的 drawRect: 方法以一种或另一种方式绘制的。视图有一个层的事实是由于层支持。对于现有控件的层,您最终可以做的事情很少。要正确自定义它们,您可以根据需要覆盖 NSView、NSControl、NSCell 等中的标准绘图例程。

【讨论】:

  • 如果您能解释或至少指出一些关于如何使用 NSBezierPath 绘制具有两个圆角的矩形然后将按钮的绘制方法放入 insdie 的参考会更好。跨度>
猜你喜欢
  • 2016-04-27
  • 1970-01-01
  • 2021-06-14
  • 2018-03-24
  • 1970-01-01
  • 2021-05-04
  • 2017-11-27
  • 2016-07-10
  • 2019-06-09
相关资源
最近更新 更多