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 takes a little more code, I extracted it into a separate method.

The actual drawing of the custom TabBar is implemented in the createPath method. With the help of the UIBezierPath , we draw a line from the top left to the beginning of our indentation. Here it’s getting a little tricky (at least for me). I got the correct Bézier curves by trial 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 ViewController s. 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 receiving 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.

That's it!