UITabBar 在 iOS7 上更改一个 UITabBarItem 的背景颜色

Posted

技术标签:

【中文标题】UITabBar 在 iOS7 上更改一个 UITabBarItem 的背景颜色【英文标题】:UITabBar change background color of one UITabBarItem on iOS7 【发布时间】:2013-12-05 21:01:45 【问题描述】:

我可以更改UITabBar 中特定UITabBarItem 的背景颜色吗?

我知道如何更改所选背景的所有背景,使用:

[[UITabBar appearance] setBarTintColor:[UIColor redColor]];
[[UITabBar appearance] setTintColor:[UIColor blueColor]];
[[UITabBar appearance] setSelectedImageTintColor:[UIColor yellowColor]];

但是可以只对一项不进行子类化吗?

谢谢

【问题讨论】:

【参考方案1】:

您可以在父 tabBar 中添加子视图,并在子视图上设置背景颜色。您可以使用 tabBar 框架尺寸计算您的 tabBarItem 的偏移量和宽度,然后在下面插入子视图。

示例(在 Swift 中):

// Add background color to middle tabBarItem
let itemIndex = 2
let bgColor = UIColor(red: 0.08, green: 0.726, blue: 0.702, alpha: 1.0)

let itemWidth = tabBar.frame.width / CGFloat(tabBar.items!.count)
let bgView = UIView(frame: CGRectMake(itemWidth * itemIndex, 0, itemWidth, tabBar.frame.height))
bgView.backgroundColor = bgColor
tabBar.insertSubview(bgView, atIndex: 0)

【讨论】:

谢谢@nathan.f77 它有效,唯一的问题是只允许我更改背景颜色(我接受了你的回答,因为这实际上是我的问题)。但是当我改变背景颜色时,我还需要改变这个项目的色调.. 现在,我在项目位置的 tarBar 顶部添加一个按钮...... :( 当我复制粘贴这段代码时,xCode 报错:'Could not find member frame' on the line: let bgView =... @ChrisHarrison - 这很奇怪,因为您在上面的行中调用了tabBar.frame,所以它也应该在那里给出错误。 @nathan.f77 改成这一行: let itemWidth: CGFloat = tabBar.frame.width / CGFloat(tabBar.items!.count) 解决问题。 这真是太聪明了。我认为 insertSubview: 会阻止图标和文本。原来没有。【参考方案2】:

在 Swift 中: 此解决方案适用于使用 Auto Layout 的应用程序。其他解决方案的主要区别在于:tabBar.frame.width 没有获得实际设备的屏幕宽度。所以,bgView 出现在错误的地方。

你可以用这个来修复它:UIScreen.main.bounds.width

let tabWidth: CGFloat = UIScreen.main.bounds.width / CGFloat(self.tabbar!.items!.count)
let tabIndex: CGFloat = 2
let bgColor: UIColor = .redColor
let bgView = UIView(frame: CGRectMake(tabWidth * tabIndex, 0, tabWidth, 49))
bgView.backgroundColor = bgColor
self.tabbar!.insertSubview(bgView, atIndex: 0)

49 是默认高度UITabbar

【讨论】:

不确定这是不是由最近对自动布局的更改引起的,但这不起作用。在最后一行代码的索引 0 处插入新视图将使其他子视图(很可能是背景视图)覆盖我们的新视图。与所有视图定义一样,子视图的顺序对渲染很重要。要将新视图放在背景视图之上但在 tabIndex 项目的图像和文本之下,这似乎可以解决 ios 9/Xcode 7.3 的问题:self.tabBar!.insertSubview(bgView, atIndex: tabIndex + 2) 完美!谢谢!我确认它适用于 iOS 12.1 和 Xcode 10.1。【参考方案3】:

Objective C 解决方案:

int itemIndex = 3;
UIColor* bgColor = [UIColor colorWithRed:(245/255.f) green:(192/255.f) blue:(47/255.f) alpha:1];

float itemWidth = self.tabBarController.tabBar.frame.size.width / 5.0f; //5 = tab bar items
UIView* bgView = [[UIView alloc]initWithFrame: CGRectMake(itemWidth*itemIndex, 0,itemWidth, self.tabBarController.tabBar.frame.size.height)];
bgView.backgroundColor = bgColor;
[self.tabBarController.tabBar insertSubview:bgView atIndex:1];

【讨论】:

【参考方案4】:

为 Swift 4 更新:

let itemIndex: CGFloat = 2.0
let bgColor = UIColor.ownBlue

let itemWidth = tabBar.frame.width / CGFloat(tabBar.items!.count)
let bgView = UIView(frame: CGRect(x: itemWidth * itemIndex, y: 0, width: itemWidth, height: tabBar.frame.height))

bgView.backgroundColor = bgColor
tabBar.insertSubview(bgView, at: 0)

【讨论】:

【参考方案5】:

您无法使用 tint color 属性真正做到这一点。请参阅this post 关于即使setSelectedImageTintColor 似乎也没有真正起作用的事实(我上次检查时没有)。

解决方案是动态更改相关项目的tintColor。您可以通过实现UITabBarDelegate 方法tabBar:didSelectItem: 例如在所选项目更改时执行此操作ad hoc在应用委托中。

【讨论】:

嘿@Mundi,谢谢你的回答。我不想在选择时更改它,但一直都在更改它。我基本上有五个按钮都是白色背景的,除了中间的那个总是黑色背景。 @HuguesBR 你找到方法了吗? 不是真的,我在标签栏视图中添加了一个 uibutton,它掩盖了相关标签以达到目的...【参考方案6】:

比赛迟到了,但我就是这样做的。我使标签看起来像按钮,具有圆形视图。上面的答案,在设备旋转或应用发送到拆分窗口时会出现问题。

此解决方案将背景直接与每个选项卡结合,使用自动布局,因此它们自然会跟随选项卡栏的变化。

这是在 UITabBarController 的自定义子类上完成的。

首先,我设置选项卡项中图标的颜色(未选中为白色,选中为黑色),然后,我迭代选项卡,并为每个选项卡插入背景,使用自动布局让它们切入标签:

override func viewDidLoad() 
    super.viewDidLoad()
    let appearance = UITabBarAppearance()
    appearance.stackedLayoutAppearance.normal.iconColor = .white
    appearance.stackedLayoutAppearance.selected.iconColor = .black
    appearance.inlineLayoutAppearance.normal.iconColor = .white
    appearance.inlineLayoutAppearance.selected.iconColor = .black
    appearance.compactInlineLayoutAppearance.normal.iconColor = .white
    appearance.compactInlineLayoutAppearance.selected.iconColor = .black

    tabBar.subviews.forEach 
        if let item = $0 as? UIControl 
            let wrapper = UIView()
            wrapper.isUserInteractionEnabled = false
            wrapper.clipsToBounds = true
            wrapper.backgroundColor = tabBar.tintColor
            wrapper.layer.cornerRadius = 8
            item.insertSubview(wrapper, at: 0)
            wrapper.translatesAutoresizingMaskIntoConstraints = false
            wrapper.leadingAnchor.constraint(equalTo: item.leadingAnchor).isActive = true
            wrapper.trailingAnchor.constraint(equalTo: item.trailingAnchor).isActive = true
            wrapper.topAnchor.constraint(equalTo: item.topAnchor).isActive = true
            wrapper.bottomAnchor.constraint(equalTo: item.bottomAnchor).isActive = true
        
    

之所以如此,是因为标签栏将标签项实现为 UIControl 的内部子类,即 UIView。

我可以在控件下方添加视图。

这最终看起来像这样:

注意:关闭用户交互很重要,就像在 0 处插入一样。

缺点是无法判断哪个项目是选定的(在创建背景图像时)。

另外注意: Apple REALLY 不希望我们在标签栏中胡闹,所以我可以看到这种方法(以及上面的方法) ),在未来的一些操作系统升级中中断。

【讨论】:

以上是关于UITabBar 在 iOS7 上更改一个 UITabBarItem 的背景颜色的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS 7.1 中更改 TabBar 上的图像和标签颜色?

iOS7中的UITabBar徽章位置

在 iOS7 中移除 UITabBar 水平分隔符

iOS7 无法淡化 UIToolbar 或 UITabbar

iOS 7 uitabbar 显示,在 ios8 上不可见

iOS 7 UITabBar 徽章位置