【发布时间】:2012-10-31 18:03:03
【问题描述】:
我想更改UITabBarItem徽章的背景颜色,但找不到任何有关如何制作的资源。
【问题讨论】:
标签: iphone objective-c ios uitabbar uitabbaritem
我想更改UITabBarItem徽章的背景颜色,但找不到任何有关如何制作的资源。
【问题讨论】:
标签: iphone objective-c ios uitabbar uitabbaritem
UITabBarItem 从 iOS 10 开始提供此功能。
var badgeColor: UIColor? { get set }
它也可以通过外观获得。
if #available(iOS 10, *) {
UITabBarItem.appearance().badgeColor = .green
}
参考文档: https://developer.apple.com/reference/uikit/uitabbaritem/1648567-badgecolor
【讨论】:
respondsToSelector resp #available 电话中附上这个吗?
现在在 iOS 10 及更高版本中原生支持更改徽章颜色,使用 UITabBarItem 中的 badgeColor 属性。有关该物业的更多信息,请参阅apple docs。
例子:
myTab.badgeColor = UIColor.blue
[myTab setBadgeColor:[UIColor blueColor]];
【讨论】:
我为我的应用编写了这段代码,但我只在 iOS 7 中对其进行了测试。
for (UIView* tabBarButton in self.tabBar.subviews) {
for (UIView* badgeView in tabBarButton.subviews) {
NSString* className = NSStringFromClass([badgeView class]);
// looking for _UIBadgeView
if ([className rangeOfString:@"BadgeView"].location != NSNotFound) {
for (UIView* badgeSubview in badgeView.subviews) {
NSString* className = NSStringFromClass([badgeSubview class]);
// looking for _UIBadgeBackground
if ([className rangeOfString:@"BadgeBackground"].location != NSNotFound) {
@try {
[badgeSubview setValue:[UIImage imageNamed:@"YourCustomImage.png"] forKey:@"image"];
}
@catch (NSException *exception) {}
}
if ([badgeSubview isKindOfClass:[UILabel class]]) {
((UILabel *)badgeSubview).textColor = [UIColor greenColor];
}
}
}
}
}
您只能使用图像而不是颜色来更新徽章背景。如果您想以某种方式更新它,我还公开了徽章标签。
需要注意的是,这段代码必须在设置tabBarItem.badgeValue后调用!
编辑:2014 年 4 月 14 日
上面的代码在任何地方调用时都可以在 iOS 7 中运行。要让它在 iOS 7.1 中工作,请在视图控制器 -viewWillLayoutSubviews 中调用它。
编辑:2014 年 12 月 22 日
这是我目前正在使用的更新后的 sn-p。为简单起见,我将代码放在类别扩展中。
- (void)badgeViews:(void (^)(UIView* badgeView, UILabel* badgeLabel, UIView* badgeBackground))block {
if (block) {
for (UIView* tabBarButton in self.subviews) {
for (UIView* badgeView in tabBarButton.subviews) {
NSString* className = NSStringFromClass([badgeView class]);
if ([className rangeOfString:@"BadgeView"].location != NSNotFound) {
UILabel* badgeLabel;
UIView* badgeBackground;
for (UIView* badgeSubview in badgeView.subviews) {
NSString* className = NSStringFromClass([badgeSubview class]);
if ([badgeSubview isKindOfClass:[UILabel class]]) {
badgeLabel = (UILabel *)badgeSubview;
} else if ([className rangeOfString:@"BadgeBackground"].location != NSNotFound) {
badgeBackground = badgeSubview;
}
}
block(badgeView, badgeLabel, badgeBackground);
}
}
}
}
}
然后当你准备好调用它时,它会是这样的。
[self.tabBar badgeViews:^(UIView *badgeView, UILabel *badgeLabel, UIView *badgeBackground) {
}];
编辑:2015 年 11 月 16 日
我注意到有些人需要更清楚地了解这段代码中发生的事情。 for 循环正在搜索一些不可公开访问的视图。通过检查视图类名称是否包含预期名称的一部分,可以确保到达预期视图,同时不会引发 Apple 的任何可能的危险信号。一旦找到所有内容,就可以轻松访问这些视图来执行一个块。
值得注意的是,此代码有可能在未来的 iOS 更新中停止工作。例如,这些内部视图有朝一日可能会获得不同的类名。然而,这种可能性几乎为零,因为即使在内部,Apple 也很少将类重构为这种性质。但即使他们这样做,它也将是 UITabBarBadgeView 的标题,它仍然会达到代码中的预期点。由于 iOS9 已经推出,而且这段代码仍然可以按预期工作,因此您可以期望这个问题永远不会出现。
【讨论】:
-viewWillLayoutSubviews。
if (block) 条件放在方法的顶部:没有block 参数,此方法无论如何都不会执行任何操作。
我有同样的问题,并通过创建一个小类别将 BadgeView 替换为您可以轻松自定义的 UILabel 来解决它。
【讨论】:
对于使用 Swift 的人,我设法改进了 TimWhiting 的答案,以便让徽章视图在任何屏幕尺寸和任何方向上都能正常工作。
extension UITabBarController {
func setBadges(badgeValues: [Int]) {
for view in self.tabBar.subviews {
if view is CustomTabBadge {
view.removeFromSuperview()
}
}
for index in 0...badgeValues.count-1 {
if badgeValues[index] != 0 {
addBadge(index, value: badgeValues[index], color:UIColor(paletteItem: .Accent), font: UIFont(name: Constants.ThemeApp.regularFontName, size: 11)!)
}
}
}
func addBadge(index: Int, value: Int, color: UIColor, font: UIFont) {
let badgeView = CustomTabBadge()
badgeView.clipsToBounds = true
badgeView.textColor = UIColor.whiteColor()
badgeView.textAlignment = .Center
badgeView.font = font
badgeView.text = String(value)
badgeView.backgroundColor = color
badgeView.tag = index
tabBar.addSubview(badgeView)
self.positionBadges()
}
override public func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.positionBadges()
}
// Positioning
func positionBadges() {
var tabbarButtons = self.tabBar.subviews.filter { (view: UIView) -> Bool in
return view.userInteractionEnabled // only UITabBarButton are userInteractionEnabled
}
tabbarButtons = tabbarButtons.sort({ $0.frame.origin.x < $1.frame.origin.x })
for view in self.tabBar.subviews {
if view is CustomTabBadge {
let badgeView = view as! CustomTabBadge
self.positionBadge(badgeView, items:tabbarButtons, index: badgeView.tag)
}
}
}
func positionBadge(badgeView: UIView, items: [UIView], index: Int) {
let itemView = items[index]
let center = itemView.center
let xOffset: CGFloat = 12
let yOffset: CGFloat = -14
badgeView.frame.size = CGSizeMake(17, 17)
badgeView.center = CGPointMake(center.x + xOffset, center.y + yOffset)
badgeView.layer.cornerRadius = badgeView.bounds.width/2
tabBar.bringSubviewToFront(badgeView)
}
}
class CustomTabBadge: UILabel {}
【讨论】:
不,您不能更改颜色,但您可以使用自己的徽章。在文件范围内添加此扩展名,您可以根据需要自定义徽章。只需在您的任何根视图控制器中调用self.tabBarController!.setBadges([1,0,2])。
需要明确的是,标签栏包含三个项目,徽章值从左到右。
extension UITabBarController {
func setBadges(badgeValues:[Int]){
var labelExistsForIndex = [Bool]()
for value in badgeValues {
labelExistsForIndex.append(false)
}
for view in self.tabBar.subviews {
if view.isKindOfClass(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 var i=0;i<labelExistsForIndex.count;i++ {
if labelExistsForIndex[i] == false {
if badgeValues[i] > 0 {
addBadge(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){
let itemPosition = CGFloat(index+1)
let itemWidth:CGFloat = tabBar.frame.width / CGFloat(tabBar.items!.count)
let bgColor = color
let xOffset:CGFloat = 12
let yOffset:CGFloat = -9
var badgeView = PGTabBadge()
badgeView.frame.size=CGSizeMake(17, 17)
badgeView.center=CGPointMake((itemWidth * itemPosition)-(itemWidth/2)+xOffset, 20+yOffset)
badgeView.layer.cornerRadius=badgeView.bounds.width/2
badgeView.clipsToBounds=true
badgeView.textColor=UIColor.whiteColor()
badgeView.textAlignment = .Center
badgeView.font = font
badgeView.text = String(value)
badgeView.backgroundColor = bgColor
badgeView.tag=index
tabBar.addSubview(badgeView)
}
}
class PGTabBadge: UILabel {
}
【讨论】:
Swift 3 这是 Swift 3 的 @Kirualex 答案的更新版本(改进了 @TimWhiting 的答案)。
extension UITabBarController {
func setBadges(badgeValues: [Int]) {
for view in self.tabBar.subviews {
if view is CustomTabBadge {
view.removeFromSuperview()
}
}
for index in 0...badgeValues.count-1 {
if badgeValues[index] != 0 {
addBadge(index: index, value: badgeValues[index], color: UIColor.blue, font: UIFont(name: "Helvetica-Light", size: 11)!)
}
}
}
func addBadge(index: Int, value: Int, color: UIColor, font: UIFont) {
let badgeView = CustomTabBadge()
badgeView.clipsToBounds = true
badgeView.textColor = UIColor.white
badgeView.textAlignment = .center
badgeView.font = font
badgeView.text = String(value)
badgeView.backgroundColor = color
badgeView.tag = index
tabBar.addSubview(badgeView)
self.positionBadges()
}
override open func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.positionBadges()
}
// Positioning
func positionBadges() {
var tabbarButtons = self.tabBar.subviews.filter { (view: UIView) -> Bool in
return view.isUserInteractionEnabled // only UITabBarButton are userInteractionEnabled
}
tabbarButtons = tabbarButtons.sorted(by: { $0.frame.origin.x < $1.frame.origin.x })
for view in self.tabBar.subviews {
if view is CustomTabBadge {
let badgeView = view as! CustomTabBadge
self.positionBadge(badgeView: badgeView, items:tabbarButtons, index: badgeView.tag)
}
}
}
func positionBadge(badgeView: UIView, items: [UIView], index: Int) {
let itemView = items[index]
let center = itemView.center
let xOffset: CGFloat = 12
let yOffset: CGFloat = -14
badgeView.frame.size = CGSize(width: 17, height: 17)
badgeView.center = CGPoint(x: center.x + xOffset, y: center.y + yOffset)
badgeView.layer.cornerRadius = badgeView.bounds.width/2
tabBar.bringSubview(toFront: badgeView)
}
}
class CustomTabBadge: UILabel {}
【讨论】:
似乎没有。您只能设置该值。 来自 Apple 的文档徽章是:
显示在项目右上角的文本,带有 环绕红色椭圆形。
【讨论】:
您需要在索引处指定标签项以更改徽章颜色,#available in iOS 10,
if #available(iOS 10.0, *)
{
self.kAppTabBarController.tabBar.items![1].badgeColor = YOUR_COLOR
}
【讨论】:
是的,但唯一可能的解决方案是创建自定义标签栏并创建自定义标签栏徽章图标。您会发现许多用于创建自定义标签栏的文章/代码。
【讨论】:
// change TabBar BadgeView background Color
-(void)changeTabBarBadgeViewBgColor:(UITabBar*)tabBar {
for (UIView* tabBarButton in tabBar.subviews) {
for (UIView* badgeView in tabBarButton.subviews) {
NSString* className = NSStringFromClass([badgeView class]);
// looking for _UIBadgeView
if ([className rangeOfString:@"BadgeView"].location != NSNotFound) {
for (UIView* badgeSubview in badgeView.subviews) {
NSString* className = NSStringFromClass([badgeSubview class]);
// looking for _UIBadgeBackground
if ([className rangeOfString:@"BadgeBackground"].location != NSNotFound) {
@try {
[badgeSubview setValue:nil forKey:@"image"];
[badgeSubview setBackgroundColor:[UIColor blueColor]];
badgeSubview.clipsToBounds = YES;
badgeSubview.layer.cornerRadius = badgeSubview.frame.size.height/2;
}
@catch (NSException *exception) {}
}
if ([badgeSubview isKindOfClass:[UILabel class]]) {
((UILabel *)badgeSubview).textColor = [UIColor greenColor];
}
}
}
}
}
}
【讨论】:
嗯...这很容易。 [[self tabBarItem] setBadgeColor:[UIColor greenColor]];
【讨论】:
由于 iOS 15 有不同的方法,我的情况是什么:
let appearance = UITabBarAppearance()
appearance.configureWithTransparentBackground()
let barAppearance = UITabBarItemAppearance()
barAppearance.normal.badgeBackgroundColor = .green
barAppearance.normal.badgeTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.red]
appearance.stackedLayoutAppearance = barAppearance
tabBar.standardAppearance = appearance
【讨论】:
看看这里@@UITabbarItem-CustomBadge。
下面是完整的演示
如果要使用默认实现,只需要两行代码
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//supplying the animation parameter
[UITabBarItem setDefaultAnimationProvider:[[DefaultTabbarBadgeAnimation alloc] init]];
[UITabBarItem setDefaultConfigurationProvider:[[DefaultSystemLikeBadgeConfiguration alloc] init]];
//rest of your code goes following...
return YES;
}
【讨论】: