2

Is is possible to set an item with two colors on the tab bar?

(I'm a beginner in swift)

What I want to achieve:

I want to have something-like a white background for each item in both active and inactive states.

-> Example of what I want


What I have tried so far:

I've been trying by using a png with transparency, white color and black color but it seems that anyhing that is not a transparent pixel is taken as the same color. (The asset I've working with is rendered as a whole color image instead of differentiating black and white)

-> The asset I thought it would work


What I think its the way but don't know how:

(This is an assumption)

I think this could be done by setting an inactive item in the background (first layer, white color) and an active item (second layer, black color) in the same coordinates with the color I want to change:

-> Two assets for Layer 1 and layer 2


I'm using an storyboard with storyboard references to set initial configuration for the assets of both active an inactive states.

I'm setting active state color programatically.

Suggestions to achive this in more elegant ways are welcome.

Thank you :)

Sid Mhatre
  • 2,880
  • 1
  • 14
  • 35
Ryoko
  • 45
  • 6
  • [This Answer](https://stackoverflow.com/a/31117874/9333764) --- [Or This one](https://stackoverflow.com/a/41175770/9333764) May answer your query – Jake Mar 01 '18 at 15:47

3 Answers3

2

Thank you all for your help.

Inspired by @Jake link, I kept searching and found that Xcode has different modes to render image assets.

Render as Template:

The default one, renders images as they were templates. (You can take any image and colorize it programatically, but it does not recognice if it has more than 1 color)

Render as Original:

The other mode, renders images as they are. So it actually recognizes if it has more than 1 color and leave them that way. This allows you to have tab bar items with multiple colors.


How can this property be modified?

Programatically:

(as a property)

tabBarItem.image = tabBarImage.withRenderingMode(.alwaysOriginal)

//or

tabBarItem.image = tabBarImage.withRenderingMode(.alwaysTemplate)

Via Interface Builder:

1. Assets Folder, 2. Select an asset, 3. Attribute Inspector

Render as: Default, Original Image, Template Image.

Ryoko
  • 45
  • 6
0

Subclass your TabbarviewController, and set the color:

tabBar.tintColor = .red
zheck
  • 238
  • 3
  • 11
0

I would probably just draw this in quartz. It's a very simple vector and would be easy to do in few lines of code. It would also react to a change of state and update accordingly. See below for an example UIView that does exactly this:

class TabIcon: UIView {

    var enabled: Bool = false {
        didSet {
            setNeedsDisplay()
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.backgroundColor = .clear
        self.isOpaque = false
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func draw(_ rect: CGRect) {

        super.draw(rect)

        let ctx = UIGraphicsGetCurrentContext()

        ctx?.setFillColor(UIColor.white.cgColor)
        ctx?.addEllipse(in: rect)
        ctx?.fillPath()

        ctx?.setFillColor(enabled ? UIColor.purple.cgColor : UIColor.lightGray.cgColor)
        ctx?.addEllipse(in: CGRect(x: rect.minX + 5, y: rect.minY + 5, width: rect.width - 10, height: rect.height - 10))
        ctx?.fillPath()

        ctx?.setFillColor(UIColor.white.cgColor)
        ctx?.addEllipse(in: CGRect(x: rect.minX + 15, y: rect.minY + 15, width: rect.width - 30, height: rect.height - 30))
        ctx?.fillPath()
    }
}

All you have to do is use this view as the tab icon, changing the enabled property when it is selected will automatically trigger a redraw. The result looks like this:

Result

Of course, fine tune the values I have used to match your design exactly. Also note I've hardcoded values, you could determine your frames based on a proportion of the overall size for better reusability.

Hope this helps!

Jacob King
  • 5,680
  • 4
  • 23
  • 43