自定义 BarButtonItem 项:在右上角添加红点,Swift 4 IOS
Posted
技术标签:
【中文标题】自定义 BarButtonItem 项:在右上角添加红点,Swift 4 IOS【英文标题】:Custom BarButtonItem Item: Add red dot on top right corner, Swift 4 IOS 【发布时间】:2018-12-19 07:16:29 【问题描述】:我想在UIbarButtonItem
的右上角添加/设置未读标志为红点,请参阅附图
我应该怎么做才能在条形按钮项目上添加/设置红点? 一旦用户点击项目然后我想删除红点。
【问题讨论】:
想法是创建一个徽章。试试这样的:gist.github.com/moflo/3939e6801dc9575903b05baa72365695 或者这个库正是你想要的:github.com/mikeMTOL/UIBarButtonItem-Badge 它是用 ObjC 编写的,但只需使用一个头文件,你就可以在你的 swift 项目中使用它 github.com/jkpang/PPBadgeView 【参考方案1】:UIButton 子类
好的,让我们开始创建自定义UIButton
子类
class ButtonWithBadge: UIButton
现在让我们创建UIView
来代表红点
let badgeView: UIView =
let view = UIView()
view.layer.cornerRadius = 3
view.backgroundColor = .red
return view
()
然后为这个子类覆盖init
并在里面添加这个badgeView
到你的按钮的右上角:设置它的约束(右和上等于按钮的锚点,宽度和高度是badgeView
的cornerRadius的两倍值)
override init(frame: CGRect)
super.init(frame: frame)
addSubview(badgeView)
badgeView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
badgeView.rightAnchor.constraint(equalTo: rightAnchor, constant: 3),
badgeView.topAnchor.constraint(equalTo: topAnchor, constant: 3),
badgeView.heightAnchor.constraint(equalToConstant: badgeView.layer.cornerRadius*2),
badgeView.widthAnchor.constraint(equalToConstant: badgeView.layer.cornerRadius*2)
])
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
接下来创建代表按钮当前状态的变量:
var isRead: Bool = false
现在让我们创建一些方法,根据isRead
的值隐藏或取消隐藏badgeView
func setBadge()
badgeView.isHidden = isRead
现在我们有了函数,对吧?所以让我们在init
的末尾和isRead
变量的didSet
中调用这个函数
class ButtonWithProperty: UIButton
var isRead: Bool = false
didSet
setBadge()
override init(frame: CGRect)
...
setBadge()
添加到 ViewController
首先为按钮和视图创建变量
lazy var barButton: ButtonWithProperty =
let button = ButtonWithProperty()
... // set color, title, target, etc.
return button
()
现在例如在viewDidLoad
中添加这个barButton
到UINavigationBar
并按照你想要的方式放置它:
override func viewDidLoad()
super.viewDidLoad()
...
guard let navigationBar = self.navigationController?.navigationBar else return
navigationBar.addSubview(barButton)
barButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
barButton.rightAnchor.constraint(equalTo: navigationBar.rightAnchor, constant: -20),
barButton.bottomAnchor.constraint(equalTo: navigationBar.bottomAnchor, constant: -6)
])
现在,当您需要时,您可以轻松更改barButton
的isRead
变量,红点消失或出现
barButton.isRead = true
class ButtonWithProperty: UIButton
var isRead: Bool = false
didSet
setBadge()
lazy var badgeView: UIView =
let view = UIView()
view.layer.cornerRadius = 3
view.backgroundColor = .red
return view
()
override init(frame: CGRect)
super.init(frame: frame)
addSubview(badgeView)
badgeView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
badgeView.rightAnchor.constraint(equalTo: rightAnchor, constant: 3),
badgeView.topAnchor.constraint(equalTo: topAnchor, constant: 3),
badgeView.heightAnchor.constraint(equalToConstant: badgeView.layer.cornerRadius*2),
badgeView.widthAnchor.constraint(equalToConstant: badgeView.layer.cornerRadius*2)
])
setBadge()
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
func setBadge()
badgeView.isHidden = isRead
ViewController 内部:
class ViewController: UIViewController
lazy var barButton: ButtonWithProperty =
let button = ButtonWithProperty()
... // color, title, target, etc.
return button
()
...
override func viewDidLoad()
super.viewDidLoad()
...
guard let navigationBar = self.navigationController?.navigationBar else return
navigationBar.addSubview(barButton)
barButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
barButton.rightAnchor.constraint(equalTo: navigationBar.rightAnchor, constant: -20),
barButton.bottomAnchor.constraint(equalTo: navigationBar.bottomAnchor, constant: -6)
])
...
【讨论】:
【参考方案2】:我已经编写了一个自定义栏按钮类来处理这个问题,我使用CAShapeLayer
在UIBarButtonItem
上绘制一个点。
// Custom Bar button
class CustomBarButton: UIBarButtonItem
// Unread Mark
private var unreadMark: CAShapeLayer?
// Keep track of unread status
var hasUnread: Bool = false
didSet
setUnread(hasUnread: hasUnread)
// Toggles unread status
private func setUnread(hasUnread: Bool)
if hasUnread
unreadMark = CAShapeLayer();
unreadMark?.path = UIBezierPath(ovalIn: CGRect(x: (self.customView?.frame.width ?? 0) - 10, y: 5, width: 5, height: 5)).cgPath;
unreadMark?.fillColor = UIColor.red.cgColor
self.customView?.layer.addSublayer(unreadMark!)
else
unreadMark?.removeFromSuperlayer()
栏按钮项没有可用的图层属性,因此您需要使用自定义视图创建UIBarButtonItem
:
// Bar button property
var barButton:CustomBarButton!
// Initialisation
button = UIButton(type: .custom)
button.frame = CGRect(x: 0, y: 0, width: 70, height: 40)
button.setTitle("Right", for: .normal)
button.setTitleColor(UIColor.green, for: .normal)
// Bar button
barButton = CustomBarButton(customView: button)
button.addTarget(self, action: #selector(toggleStatus(sender:)), for: UIControl.Event.touchUpInside)
// Flexible space (Optional)
let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
toolBar.items = [flexibleSpace, barButton]
在IBAction
中,您可以使用hasUnread
属性切换状态:
@objc func toggleStatus(sender: AnyObject)
barButton.hasUnread = !barButton.hasUnread
它看起来像:
【讨论】:
以上是关于自定义 BarButtonItem 项:在右上角添加红点,Swift 4 IOS的主要内容,如果未能解决你的问题,请参考以下文章
为啥我必须在实现自定义左 barButtonItem 之前隐藏后退按钮项?