Swift iOS - 如何排列子层位置以匹配按钮文本的中心
Swift iOS - How to line up a sublayer position to match the center of button text
我有一个文本按钮。我添加了一个红色背景子图层,并使背景图层的宽度和高度大于按钮文本。我尝试使用以下方法将背景层居中放置在按钮上:
backgroundLayer.position = button.center
它没有居中。这是我得到的:
我知道我可以直接在按钮上设置背景颜色和 cornerRadius,但是当我这样做时,红色背景会紧贴文本:
button.backgroundColor = UIColor.red
button.layer.cornerRadius = 10
我希望红色背景比文字更宽更高:
backgroundLayer.frame = CGRect(x: 0, y: 0, width: buttonTextSize.width + 10, height: buttonTextSize.height + 5
我想以 Photoshop 为例,但目前我面前没有 Photoshop。这是我能找到的最接近的。这是来自 Vimeo 的按钮。他们没有使用文本,但是 backgroundLayer 比按钮图像更宽更高,并且 backgroundLayer 的位置与按钮的 midX 和 midY 对齐:
如何让背景子层的位置与按钮文本的中心对齐?
let button: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle("Next", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.contentHorizontalAlignment = .center
button.titleLabel?.font = UIFont.systemFont(ofSize: 23)
return button
}()
let backgroundLayer: CALayer = {
let layer = CALayer()
layer.backgroundColor = UIColor.red.cgColor
layer.cornerRadius = 10
return layer
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
view.addSubview(button)
button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
let buttonText = button.titleLabel?.text
let buttonTextSize = (buttonText! as NSString).size(withAttributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 23.0)])
// I added 10 points to the backgroundLayer's width and 5 points to the backgroundLayer's height so its wider then the text
backgroundLayer.frame = CGRect(x: 0, y: 0, width: buttonTextSize.width + 10, height: buttonTextSize.height + 5)
button.layer.insertSublayer(backgroundLayer, at: 0)
backgroundLayer.position = button.center
}
这是一个看起来像你想要的样子的按钮(当然你可以调整任何不适合你感觉的参数):
此按钮自动为红色、圆角且比其文本大很多(即使按钮使用自动布局定位)。
这是通过子类实现的方法:
class MyRedButton : UIButton {
override func layoutSubviews() {
super.layoutSubviews()
self.backgroundColor = .red
self.layer.cornerRadius = 10
}
override var intrinsicContentSize: CGSize {
var sz = super.intrinsicContentSize
sz.width += 30; sz.height += 30
return sz
}
}
Matt 赞成的答案是正确的。
他在评论中指出我最初做错的两件事是。
- 我尝试设置
backgroundLayer.position = button.center
。这是错误的,因为按钮的中心基于框架的 center 而不是 bounds 中心。我应该设置 backgroundLayer.position 以匹配按钮边界的中心
- 我试图在
viewWillLayoutSubviews
中将 backgroundLayer 的位置设置为按钮的中心,他说按钮的边界尚不清楚,因此 backgroundLayer 没有信息作为基础。我应该将代码添加到 viewDidLayoutSubviews
这里是代码:
// 1. add the code to viewDidLayoutSubviews
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let text = button.titleLabel?.text
let textSize = (text! as NSString).size(withAttributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 23.0)])
backgroundLayer.frame = CGRect(x: 0, y: 0, width: textSize.width + 10, height: textSize.height + 5)
button.layer.insertSublayer(backgroundLayer, at: 0)
// 2. get the buttons bound's center by accessing it's midX and midY
let buttonMidX = button.bounds.midX
let buttonMidY = button.bounds.midY
let buttonBoundsCenter = CGPoint(x: buttonMidX, y: buttonMidY)
// 3. set the backgroundLayer's postion to the buttonBoundsCenter
backgroundLayer.position = buttonBoundsCenter
}
有效:
我有一个文本按钮。我添加了一个红色背景子图层,并使背景图层的宽度和高度大于按钮文本。我尝试使用以下方法将背景层居中放置在按钮上:
backgroundLayer.position = button.center
它没有居中。这是我得到的:
我知道我可以直接在按钮上设置背景颜色和 cornerRadius,但是当我这样做时,红色背景会紧贴文本:
button.backgroundColor = UIColor.red
button.layer.cornerRadius = 10
我希望红色背景比文字更宽更高:
backgroundLayer.frame = CGRect(x: 0, y: 0, width: buttonTextSize.width + 10, height: buttonTextSize.height + 5
我想以 Photoshop 为例,但目前我面前没有 Photoshop。这是我能找到的最接近的。这是来自 Vimeo 的按钮。他们没有使用文本,但是 backgroundLayer 比按钮图像更宽更高,并且 backgroundLayer 的位置与按钮的 midX 和 midY 对齐:
如何让背景子层的位置与按钮文本的中心对齐?
let button: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle("Next", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.contentHorizontalAlignment = .center
button.titleLabel?.font = UIFont.systemFont(ofSize: 23)
return button
}()
let backgroundLayer: CALayer = {
let layer = CALayer()
layer.backgroundColor = UIColor.red.cgColor
layer.cornerRadius = 10
return layer
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.lightGray
view.addSubview(button)
button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
let buttonText = button.titleLabel?.text
let buttonTextSize = (buttonText! as NSString).size(withAttributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 23.0)])
// I added 10 points to the backgroundLayer's width and 5 points to the backgroundLayer's height so its wider then the text
backgroundLayer.frame = CGRect(x: 0, y: 0, width: buttonTextSize.width + 10, height: buttonTextSize.height + 5)
button.layer.insertSublayer(backgroundLayer, at: 0)
backgroundLayer.position = button.center
}
这是一个看起来像你想要的样子的按钮(当然你可以调整任何不适合你感觉的参数):
此按钮自动为红色、圆角且比其文本大很多(即使按钮使用自动布局定位)。
这是通过子类实现的方法:
class MyRedButton : UIButton {
override func layoutSubviews() {
super.layoutSubviews()
self.backgroundColor = .red
self.layer.cornerRadius = 10
}
override var intrinsicContentSize: CGSize {
var sz = super.intrinsicContentSize
sz.width += 30; sz.height += 30
return sz
}
}
Matt 赞成的答案是正确的。
他在评论中指出我最初做错的两件事是。
- 我尝试设置
backgroundLayer.position = button.center
。这是错误的,因为按钮的中心基于框架的 center 而不是 bounds 中心。我应该设置 backgroundLayer.position 以匹配按钮边界的中心 - 我试图在
viewWillLayoutSubviews
中将 backgroundLayer 的位置设置为按钮的中心,他说按钮的边界尚不清楚,因此 backgroundLayer 没有信息作为基础。我应该将代码添加到viewDidLayoutSubviews
这里是代码:
// 1. add the code to viewDidLayoutSubviews
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let text = button.titleLabel?.text
let textSize = (text! as NSString).size(withAttributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 23.0)])
backgroundLayer.frame = CGRect(x: 0, y: 0, width: textSize.width + 10, height: textSize.height + 5)
button.layer.insertSublayer(backgroundLayer, at: 0)
// 2. get the buttons bound's center by accessing it's midX and midY
let buttonMidX = button.bounds.midX
let buttonMidY = button.bounds.midY
let buttonBoundsCenter = CGPoint(x: buttonMidX, y: buttonMidY)
// 3. set the backgroundLayer's postion to the buttonBoundsCenter
backgroundLayer.position = buttonBoundsCenter
}
有效: