9

I try to create custom tabbar like the below picture: enter image description here

Below is the result i get: enter image description here

Below is my current code:

class CustomTabBarController: UITabBarController {


    override func viewDidLoad() {
        super.viewDidLoad()

        let controller1 = UIViewController()
        controller1.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 1)
        let nav1 = UINavigationController(rootViewController: controller1)

        let controller2 = UIViewController()
        controller2.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 2)
        let nav2 = UINavigationController(rootViewController: controller2)

        let controller3 = UIViewController()
        let nav3 = UINavigationController(rootViewController: controller3)
        nav3.title = ""

        let controller4 = UIViewController()
        controller4.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 4)
        let nav4 = UINavigationController(rootViewController: controller4)

        let controller5 = UIViewController()
        controller5.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 5)
        let nav5 = UINavigationController(rootViewController: controller5)

        viewControllers = [nav1, nav2, nav3, nav4, nav5]
        setupMiddleButton()  
    }

    func setupMiddleButton() {
        let menuButton = UIButton(frame: CGRect(x: 0, y: 0, width: 64, height: 64))
        var menuButtonFrame = menuButton.frame
        menuButtonFrame.origin.y = view.bounds.height - menuButtonFrame.height - 50
        menuButtonFrame.origin.x = view.bounds.width/2 - menuButtonFrame.size.width/2
        menuButton.frame = menuButtonFrame

        menuButton.backgroundColor = UIColor.red
        menuButton.layer.cornerRadius = menuButtonFrame.height/2
        view.addSubview(menuButton)

        menuButton.setImage(UIImage(named: "example"), for: .normal)
        menuButton.addTarget(self, action: #selector(menuButtonAction(sender:)), for: .touchUpInside)

        view.layoutIfNeeded()
    }


    // MARK: - Actions

    @objc private func menuButtonAction(sender: UIButton) {
        selectedIndex = 2
    }

}

How can I draw the shape of the tabbar of the first picture joint

I'm stuck on it that makes several thanks for your help

Mickael Belhassen
  • 2,970
  • 1
  • 25
  • 46
  • The controller is primarily a container view for a UITabBar and the content views, and as a UITabBar is a UIView you should just be able to assign a subclassed TabBar where you override the draw method to lay it out as you like. (Or so I'd expect - it's one of those things I keep meaning to try ) – flanker Nov 28 '19 at 15:15
  • can u help me in creating tab bar above like i have a default tab bar controller but i want my center tab bar item to be exactly like above – Dilip Tiwari Apr 28 '20 at 08:59
  • 1
    Yes look at this https://medium.com/@philipp307/draw-a-custom-ios-tabbar-shape-27d298a7f4fa – Mickael Belhassen Apr 28 '20 at 09:04
  • https://github.com/quicklearner4991/Swift-Custom-TabBar-with-big-center-rounded-button – Quick learner Jul 06 '22 at 17:44

2 Answers2

30

You need to customise the tabbar of your CustomTabBarController

Just assign the AppTabBar to the tabbar of your tabBarController for storyboard like this it should works

enter image description here

@IBDesignable
class AppTabBar: UITabBar {

    private var shapeLayer: CALayer?

    override func draw(_ rect: CGRect) {
        self.addShape()
    }

    private func addShape() {
        let shapeLayer = CAShapeLayer()
        shapeLayer.path = createPath()
        shapeLayer.strokeColor = UIColor.lightGray.cgColor
        shapeLayer.fillColor = #colorLiteral(red: 0.9782002568, green: 0.9782230258, blue: 0.9782107472, alpha: 1)
        shapeLayer.lineWidth = 0.5
        shapeLayer.shadowOffset = CGSize(width:0, height:0)
        shapeLayer.shadowRadius = 10
        shapeLayer.shadowColor = UIColor.gray.cgColor
        shapeLayer.shadowOpacity = 0.3

        if let oldShapeLayer = self.shapeLayer {
            self.layer.replaceSublayer(oldShapeLayer, with: shapeLayer)
        } else {
            self.layer.insertSublayer(shapeLayer, at: 0)
        }
        self.shapeLayer = shapeLayer
    }

    func createPath() -> CGPath {
        let height: CGFloat = 86.0
        let path = UIBezierPath()
        let centerWidth = self.frame.width / 2
        path.move(to: CGPoint(x: 0, y: 0))
        path.addLine(to: CGPoint(x: (centerWidth - height ), y: 0))
        path.addCurve(to: CGPoint(x: centerWidth, y: height - 40),
                      controlPoint1: CGPoint(x: (centerWidth - 30), y: 0), controlPoint2: CGPoint(x: centerWidth - 35, y: height - 40))
        path.addCurve(to: CGPoint(x: (centerWidth + height ), y: 0),
                      controlPoint1: CGPoint(x: centerWidth + 35, y: height - 40), controlPoint2: CGPoint(x: (centerWidth + 30), y: 0))
        path.addLine(to: CGPoint(x: self.frame.width, y: 0))
        path.addLine(to: CGPoint(x: self.frame.width, y: self.frame.height))
        path.addLine(to: CGPoint(x: 0, y: self.frame.height))
        path.close()
        return path.cgPath
    }

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        guard !clipsToBounds && !isHidden && alpha > 0 else { return nil }
        for member in subviews.reversed() {
            let subPoint = member.convert(point, from: self)
            guard let result = member.hitTest(subPoint, with: event) else { continue }
            return result
        }
        return nil
    }
}

extension UITabBar {
    override open func sizeThatFits(_ size: CGSize) -> CGSize {
        var sizeThatFits = super.sizeThatFits(size)
        sizeThatFits.height = 74
        return sizeThatFits
    }
}
Ram Mani
  • 1,009
  • 1
  • 10
  • 15
0

For Objective C :

  1. Create class of type UITabBar with name CustomizedTabBarObjeC and place the below code in CustomizedTabBarObjeC.h file.
#import <UIKit/UIKit.h>

@interface CustomizedTabBarObjeC : UITabBar
{
    CALayer *shapeLayer;
}

@end
  1. Use below code for CustomizedTabBarObjeC.m file.
#import "CustomizedTabBarObjeC.h"

@implementation CustomizedTabBarObjeC

- (void)addShape
{
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    shapeLayer.path = [self createPath];
    shapeLayer.strokeColor = [UIColor grayColor].CGColor;
    shapeLayer.fillColor = [UIColor whiteColor].CGColor;
    shapeLayer.lineWidth = 0.5;   
    CALayer *oldShapeLayer;
    if(oldShapeLayer == shapeLayer)
    {
        [self.layer replaceSublayer:oldShapeLayer
                    with:shapeLayer];
    }
    else
    {
        [self.layer insertSublayer:shapeLayer atIndex:0];
    }
    shapeLayer = shapeLayer;
}

-(void) drawRect:(CGRect)rect
{
    [super drawRect:rect];
    [self addShape];
}

-(CGPathRef) createPath
{ 
    float height = 40.0;
    UIBezierPath *path = [UIBezierPath bezierPath];
    float centerWidth = self.frame.size.width/2;
    [path moveToPoint:(CGPoint){0, 0}];
    [path addLineToPoint:(CGPoint){(centerWidth - height * 2), 0}];
    
    // First curve going down
    [path addCurveToPoint:(CGPoint){centerWidth, height} controlPoint1:(CGPoint){(centerWidth - 40), 0} controlPoint2:(CGPoint){(centerWidth - 30), height}];
    
    // Second curve going up
    [path addCurveToPoint:(CGPoint){(centerWidth + height * 2), 0} controlPoint1:(CGPoint){(centerWidth + 30), height} controlPoint2:(CGPoint){(centerWidth + 40), 0}];
    
    // Complete and close the rect path
    [path addLineToPoint:(CGPoint){(self.frame.size.width), 0}];
    [path addLineToPoint:(CGPoint){(self.frame.size.width), (self.frame.size.height)}];
    [path addLineToPoint:(CGPoint){0, (self.frame.size.height)}];
    [path closePath];
    
    return path.CGPath;
}
  1. Go to Tab Bar Controller. Select UITab view and change the name of the class with CustomizedTabBarObjeC.

Screenshot :

Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
Anonymous
  • 1
  • 2