Search code examples
iosswiftuinavigationcontrolleruinavigationbarsnapchat

Snapchat Navigation Bar Style - Swift


How does Snapchat make this navigation bar with the gradient background and rounded corners. Thanks!

I do not have a large enough reputation to post an image but it is the view that shows your snapchats to people, all the way to the left.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    // Override point for customization after application launch.
    // Sets background to a blank/empty image
    UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)
    // Sets shadow (line below the bar) to a blank image
    UINavigationBar.appearance().shadowImage = UIImage()
    // Sets translucent background's color
    UINavigationBar.appearance().backgroundColor = .clear
    // Set translucent
    UINavigationBar.appearance().isTranslucent = true

    return true
}

In my UITableViewControllerClass:

override func viewDidLoad() {
    super.viewDidLoad()

    tableView?.layer.cornerRadius = 15

    //Declare a gradient
    let gradient: CAGradientLayer = CAGradientLayer()
    //Set the two colors of your gradient
    gradient.colors = [UIColor.purple.cgColor, UIColor.red.cgColor]
    //Set it's location
    gradient.locations = [0.0 , 1.0]
    gradient.startPoint = CGPoint(x: 0.0, y: 0.0)
    gradient.endPoint = CGPoint(x: 1.0, y: 1.0)
    gradient.frame = CGRect(x: 0.0, y: 0.0, width: (self.navigationController?.navigationBar.frame.size.width)!, height: (self.navigationController?.navigationBar.frame.size.height)!)
    self.navigationController?.navigationBar.layer.insertSublayer(gradient, at: 0)

}

Solution

  • From what I understood, you wish to have a gradient as a background a rounded corner for your table view.

    Here is the code of my ViewController.

    class ViewController: UIViewController {
    
        @IBOutlet var backroundView: UIView!
        @IBOutlet weak var viewContainingTableView: UIView!
        @IBOutlet weak var topView: UIView!
        @IBOutlet weak var navigationBar: UINavigationBar!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            //Change the corner radius to your liking
            viewContainingTableView.layer.cornerRadius = 25
            //Make the backround of your 'navigation controller' transparent
            topView.backgroundColor = UIColor.white.withAlphaComponent(0.0)
            //Declare a gradient
            let gradient: CAGradientLayer = CAGradientLayer()
            //Set the two colors of your gradient
            gradient.colors = [UIColor.purple.cgColor, UIColor.red.cgColor]
            //Set it's location
            gradient.locations = [0.0 , 1.0]
            gradient.startPoint = CGPoint(x: 0.0, y: 0.0)
            gradient.endPoint = CGPoint(x: 1.0, y: 1.0)
            gradient.frame = CGRect(x: 0.0, y: 0.0, width: self.view.frame.size.width, height: self.view.frame.size.height)
            self.backroundView.layer.insertSublayer(gradient, at: 0)
            //self.view.layer.insertSublayer(gradient, at: 0)
        }
    }
    

    Change your didFinishLaunchingWithOptions method in your App Delegate to the following:

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        // Sets background to a blank/empty image
        UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)
        // Sets shadow (line below the bar) to a blank image
        UINavigationBar.appearance().shadowImage = UIImage()
        // Sets translucent background's color
        UINavigationBar.appearance().backgroundColor = .clear
        // Set translucent
        UINavigationBar.appearance().isTranslucent = true
        return true
    }
    

    Here is my view hierarchy:

    View hierarchy

    Here is what it gives:

    View on iPhone

    To do it without the Storyboard, change your ViewController code to the following:

    class ViewController: UIViewController {
    
        var viewContainingTableView = UIView()
        let navigationBarView = UINavigationBar()
        let topView = UIView()
        let tableView = UITableView()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            let margins = view.layoutMarginsGuide
    
            view.addSubview(topView)
            topView.translatesAutoresizingMaskIntoConstraints = false
            topView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
            topView.heightAnchor.constraint(equalToConstant: 60).isActive = true
            topView.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
            topView.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true
    
            topView.addSubview(navigationBarView)
            navigationBarView.translatesAutoresizingMaskIntoConstraints = false
            navigationBarView.topAnchor.constraint(equalTo: topView.topAnchor).isActive = true
            navigationBarView.bottomAnchor.constraint(equalTo: topView.bottomAnchor).isActive = true
            navigationBarView.leadingAnchor.constraint(equalTo: topView.leadingAnchor).isActive = true
            navigationBarView.trailingAnchor.constraint(equalTo: topView.trailingAnchor).isActive = true
            self.navigationItem.title = "Test"
    
            let buttonNavBar = UIBarButtonItem(title: "Button", style: .plain, target: nil, action: #selector(buttonAction))
            navigationItem.rightBarButtonItem = buttonNavBar
            navigationBarView.setItems([navigationItem], animated: false)
    
            view.addSubview(viewContainingTableView)
            viewContainingTableView.translatesAutoresizingMaskIntoConstraints = false
            viewContainingTableView.topAnchor.constraint(equalTo: topView.bottomAnchor, constant: 0).isActive = true
            viewContainingTableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
            viewContainingTableView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
            viewContainingTableView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
            viewContainingTableView.backgroundColor = UIColor.white
    
            viewContainingTableView.addSubview(tableView)
            tableView.translatesAutoresizingMaskIntoConstraints = false
            tableView.topAnchor.constraint(equalTo: viewContainingTableView.topAnchor, constant: 20).isActive = true
            tableView.bottomAnchor.constraint(equalTo: viewContainingTableView.bottomAnchor).isActive = true
            tableView.leadingAnchor.constraint(equalTo: viewContainingTableView.leadingAnchor).isActive = true
            tableView.trailingAnchor.constraint(equalTo: viewContainingTableView.trailingAnchor).isActive = true
    
            view.setNeedsUpdateConstraints()
            view.updateConstraints()
    
            //Change the corner radius to your liking
            viewContainingTableView.layer.cornerRadius = 25
            //Make the backround of your 'navigation controller' transparent
            topView.backgroundColor = UIColor.white.withAlphaComponent(0.0)
            //Declare a gradient
            let gradient: CAGradientLayer = CAGradientLayer()
            //Set the two colors of your gradient
            gradient.colors = [UIColor.purple.cgColor, UIColor.red.cgColor]
            //Set it's location
            gradient.locations = [0.0 , 1.0]
            gradient.startPoint = CGPoint(x: 0.0, y: 0.0)
            gradient.endPoint = CGPoint(x: 1.0, y: 1.0)
            gradient.frame = CGRect(x: 0.0, y: 0.0, width: self.view.frame.size.width, height: self.view.frame.size.height)
            self.view.layer.insertSublayer(gradient, at: 0)
        }
    
    @objc func buttonAction() { 
            //Function of your button: add code to execute when button is pressed
        }    
    }