Skip to content

Instantly share code, notes, and snippets.

@vistar941
Last active April 28, 2026 17:25
Show Gist options
  • Select an option

  • Save vistar941/2d4a120fefa37de73aeb18b6d20f4445 to your computer and use it in GitHub Desktop.

Select an option

Save vistar941/2d4a120fefa37de73aeb18b6d20f4445 to your computer and use it in GitHub Desktop.
Work around UIButton limitations using only public APIs.
import UIKit
final class MenuControl: UIControl {
private let label: UILabel = {
let label = UILabel()
label.text = "Public API-Only Menu"
label.font = .boldSystemFont(ofSize: 15)
label.textAlignment = .center
label.textColor = .white
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setup() {
// Calling `performPrimaryAction()` from the caller allows the menu to be displayed programmatically.
// isHidden = true
// isUserInteractionEnabled = false
cornerConfiguration = .capsule()
backgroundColor = .systemBlue
showsMenuAsPrimaryAction = true
isContextMenuInteractionEnabled = true
addSubview(label)
NSLayoutConstraint.activate([
label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
label.topAnchor.constraint(equalTo: topAnchor),
label.bottomAnchor.constraint(equalTo: bottomAnchor)
])
}
override func contextMenuInteraction(
_ interaction: UIContextMenuInteraction,
configurationForMenuAtLocation location: CGPoint
) -> UIContextMenuConfiguration? {
.init(actionProvider: { _ in
UIMenu(children: [
UIAction(title: "First") { _ in
print("First")
},
UIAction(title: "Second") { _ in
print("Second")
},
UIAction(title: "Third") { _ in
print("Third")
},
])
})
}
}
final class ViewController: UIViewController {
private let menuControl: MenuControl = {
let control = MenuControl()
control.translatesAutoresizingMaskIntoConstraints = false
return control
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .secondarySystemBackground
view.addSubview(menuControl)
NSLayoutConstraint.activate([
menuControl.centerXAnchor.constraint(equalTo: view.centerXAnchor),
menuControl.centerYAnchor.constraint(equalTo: view.topAnchor, constant: 100),
menuControl.widthAnchor.constraint(equalToConstant: 200),
menuControl.heightAnchor.constraint(equalToConstant: 50)
])
}
}
#Preview {
ViewController()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment