我正在尝试添加一个底部边框到我的标签。以下是代码:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .systemBackground
self.navigationItem.titleView = UIImageView(
image: UIImage(named: "Twitter")!.resize(25, 25)
)
let leftBarImage = UIImageView(
image: UIImage(named: "Profile")!.resize(35, 35)
)
leftBarImage.layer.borderWidth = 1
leftBarImage.layer.borderColor = UIColor.systemGray4.cgColor
leftBarImage.layer.cornerRadius = leftBarImage.frame.width / 2
leftBarImage.clipsToBounds = true
self.navigationItem.leftBarButtonItem = UIBarButtonItem(
customView: leftBarImage
)
let segmentedControl = UIStackView()
segmentedControl.translatesAutoresizingMaskIntoConstraints = false
segmentedControl.axis = .horizontal
segmentedControl.alignment = .center
segmentedControl.distribution = .fillEqually
segmentedControl.backgroundColor = .green
segmentedControl.addBorder(
for: .Bottom,
color: UIColor.red.cgColor,
thickness: 20
)
for menuLabelText in ["For you", "Following"] {
let menuLabel = UILabel()
menuLabel.text = menuLabelText
menuLabel.textAlignment = .center
menuLabel.font = UIFont.boldSystemFont(ofSize: 16)
segmentedControl.addArrangedSubview(menuLabel)
}
self.view.addSubview(segmentedControl)
NSLayoutConstraint.activate([
segmentedControl.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
segmentedControl.widthAnchor.constraint(equalTo: view.safeAreaLayoutGuide.widthAnchor)
])
}
}
以及边界逻辑,
import UIKit
extension UIView {
enum BorderSide {
case Left, Right, Top, Bottom
}
func addBorder(for side: BorderSide, color: CGColor, thickness: CGFloat) {
let border = CALayer()
border.backgroundColor = color
switch side {
case .Left:
border.frame = CGRect(
x: frame.minX,
y: frame.minY,
width: thickness,
height: frame.height
)
break
case .Right:
border.frame = CGRect(
x: frame.maxX,
y: frame.minY,
width: thickness,
height: frame.height
)
break
case .Top:
border.frame = CGRect(
x: frame.minX,
y: frame.minY,
width: frame.width,
height: thickness
)
break
case .Bottom:
border.frame = CGRect(
x: frame.minX,
y: frame.maxY,
width: frame.width,
height: thickness
)
break
}
layer.addSublayer(border)
}
}
边框根本不显示。下面是截图:
你可以看到绿色的背景,但没有红色的边界下面。任何帮助将不胜感激。谢谢!
1条答案
按热度按时间kqlmhetl1#
首先,我们来看看代码有什么问题......
UIView
扩展中的addBorder(...)
函数使用视图的frame
--所以,让我们在尝试添加边框之前放置一个print()
语句,以查看视图的框架:您将在调试控制台中看到以下内容:
因此,您的扩展尝试设置层的帧:
正如我们所看到的,我们最终得到了一个
(x: 0.0, y: 0.0, width: 0.0, height: 20.0)
的层帧......我们什么也看不到,因为它没有宽度。因此,让我们尝试在
viewDidLayoutSubviews()
中添加边框。注意,我们将把
segmentedControl
的创建移到viewDidLoad()
之外,这样我们就可以在其他地方引用它,并且,我们将把addBorder()
保留为原来的red,然后在viewDidLayoutSubviews()
中用blue再次调用它:现在,我们看到两个“打印帧”输出:
不幸的是,这是结果:
蓝色层位于堆栈视图/标签底部的下方。
这是因为扩展使用的是
frame.maxY
--它是frame.origin.y + frame.size.height
--而框架的origin.y
是97.66666666666667
(它的顶部在导航栏下面)。您 * 可以 * 使用相同的
addBorder()
方法,方法是在视图布局之后(也就是说,在帧设置之后)调用它,并修改扩展以使用视图的bounds
而不是frame
:我们就得到了这个
然而......很明显,这不是一个好方法。值得注意的是,
layer
出现在视图的边界之外。因此,如果您添加一个约束在segmentedControl
底部的子视图,**该视图的顶部将被20点高的“边界”层覆盖。我的猜测是,你也会希望能够点击标签...可能你也想移动“边界”,以显示只在选定的标签...等。
做一些搜索/探索如何子类化
UIView
,以便它自己处理所有这些。