以下の質問は私のものと似ています。
カスタム UIImage を UITabBarItem バッジとして使用するには?
自分で描く代わりに背景画像を使用することはできますか? 私のアプリは 1 桁の BadgeValue しか使用しないので、問題ないと思います。
どうしてもできない場合は、代わりにバッジの色を変更できるかどうか知りたいです。以下の質問の答えは、実際には役に立ちません。
以下の質問は私のものと似ています。
カスタム UIImage を UITabBarItem バッジとして使用するには?
自分で描く代わりに背景画像を使用することはできますか? 私のアプリは 1 桁の BadgeValue しか使用しないので、問題ないと思います。
どうしてもできない場合は、代わりにバッジの色を変更できるかどうか知りたいです。以下の質問の答えは、実際には役に立ちません。
これが最善の策です。この拡張子をファイル スコープに追加すると、バッジを好きなようにカスタマイズできます。self.tabBarController!.setBadges([1,0,2])
ルート ビュー コントローラーのいずれかを呼び出すだけです。
明確にするために、これは 3 つの項目を持つタブ バーで、バッジの値は左から右に移動します。
代わりに画像を追加したい場合は、addBadge
メソッドを変更するだけです
extension UITabBarController {
func setBadges(badgeValues: [Int]) {
var labelExistsForIndex = [Bool]()
for _ in badgeValues {
labelExistsForIndex.append(false)
}
for view in self.tabBar.subviews where view is PGTabBadge {
let badgeView = view as! PGTabBadge
let index = badgeView.tag
if badgeValues[index] == 0 {
badgeView.removeFromSuperview()
}
labelExistsForIndex[index] = true
badgeView.text = String(badgeValues[index])
}
for i in 0...(labelExistsForIndex.count - 1) where !labelExistsForIndex[i] && (badgeValues[i] > 0) {
addBadge(index: i, value: badgeValues[i], color: .red, font: UIFont(name: "Helvetica-Light", size: 11)!)
}
}
func addBadge(index: Int, value: Int, color: UIColor, font: UIFont) {
let itemPosition = CGFloat(index + 1)
let itemWidth: CGFloat = tabBar.frame.width / CGFloat(tabBar.items!.count)
let bgColor = color
let xOffset: CGFloat = 5
let yOffset: CGFloat = -12
let badgeView = PGTabBadge()
badgeView.frame.size = CGSize(width: 12, height: 12)
badgeView.center = CGPoint(x: (itemWidth * itemPosition) - (itemWidth / 2) + xOffset, y: 20 + yOffset)
badgeView.layer.cornerRadius = badgeView.bounds.width/2
badgeView.clipsToBounds = true
badgeView.textColor = UIColor.white
badgeView.textAlignment = .center
badgeView.font = font
badgeView.text = String(value)
badgeView.backgroundColor = bgColor
badgeView.tag = index
tabBar.addSubview(badgeView)
}
}
class PGTabBadge: UILabel { }
TimWhiting's answerに基づく別のソリューションを次に示します。
extension UITabBar {
func setBadge(value: String?, at index: Int, withConfiguration configuration: TabBarBadgeConfiguration = TabBarBadgeConfiguration()) {
let existingBadge = subviews.first { ($0 as? TabBarBadge)?.hasIdentifier(for: index) == true }
existingBadge?.removeFromSuperview()
guard let tabBarItems = items,
let value = value else { return }
let itemPosition = CGFloat(index + 1)
let itemWidth = frame.width / CGFloat(tabBarItems.count)
let itemHeight = frame.height
let badge = TabBarBadge(for: index)
badge.frame.size = configuration.size
badge.center = CGPoint(x: (itemWidth * itemPosition) - (0.5 * itemWidth) + configuration.centerOffset.x,
y: (0.5 * itemHeight) + configuration.centerOffset.y)
badge.layer.cornerRadius = 0.5 * configuration.size.height
badge.clipsToBounds = true
badge.textAlignment = .center
badge.backgroundColor = configuration.backgroundColor
badge.font = configuration.font
badge.textColor = configuration.textColor
badge.text = value
addSubview(badge)
}
}
class TabBarBadge: UILabel {
var identifier: String = String(describing: TabBarBadge.self)
private func identifier(for index: Int) -> String {
return "\(String(describing: TabBarBadge.self))-\(index)"
}
convenience init(for index: Int) {
self.init()
identifier = identifier(for: index)
}
func hasIdentifier(for index: Int) -> Bool {
let has = identifier == identifier(for: index)
return has
}
}
class TabBarBadgeConfiguration {
var backgroundColor: UIColor = .red
var centerOffset: CGPoint = .init(x: 12, y: -9)
var size: CGSize = .init(width: 17, height: 17)
var textColor: UIColor = .white
var font: UIFont! = .systemFont(ofSize: 11) {
didSet { font = font ?? .systemFont(ofSize: 11) }
}
static func construct(_ block: (TabBarBadgeConfiguration) -> Void) -> TabBarBadgeConfiguration {
let new = TabBarBadgeConfiguration()
block(new)
return new
}
}
うーん...組み込みのバッジの背景を変更することは、私には不可能に思えます。しかし、代わりに可能なことは次のとおりです。
TabBarController をサブクラス化し、NIB にレイアウトされたカスタム ビューを構築し、それをタブ バー内の必要な場所にあるビュー階層に追加します。
カスタム ビューでは、画像を背景として設定し、その背景の上にラベルを設定して、数値を表示し、コードで変更することができます。
次に、ビューをタブ バーの内側に配置するカスタム ビューの水平方向および垂直方向の位置を把握する必要があります。
これが少し役立つことを願っています。セバスチャン
TimWhiting の回答が Swift 4 に更新され、一部の力のアンラップが削除されました。
extension UITabBarController {
func setBadges(badgeValues: [Int]) {
var labelExistsForIndex = [Bool]()
for _ in badgeValues {
labelExistsForIndex.append(false)
}
for view in tabBar.subviews {
if let badgeView = view as? PGTabBadge {
let index = badgeView.tag
if badgeValues[index] == 0 {
badgeView.removeFromSuperview()
}
labelExistsForIndex[index] = true
badgeView.text = String(badgeValues[index])
}
}
for i in 0 ... labelExistsForIndex.count - 1 where !labelExistsForIndex[i] && badgeValues[i] > 0 {
addBadge(
index: i,
value: badgeValues[i],
color: UIColor(red: 4 / 255, green: 110 / 255, blue: 188 / 255, alpha: 1),
font: UIFont(name: "Helvetica-Light", size: 11)!
)
}
}
func addBadge(index: Int, value: Int, color: UIColor, font: UIFont) {
guard let tabBarItems = tabBar.items else { return }
let itemPosition = CGFloat(index + 1)
let itemWidth: CGFloat = tabBar.frame.width / CGFloat(tabBarItems.count)
let bgColor = color
let xOffset: CGFloat = 12
let yOffset: CGFloat = -9
let badgeView = PGTabBadge()
badgeView.frame.size = CGSize(width: 17, height: 17)
badgeView.center = CGPoint(x: (itemWidth * itemPosition) - (itemWidth / 2) + xOffset, y: 20 + yOffset)
badgeView.layer.cornerRadius = badgeView.bounds.width / 2
badgeView.clipsToBounds = true
badgeView.textColor = UIColor.white
badgeView.textAlignment = .center
badgeView.font = font
badgeView.text = String(value)
badgeView.backgroundColor = bgColor
badgeView.tag = index
tabBar.addSubview(badgeView)
}
}
class PGTabBadge: UILabel {}
サンプル画像