#ios #swift #uibutton #uibezierpath
#iOS #swift #uibutton #uibezierpath
Вопрос:
У меня есть диапазон определенных путей Безье в одном контроллере представления (по умолчанию). Однако, в частности, я хочу сделать один из них UIButton (он пока никуда не должен вести, но было бы здорово, если бы он мог печатать что-либо на ощупь).
Рассмотрев некоторые похожие вопросы, я смог определить нужный мне путь Безье и UIButton отдельно в симуляторе, но не смог соединить их вместе.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let circlePath = UIBezierPath(arcCenter: CGPoint(x: 200, y: 350), radius: CGFloat(150), startAngle: CGFloat(0), endAngle:CGFloat(Double.pi * 2), clockwise: true)
let shapeLayer = CAShapeLayer()
shapeLayer.path = circlePath.cgPath
//change the fill color
shapeLayer.fillColor = UIColor.clear.cgColor
//you can change the stroke color
shapeLayer.strokeColor = UIColor.gray.cgColor
//you can change the line width
shapeLayer.lineWidth = 7.5
view.layer.addSublayer(shapeLayer)
let button = UIButton(frame: CGRect(x: 100, y: 100, width: 100, height: 50))
button.backgroundColor = .green
button.setTitle("Test Button", for: .normal)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
self.view.addSubview(button)
}
@objc func buttonAction(sender: UIButton!) {
print("Button tapped")
}
}
Как я могу передать circlePath как UIButton?.
Ответ №1:
UIButton — это UIView, поэтому вы можете добавить созданный вами слой к кнопке точно так же, как вы создали view:
button.layer.addSublayer(shapeLayer)
Обратите внимание, что затем этот слой будет закрывать метку UIButton, но простой способ решить эту проблему — изменить z-положение слоя:
shapeLayer.zPosition = -1
Например. если вы хотите добавить круглый слой к кнопке:
let circlePath = UIBezierPath(ovalIn: button.bounds)
let shapeLayer = CAShapeLayer()
shapeLayer.path = circlePath.cgPath
shapeLayer.zPosition = -1
button.layer.addSublayer(shapeLayer)
Или сопоставление окружности в вашем примере, но создание кнопки перед формой:
// define circle parameters
let radius: CGFloat = 150
let center = CGPoint(x: 200, y: 350)
// create the button
let button = UIButton(frame: CGRect(origin: center.applying(CGAffineTransform(translationX: -radius, y: -radius)),
size: CGSize(width: 2 * radius, height: 2 * radius)))
// create the circle layer
let circlePath = UIBezierPath(ovalIn: button.bounds)
let shapeLayer = CAShapeLayer()
shapeLayer.path = circlePath.cgPath
shapeLayer.zPosition = -1
// add the circle layer to the button
button.layer.addSublayer(shapeLayer)
view.addSubview(button)
Комментарии:
1. Спасибо за ответ. Мне пришлось переключить положение кнопки и путь, чтобы разрешить ее запуск. Однако я получаю сообщение «кнопка нажата» только всякий раз, когда я нажимаю на позицию, где раньше была исходная кнопка, а не на круговой слой. Я пытаюсь сделать круговой слой единственной кнопкой в представлении — извините, если я выражаюсь неясно!
2. Да, рамки кнопки и слоя могут отличаться. UIBezierPath(ovalIn: кнопка. границы) создает путь, который, будучи назначен кнопке, находится внутри кнопки. Есть ли у вас особая причина, по которой вы хотите сначала объявить путь, а затем кнопку, а не наоборот?
3. Это получилось так, потому что я не так много знаю. Я больше сосредоточен (возможно, без необходимости) на пути, потому что я хочу, чтобы на касание реагировал только штрих пути, а не весь круг. Я также надеюсь настроить так, чтобы позже я мог применить анимированный градиент к штриху пути
4. Ах, так вам нужен путь, который реагирует на прикосновение? UIButton действительно не подходит для этого, и это, вероятно, приводит к путанице. Вам следует поискать вопросы «Как обнаружить касания в CGPath» или создать его самостоятельно.
5. Именно это — моя вина за расплывчатость. Я сделаю именно это. Спасибо, Прибе