IBDesignable ButtonView 右边框在方向更改时重叠(横向)
IBDesignable ButtonView right border overlapping on orientation change (Landscape)
我在使用 IBDesignable ButtonView
和方向管理我的 UITableView
时遇到问题。基本上,问题发生在我切换到横向时,UITableViewCell
内的 customView 的右边框重叠。只有当我将方向更改为横向时才会发生这种情况。它应该能够在单元格内正确显示右边框。
有人对这个问题有什么想法吗?我附上了一张关于我的布局组织方式和行为的图片:
In Portrait
, working as expected
In Landscape
, right border overlapping
要添加更多详细信息,每个 ButtonView
都在 Storyboard
中定义为 User Defined Runtime Attributes
的布尔值,前两个按钮也是如此。
这是IBDesignable ButtonView
实现
import UIKit
@IBDesignable
class ButtonView: UIView {
// MARK: - Properties
@IBInspectable var image: UIImage? {
didSet {
imageView.image = image
}
}
@IBInspectable var title: String? {
didSet {
titleLabel.text = title
}
}
@IBInspectable var hasRightBorder: Bool = false
@IBInspectable var disabledColor: UIColor = Colors.lightGray
@IBInspectable var enabledColor: UIColor = Colors.primary
@IBInspectable var iconSize: CGFloat = 16.0 {
didSet {
imageView.addConstraints(width: iconSize, height: iconSize)
}
}
var imageView = UIImageView()
var titleLabel = UILabel()
var button = UIButton(type: .custom)
var isEnabled = true {
didSet {
if isEnabled {
imageView.tintColor = enabledColor
titleLabel.textColor = enabledColor
} else {
imageView.tintColor = disabledColor
titleLabel.textColor = disabledColor
}
button.isEnabled = isEnabled
}
}
var buttonClosure: (() ->Void)?
// MARK: - Initializers
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
// MARK: - View lifecycle
override func layoutSubviews() {
super.layoutSubviews()
if hasRightBorder {
layer.addBorder(edge: .right, color: Colors.lightGray, thickness: 1.0)
} else {
layer.addBorder(edge: .right, color: UIColor.clear, thickness: 0.0)
}
}
// MARK: - Actions
@objc fileprivate func buttonTapped() {
buttonClosure?()
}
// MARK: - Private API
fileprivate func setupView() {
imageView.tintColor = enabledColor
imageView.translatesAutoresizingMaskIntoConstraints = false
addSubview(imageView)
imageView.topAnchor.constraint(equalTo: topAnchor, constant: 5.0).isActive = true
imageView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
titleLabel.textColor = Colors.primary
titleLabel.font = FontBook.regular.of(size: .extraSmall)
titleLabel.translatesAutoresizingMaskIntoConstraints = false
addSubview(titleLabel)
titleLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -5.0).isActive = true
titleLabel.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
button.translatesAutoresizingMaskIntoConstraints = false
addSubview(button)
button.fillSuperview(with: -10.0)
}
}
addBorder 实现
extension CALayer {
func addBorder(edge: UIRectEdge, color: UIColor, thickness: CGFloat) {
let border = CALayer();
switch edge {
case UIRectEdge.top:
border.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: thickness)
break
case UIRectEdge.bottom:
border.frame = CGRect(x:0, y:self.frame.height - thickness, width:self.frame.width, height:thickness)
break
case UIRectEdge.left:
border.frame = CGRect(x:0, y:0, width: thickness, height: self.frame.height)
break
case UIRectEdge.right:
border.frame = CGRect(x:self.frame.width - thickness, y: 0, width: thickness, height:self.frame.height)
break
default:
break
}
border.backgroundColor = color.cgColor;
addSublayer(border)
}
}
Here is how it looks in Storyboard
我使用不同的方法解决了这个问题。通过查看 this answer,我了解到包括旋转设备在内的许多事情都需要调用 layoutSubview
。这就是边界重复的原因。我正在发布我的解决方案,以防有人遇到同样的问题。
首先,我没有定义布尔值 hasRightBorder
,而是在 Storyboard
中创建了宽度为 1 的 border
然后,我在ButtonView
class里面定义了一个UIView
,设置了宽度和边框加高后添加到视图中。像魅力一样工作:)
@IBDesignable
class ButtonView: UIView {
// MARK: - Properties
@IBInspectable var image: UIImage? {
didSet {
imageView.image = image
}
}
//Add the rightBorder support
@IBInspectable var border: CGFloat = 1.0 {
didSet {
view.addConstraints(width: border, height: frame.size.height)
}
}
// MARK: - Initializers
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
//view to add right border
var view = UIView()
// MARK: - Private API
fileprivate func setupView() {
//Set the color & add it to view
view.backgroundColor = Colors.lightGray
view.translatesAutoresizingMaskIntoConstraints = false
addSubview(view)
view.rightAnchor.constraint(equalTo: rightAnchor, constant: 0).isActive = true
}
}
我在使用 IBDesignable ButtonView
和方向管理我的 UITableView
时遇到问题。基本上,问题发生在我切换到横向时,UITableViewCell
内的 customView 的右边框重叠。只有当我将方向更改为横向时才会发生这种情况。它应该能够在单元格内正确显示右边框。
有人对这个问题有什么想法吗?我附上了一张关于我的布局组织方式和行为的图片:
In Portrait
, working as expected
In Landscape
, right border overlapping
要添加更多详细信息,每个 ButtonView
都在 Storyboard
中定义为 User Defined Runtime Attributes
的布尔值,前两个按钮也是如此。
这是IBDesignable ButtonView
实现
import UIKit
@IBDesignable
class ButtonView: UIView {
// MARK: - Properties
@IBInspectable var image: UIImage? {
didSet {
imageView.image = image
}
}
@IBInspectable var title: String? {
didSet {
titleLabel.text = title
}
}
@IBInspectable var hasRightBorder: Bool = false
@IBInspectable var disabledColor: UIColor = Colors.lightGray
@IBInspectable var enabledColor: UIColor = Colors.primary
@IBInspectable var iconSize: CGFloat = 16.0 {
didSet {
imageView.addConstraints(width: iconSize, height: iconSize)
}
}
var imageView = UIImageView()
var titleLabel = UILabel()
var button = UIButton(type: .custom)
var isEnabled = true {
didSet {
if isEnabled {
imageView.tintColor = enabledColor
titleLabel.textColor = enabledColor
} else {
imageView.tintColor = disabledColor
titleLabel.textColor = disabledColor
}
button.isEnabled = isEnabled
}
}
var buttonClosure: (() ->Void)?
// MARK: - Initializers
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
// MARK: - View lifecycle
override func layoutSubviews() {
super.layoutSubviews()
if hasRightBorder {
layer.addBorder(edge: .right, color: Colors.lightGray, thickness: 1.0)
} else {
layer.addBorder(edge: .right, color: UIColor.clear, thickness: 0.0)
}
}
// MARK: - Actions
@objc fileprivate func buttonTapped() {
buttonClosure?()
}
// MARK: - Private API
fileprivate func setupView() {
imageView.tintColor = enabledColor
imageView.translatesAutoresizingMaskIntoConstraints = false
addSubview(imageView)
imageView.topAnchor.constraint(equalTo: topAnchor, constant: 5.0).isActive = true
imageView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
titleLabel.textColor = Colors.primary
titleLabel.font = FontBook.regular.of(size: .extraSmall)
titleLabel.translatesAutoresizingMaskIntoConstraints = false
addSubview(titleLabel)
titleLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -5.0).isActive = true
titleLabel.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
button.translatesAutoresizingMaskIntoConstraints = false
addSubview(button)
button.fillSuperview(with: -10.0)
}
}
addBorder 实现
extension CALayer {
func addBorder(edge: UIRectEdge, color: UIColor, thickness: CGFloat) {
let border = CALayer();
switch edge {
case UIRectEdge.top:
border.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: thickness)
break
case UIRectEdge.bottom:
border.frame = CGRect(x:0, y:self.frame.height - thickness, width:self.frame.width, height:thickness)
break
case UIRectEdge.left:
border.frame = CGRect(x:0, y:0, width: thickness, height: self.frame.height)
break
case UIRectEdge.right:
border.frame = CGRect(x:self.frame.width - thickness, y: 0, width: thickness, height:self.frame.height)
break
default:
break
}
border.backgroundColor = color.cgColor;
addSublayer(border)
}
}
Here is how it looks in Storyboard
我使用不同的方法解决了这个问题。通过查看 this answer,我了解到包括旋转设备在内的许多事情都需要调用 layoutSubview
。这就是边界重复的原因。我正在发布我的解决方案,以防有人遇到同样的问题。
首先,我没有定义布尔值 hasRightBorder
,而是在 Storyboard
border
然后,我在ButtonView
class里面定义了一个UIView
,设置了宽度和边框加高后添加到视图中。像魅力一样工作:)
@IBDesignable
class ButtonView: UIView {
// MARK: - Properties
@IBInspectable var image: UIImage? {
didSet {
imageView.image = image
}
}
//Add the rightBorder support
@IBInspectable var border: CGFloat = 1.0 {
didSet {
view.addConstraints(width: border, height: frame.size.height)
}
}
// MARK: - Initializers
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupView()
}
//view to add right border
var view = UIView()
// MARK: - Private API
fileprivate func setupView() {
//Set the color & add it to view
view.backgroundColor = Colors.lightGray
view.translatesAutoresizingMaskIntoConstraints = false
addSubview(view)
view.rightAnchor.constraint(equalTo: rightAnchor, constant: 0).isActive = true
}
}