uitabbartvosuitabbaritemuiappearance

Is it possible to use different colors for focused and selected state on uitabbaritems at tvOS?


In our tvOS app we have a customised tabbar. now additionally we want to change the background color of the focused/selected item. When I do by tabBarAppearance.selectionIndicatorTintColor = .purple, it changes focused and selected states to purple(while without that line code we do have different colors or at least different opacities).

no custom color focused: no custom color focused no custom color selected no custom color selected custom color focused custom color focused custom color selected custom color selected

Is it possible to use different colors for focused and selected (like I did for the item text, as you can see on the screen shots)?


Solution

  • I fixed that by setting the the standardAppearance of the tab bar each time the focus changes in my UITabBarController. The relevant code looks like this (the initial setup of appearance is only posted for completeness):

        // setting up standard appearance for the first time
        private func setupTabbarAppearance() {
            let tabBarAppearance = UITabBarAppearance()
            //...
            tabBarAppearance.selectionIndicatorTintColor = .focusedBackgroundColor // focused items
            //...
            let itemAppearance = UITabBarItemAppearance()
            //...
            itemAppearance.normal.titleTextAttributes[.foregroundColor] = .normalTextColor // used for focused AND non-focused items, 
                                                                                           // when the whole tabbar is focused
            //...
            itemAppearance.selected.titleTextAttributes[.foregroundColor] = .selectedTextColor // used for the selected item,
                                                                                               // wen tabbar is not focused
            // ...
            tabBarAppearance.inlineLayoutAppearance = itemAppearance
            tabBar.standardAppearance = tabBarAppearance
            tabBar.setNeedsLayout()
        }
    
        private func setTabBarIndicatorColor(tabBarFocused: Bool) {
            let currentAppearance = tabBar.standardAppearance
            // here is where the color is set
            currentAppearance.selectionIndicatorTintColor = tabBarFocused ? .focusedBackgroundColor : .selectedBackgroundColor
            tabBar.standardAppearance = currentAppearance
        }
    
        // change appearance each time, when focus changes in tabbar controller
        override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
            if isTabbarInHierarchy(view: context.nextFocusedView) {
                setTabBarIndicatorColor(tabBarFocused: true)
            } else {
                setTabBarIndicatorColor(tabBarFocused: false)
            }
            super.didUpdateFocus(in: context, with: coordinator)
        }
    
        private func isTabbarInHierarchy(view: UIView?) -> Bool {
            guard let view = view else {return false}
            if view == tabBar {
                return true
            }
            return isTabbarInHierarchy(view: view.superview)
        }