5

I'm trying to do a simple thing on iOS 13 - the last tab bar item should always be displayed in a different color.

I tried to use the new UITabBarItem.standardAppearance member. Here are my codes:

// first, set the default colors for the whole tab bar
let color = Style.Color.tabItem
let text = [NSAttributedString.Key.foregroundColor: color]
let selectedColor = Style.Color.tabItemSelected
let selectedText = [NSAttributedString.Key.foregroundColor: selectedColor]

let barAppearance = UITabBarItemAppearance()

barAppearance.normal.iconColor = color
barAppearance.disabled.iconColor = color
barAppearance.selected.iconColor = selectedColor
barAppearance.focused.iconColor = selectedColor

barAppearance.normal.titleTextAttributes = text
barAppearance.disabled.titleTextAttributes = text
barAppearance.selected.titleTextAttributes = selectedText
barAppearance.focused.titleTextAttributes = selectedText

tabBar.standardAppearance.stackedLayoutAppearance = barAppearance
tabBar.standardAppearance.inlineLayoutAppearance = barAppearance
tabBar.standardAppearance.compactInlineLayoutAppearance = barAppearance
tabBar.standardAppearance.backgroundColor = Style.Color.tabBar

// now, for the last item set special colors
if let lastItem = tabBar.items?.last {
    let specialColor = Style.Color.tabItemSpecial
    let specialText = [NSAttributedString.Key.foregroundColor: specialColor]
    let specialSelectedColor = Style.Color.tabItemSpecialSelected
    let specialSelectedText = [NSAttributedString.Key.foregroundColor: specialSelectedColor]

    let itemAppearance = UITabBarItemAppearance()

    itemAppearance.normal.iconColor = specialColor
    itemAppearance.disabled.iconColor = specialColor
    itemAppearance.selected.iconColor = specialSelectedColor
    itemAppearance.focused.iconColor = specialSelectedColor

    itemAppearance.normal.titleTextAttributes = specialText
    itemAppearance.disabled.titleTextAttributes = specialText
    itemAppearance.selected.titleTextAttributes = specialSelectedText
    itemAppearance.focused.titleTextAttributes = specialSelectedText

    let itemBarAppearance = UITabBarAppearance()

    itemBarAppearance.stackedLayoutAppearance = itemAppearance
    itemBarAppearance.inlineLayoutAppearance = itemAppearance
    itemBarAppearance.compactInlineLayoutAppearance = itemAppearance
    itemBarAppearance.backgroundColor = Style.Color.tabBar

    lastItem.standardAppearance = itemBarAppearance
}

Expected behavior:

All the tab items are ALWAYS shown in tabItem/tabItemSelected colors, the last tab item is ALWAYS shown in tabItemSpecial/tabItemSpecialSelected color.

Actual behavior:

When any of the items is selected except the last one - all the tabs items are shown in tabItem/tabItemSelected, including the last one! When I select the last tab bar item, it's standardAppearance style is applied TO ALL the other tab bar items too! So all of them use tabItemSpecial/tabItemSpecialSelected color scheme.

Am I doing something wrong? Or maybe I misunderstood the new APIs and there is no way to have one tab bar item to always have a different color?

Community
  • 1
  • 1
frangulyan
  • 3,580
  • 4
  • 36
  • 64
  • 1
    Basically I would say do not attempt to use the new UIBarAppearance stuff with a tab bar. It break the entire look of the tab bar. I could write you out a list of the bugs I've found but the margin is too small to hold it. – matt Oct 22 '19 at 02:16

1 Answers1

1

This is the expected behavior. You aren't customizing how a specific tab bar item looks, you are customizing how the tab bar appears when that item is the currently selected one.

David
  • 151
  • 2
  • But then the official documentation is extremely misleading. First, it says that it replaces the old appearance API, where you could set a selected image to a separate tab item. Second, https://developer.apple.com/documentation/uikit/uitabbaritem/3198079-standardappearance literally says "standardAppearance - The appearance settings FOR THIS SPECIFIC tab bar item.". Third, the description says "If the value of this property is not nil, UIKit uses the settings in this property when displaying THE ITEM." – frangulyan Oct 23 '19 at 20:44
  • That description is correct – when standardAppearance is not nil, UIKit uses these settings when displaying that item. Keep in mind that UITabBarAppearance is the appearance for a UITabBar, not for a UITabBarItem (that's what UITabBarItemAppearance is). It is likely that this could be explained more clearly, but the context here is that UITabBarAppearance describes more than just the appearance attributes for a UITabBarItem. If it worked as you posit, then the ambiguity would be why the background and layout attributes were unused. – David Oct 24 '19 at 02:32
  • So are you telling that with the new API Apple restricted the functionality and that there is no way to put individual images to tab items like before? I can hardly believe it. – frangulyan Oct 26 '19 at 21:22
  • The way the new API is constructed, no it does not allow you to customize each UTabBarItem independently. That doesn't mean it isn't possible (since you can still use the old customization API, although it is limited differently). This is the kind of thing that a feedback report is appropriate for. – David Oct 27 '19 at 01:53