Draw a Custom iOS TabBar shape

After reading an article how to create a custom Android Bottom-Bar shape I asked myself how to archive the same on iOS. Here is an image of the layout that I want to build.


First of all we need to create a custom IBDesignable UITabBar class and override the draw method. Here we need to insert a sublayer to the views layer. In the created layer we define the inner color, the stroke color, and the path that we want to draw. Furthermore, I created a switch that is replacing the layer if it already exists. This way the layout also supports orientation changes. 
Since the drawing of the path is a litte more code I extracted it into a separat method.

The actual drawing of the custom TabBar is implemented in the createPath method. With the help if the UIBezierPath we draw a line from top left to the beginning of our indentation. Here it is getting a litte tricky (at least for me). I got the correct Bézier curves by try and error and this nice tool.

After finishing the curves we simply need to connect the missing corners of the UIBezierPath.

As we set the class of the TabBar in the Interface Builder to our custom TabBar we can already see a preview of the new layout.

To add a button to the indentation I simply created a button sized 70 x 70 in the two ViewControllers. For the layout I used constraints centering the button horizontally in the view and adding its vertical center to the bottom of the TabBar. To give the button rounded corners I used the layer.cornerRadius key Path and set it to 25. Also don’t forget to enable clip to bounds.

You maybe noticed that the icons are not really centered in relation to the indentation. I found no better solution than setting the key path of titlePositionAdjustment for the UITabBarItem. The left item is shifted by -20 and the right by 20.

By executing the project you will end up with a UI that looks exactly like the requested layout, but there is one thing missing: The click area of the button.
To avoid the TabBar to receive touch events by clicking the button in the lower areas we need to override the point inside method of the TabBar and return false if the button was clicked.

Thats it!


If you do not like the Bézier curve you can also go with a circle: