element-ios/Riot/Modules/Common/Views/BadgedBarButtonItem.swift
2022-02-03 14:25:14 +03:00

122 lines
3.5 KiB
Swift

//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import UIKit
@objcMembers
class BadgedBarButtonItem: UIBarButtonItem {
var baseButton: UIButton
private var badgeLabel: UILabel
private var theme: Theme
var badgeText: String? {
didSet {
updateBadgeLabel()
}
}
var badgeBackgroundColor: UIColor {
didSet {
updateBadgeLabel()
}
}
var badgeTextColor: UIColor {
didSet {
updateBadgeLabel()
}
}
var badgeFont: UIFont {
didSet {
updateBadgeLabel()
}
}
var badgePadding: UIOffset {
didSet {
updateBadgeLabel()
}
}
private var shouldHideBadge: Bool {
guard let text = badgeText else {
return true
}
return text.isEmpty || text == "0" || text == "nil" || text == "null"
}
init(withBaseButton baseButton: UIButton, theme: Theme) {
self.baseButton = baseButton
self.theme = theme
badgeBackgroundColor = .gray
badgeTextColor = .white
badgeFont = .systemFont(ofSize: 12, weight: .semibold)
badgePadding = UIOffset(horizontal: 8, vertical: 2)
badgeLabel = UILabel(frame: .zero)
badgeLabel.textAlignment = .center
badgeLabel.clipsToBounds = true
baseButton.addSubview(badgeLabel)
super.init()
customView = baseButton
update(theme: theme)
updateBadgeLabel()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func updateBadgeLabel() {
badgeLabel.isHidden = shouldHideBadge
badgeLabel.backgroundColor = badgeBackgroundColor
badgeLabel.font = badgeFont
badgeLabel.textColor = badgeTextColor
let labelSize = calculateLabelSize()
var width = labelSize.width + badgePadding.horizontal
let height = labelSize.height + badgePadding.vertical
if width < height {
// let width at least be as height
width = height
}
baseButton.sizeToFit()
badgeLabel.frame = CGRect(x: baseButton.frame.width - baseButton.contentEdgeInsets.right - width/2,
y: baseButton.contentEdgeInsets.top - height/2,
width: width,
height: height)
badgeLabel.text = badgeText
badgeLabel.layer.cornerRadius = badgeLabel.frame.height/2
}
private func calculateLabelSize() -> CGSize {
let tmpLabel = UILabel(frame: badgeLabel.frame)
tmpLabel.font = badgeFont
tmpLabel.text = badgeText
tmpLabel.sizeToFit()
return tmpLabel.frame.size
}
}
extension BadgedBarButtonItem: Themable {
func update(theme: Theme) {
self.theme = theme
tintColor = theme.colors.accent
baseButton.tintColor = theme.colors.accent
}
}