Как я могу закруглить углы только одной стороны NSButton в Swift 4?

Я новичок в Swift и Stack Overflow в целом, поэтому я надеюсь, что не прошу многого о себе.

Я пытаюсь создать «сгруппированный» стиль кнопки, который можно найти в Finder или на панели инструментов редактора XCode, как эти две группы кнопок. Как вы можете видеть в первой группе кнопок, левая кнопка закруглена только с левой стороны, центральная кнопка вообще не закруглена, а правая кнопка закруглена только с правой стороны. То же самое относится и ко второй группе кнопок. Я хочу сделать что-то подобное, но я не уверен, как это сделать.

После поиска решения в Интернете (включая учебные пособия по 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()
    }

    // ...
}

... но это не сработало для меня. Некоторая простая отладка показала, что значения Optional для self.layer были 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, но это не дает того, чего я хочу. Я также не могу найти какие-либо связанные свойства/атрибуты в редакторе раскадровки. Возможно, я слишком усложнил свой подход к этой, казалось бы, простой проблеме, или, может быть, я смотрю на нее не так, но я надеюсь, что кто-то сможет мне помочь с этим. Заранее спасибо!


person tahscenery    schedule 16.03.2019    source источник
comment
Разве элементы управления на связанном изображении не представляют собой настраиваемые сегментированные элементы управления?   -  person Magnas    schedule 16.03.2019
comment
@Магнас Ааа, может быть, они это использовали! Не знал, что этот объект существует ????‍♂️. Хотя я хотел бы знать, как настроить такую ​​​​кнопку для дальнейшего использования (если это возможно)   -  person tahscenery    schedule 16.03.2019
comment
Да, сегментированный элемент управления очень полезен, когда нужно выбрать только один параметр за раз. В последнее время мне не приходилось настраивать его, но в Интернете есть много хороших руководств.   -  person Magnas    schedule 16.03.2019
comment
В Cocoa рисуется ячейка. В данном случае это NSButtonCell (подкласс NSActionCell). Проще переопределить drawBezelWithFrame:(NSRect)frame inView:(NSView*)controlView, однако если вы хотите отрисовать все - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView; Я думаю, что это показано где-то в показанном приложении Paintcode (найдите системные ресурсы, такие как кнопка)   -  person Marek H    schedule 16.03.2019
comment
Я также забыл, что если вы меняете геометрию рисования, вы должны адаптировать кольцо фокусировки и его рисование, например, focusRingMaskBoundsForFrame для геометрии   -  person Marek H    schedule 16.03.2019


Ответы (1)


1) Изображения, которые вы показали, используют простой NSSegmentedControl. Ничего не нужно настраивать.

2) То, что вы пытались сделать, все равно не сработает; Если бы он мог работать механически, то в конечном итоге он просто обрезал бы нарисованное содержимое в левых углах. Это не могло бы волшебным образом заполнить рисунок справа и создать соответствующие границы управления и т. д.

Элементы управления AppKit — это не просто CALayers с заполненными свойствами, такими как граница, фон и т. д. Почти все они так или иначе полностью отрисованы с использованием Core Graphics с помощью классического метода drawRect:. Тот факт, что представления имеют слой, связан с поддержкой слоев. Есть очень немного вещей, которые вы можете сделать со слоем существующего элемента управления. Чтобы настроить их должным образом, вы должны переопределить стандартные процедуры рисования в NSView, NSControl, NSCell и т. д. по мере необходимости.

person seth    schedule 17.03.2019
comment
Было бы лучше, если бы вы могли объяснить или хотя бы указать на какую-то ссылку о том, как нарисовать такой прямоугольник с двумя закругленными углами, используя NSBezierPath, а затем добавить метод рисования кнопки. - person Imthath; 09.03.2021