avatarCharles E.

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

4913

Abstract

ar btn.tintColor <span class="hljs-operator">=</span> <span class="hljs-type">UIColor</span>(named: <span class="hljs-string">"whiteColor"</span>) btn.translatesAutoresizingMaskIntoConstraints <span class="hljs-operator">=</span> <span class="hljs-literal">false</span> <span class="hljs-keyword">return</span> btn }()

<span class="hljs-keyword">let</span> heartBtn : <span class="hljs-type">UIButton</span> <span class="hljs-operator">=</span> {
    <span class="hljs-keyword">let</span> btn <span class="hljs-operator">=</span> <span class="hljs-type">UIButton</span>()
    <span class="hljs-keyword">let</span> config <span class="hljs-operator">=</span> <span class="hljs-type">UIImage</span>.<span class="hljs-type">SymbolConfiguration</span>(pointSize: <span class="hljs-number">16</span>, weight: .light, scale: .large)
    <span class="hljs-keyword">let</span> image <span class="hljs-operator">=</span> <span class="hljs-type">UIImage</span>(systemName: <span class="hljs-string">"heart"</span>, withConfiguration: config)
    btn.setImage(image, for: .normal)
    btn.backgroundColor <span class="hljs-operator">=</span> .clear
    btn.tintColor <span class="hljs-operator">=</span> <span class="hljs-type">UIColor</span>(named: <span class="hljs-string">"whiteColor"</span>)
    btn.translatesAutoresizingMaskIntoConstraints <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>
        <span class="hljs-keyword">return</span> btn
    }()

<span class="hljs-keyword">let</span> userBtn : <span class="hljs-type">UIButton</span> <span class="hljs-operator">=</span> {
    <span class="hljs-keyword">let</span> btn <span class="hljs-operator">=</span> <span class="hljs-type">UIButton</span>()
    <span class="hljs-keyword">let</span> config <span class="hljs-operator">=</span> <span class="hljs-type">UIImage</span>.<span class="hljs-type">SymbolConfiguration</span>(pointSize: <span class="hljs-number">16</span>, weight: .light, scale: .large)
    <span class="hljs-keyword">let</span> image <span class="hljs-operator">=</span> <span class="hljs-type">UIImage</span>(systemName: <span class="hljs-string">"person"</span>, withConfiguration: config)
    btn.setImage(image, for: .normal)
    btn.backgroundColor <span class="hljs-operator">=</span> .clear
    btn.tintColor <span class="hljs-operator">=</span> <span class="hljs-type">UIColor</span>(named: <span class="hljs-string">"whiteColor"</span>)
    btn.translatesAutoresizingMaskIntoConstraints <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>
    <span class="hljs-keyword">return</span> btn
    }()</pre></div><p id="0ac2">Back to configTabBar(), we will set the tab bar’s rootViewController to HomeController, add the buttons we created, and then set the tab bar’s background color to black.</p><div id="b3f0"><pre>    <span class="hljs-function">func <span class="hljs-title">configTabBar</span>()</span>{

<span class="hljs-comment">//Set the HomeController we created in the previous articles </span> <span class="hljs-comment">// as the main ViewController for the tabbar</span> viewControllers = [HomeController()]

<span class="hljs-comment">//Add each of the buttons to the tab bar</span> tabBar.addSubview(homeBtn) tabBar.addSubview(bagBtn) tabBar.addSubview(heartBtn) tabBar.addSubview(userBtn) tabBar.backgroundColor = .black }</pre></div><p id="dafb">Finally(maybe, maybe not), inside of <i>configConstraints(), (</i>we’re not actually using constraints this time around, but I figured I’d keep the naming convention) we’ll set the frame of each button to span the width of the tab bar</p><div id="e18b"><pre>func <span class="hljs-title function_ invoke__">configContraints</span>(){ <span class="hljs-comment">// the x value for each button is unique</span> <span class="hljs-comment">// to place each button at a differnet location </span> <span class="hljs-comment">// along the tab bar's X (horizontal) axis.</span> <span class="hljs-comment">// You can play with these values as you like</span> homeBtn.frame = <span class="hljs-title function_ invoke__">CGRect</span>(<span class="hljs-attr">x</span>: <span class="hljs-built_in">self</span>.tabBar.bounds.width / <span class="hljs-number">8</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">0</span> , <span class="hljs-attr">width</span>: <span class="hljs-number">40</span>, <span class="hljs-attr">height</span>: <span class="hljs-number">40</span>) bagBtn.frame = <span class="hljs-title function_ invoke__">CGRect</span>(<span class="hljs-attr">x</span>: <span class="hljs-built_in">self</span>.tabBar.bounds.width / <span class="hljs-number">2.95</span>, <span class="hljs-attr">y</span>: <span class="hljs-nu

Options

mber">0</span> , <span class="hljs-attr">width</span>: <span class="hljs-number">40</span>, <span class="hljs-attr">height</span>: <span class="hljs-number">40</span>) heartBtn.frame = <span class="hljs-title function_ invoke__">CGRect</span>(<span class="hljs-attr">x</span>: <span class="hljs-built_in">self</span>.tabBar.bounds.width / <span class="hljs-number">1.75</span> , <span class="hljs-attr">y</span>: <span class="hljs-number">0</span> , <span class="hljs-attr">width</span>: <span class="hljs-number">40</span>, <span class="hljs-attr">height</span>: <span class="hljs-number">40</span>) userBtn.frame = <span class="hljs-title function_ invoke__">CGRect</span>(<span class="hljs-attr">x</span>: <span class="hljs-built_in">self</span>.tabBar.bounds.width / <span class="hljs-number">1.25</span>, <span class="hljs-attr">y</span>: <span class="hljs-number">0</span> , <span class="hljs-attr">width</span>: <span class="hljs-number">40</span>, <span class="hljs-attr">height</span>: <span class="hljs-number">40</span>)

}</pre></div><p id="c530">Running this now will produce the following :</p><figure id="b34f"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*TCcIC3WLcdKyUcCenwuVxg.png"><figcaption>YIKES</figcaption></figure><p id="22cb">This…is not quite what we wanted, but I can explain.</p><p id="5069">The default appearance of UIKit’s tab bar is rather plain in terms of visual aesthetics. To achieve our desired outcome, we need to apply some customizations.</p><p id="b6c3">Let’s head back to <i>configTabBar(), </i>we’ll use CAShapeLayer to create a shape; essentially a black horizontal rectangle with rounded corners, we will specify its width and height and then assign that shape to the Tab bar’s layer.</p><div id="09f0"><pre><span class="hljs-keyword">func</span> <span class="hljs-title function_">configTabBar</span>(){
    <span class="hljs-comment">//Set the HomeController we created in the previous articles</span>
    <span class="hljs-comment">// as the main ViewController for the tabbar</span>
    viewControllers <span class="hljs-operator">=</span> [<span class="hljs-type">HomeController</span>()]
    
    <span class="hljs-comment">//Add each of the buttons to the tab bar</span>
    tabBar.addSubview(homeBtn)
    tabBar.addSubview(bagBtn)
    tabBar.addSubview(heartBtn)
    tabBar.addSubview(userBtn)

<span class="hljs-comment">// creates a black horizontal rectangle with rounded corners </span> <span class="hljs-keyword">let</span> layer <span class="hljs-operator">=</span> <span class="hljs-type">CAShapeLayer</span>() <span class="hljs-keyword">let</span> x: <span class="hljs-type">CGFloat</span> <span class="hljs-operator">=</span> <span class="hljs-number">25</span> <span class="hljs-keyword">let</span> y: <span class="hljs-type">CGFloat</span> <span class="hljs-operator">=</span> <span class="hljs-number">20</span> <span class="hljs-keyword">let</span> height <span class="hljs-operator">=</span> <span class="hljs-keyword">self</span>.tabBar.bounds.height <span class="hljs-operator">+</span> y <span class="hljs-operator">*</span> <span class="hljs-number">1.5</span> layer.path <span class="hljs-operator">=</span> <span class="hljs-type">UIBezierPath</span>(roundedRect: <span class="hljs-type">CGRect</span>(x: x, y: <span class="hljs-keyword">self</span>.tabBar.bounds.minY <span class="hljs-operator">-</span> y, width: <span class="hljs-keyword">self</span>.tabBar.bounds.width <span class="hljs-operator">-</span> <span class="hljs-number">50</span>, height: height), cornerRadius: <span class="hljs-number">16</span>).cgPath layer.fillColor <span class="hljs-operator">=</span> <span class="hljs-type">UIColor</span>.black.cgColor <span class="hljs-comment">// assign the shape to the tabbar</span> tabBar.layer.insertSublayer(layer, at: <span class="hljs-number">0</span>)

<span class="hljs-comment">// this sets the portions of the tab bar, </span> <span class="hljs-comment">// not governed by the horizontal shape</span> <span class="hljs-comment">// to be transparent</span> tabBar.backgroundImage <span class="hljs-operator">=</span> <span class="hljs-type">UIImage</span>()

}</pre></div><figure id="caab"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*TE6fPdZ-dIE3dsivJsAnJA.gif"><figcaption>Finally!</figcaption></figure><p id="5822">We now have that customized tab bar and thus concludes this episode. If you enjoyed this series of articles or found them helpful, let me know your thoughts in the comments, stay tuned for more recreations, and as always you can find the completed code in the GitHub repo right <a href="https://github.com/CharlesAE/YT-DribbbleUI-One/tree/part_four">here</a></p></article></body>

Recreate a Dribbble App Design with UIKit Episode 1 — Part 4

This article will guide you through my thought process and approach to programmatically recreating a cool UI design.

Recreating Dribbble Designs

Hey everyone, I appreciate your return for the finale of Episode 1! As a quick reminder, way back in part 1, we dissected the design into 3 primary sections;

The header
The Body
The footer

We’re finally on the last leg of this series, so let’s kick things off by tackling the footer in this article. (I crack myself up sometimes.)

Photo by No Revisions on Unsplash

First off, create a MainTabController.swift file, as the name suggests, this will house the UITabBar, therefore make it a class of type UITabBarController. Override viewDidLoad() function and call configTabBar() and configConstraints() functions, which we will create right afterward.

override func viewDidLoad() {
        super.viewDidLoad()
        configTabBar()
        configContraints()
        
    }
    func configTabBar(){

}
    func configContraints(){

}

We’ll get back to these, but for now, let's create the tab bar items(the little buttons on the tab bar), since the design does not require a title for each item, we will use regular UIButtons here.

    
    //Create buttons
    let homeBtn: UIButton = {
        var btn = UIButton()
        let config = UIImage.SymbolConfiguration(pointSize: 16, weight: .light, scale: .large)
        let image = UIImage(systemName: "house.fill", withConfiguration: config)
        btn.setImage(image, for: .normal)
        btn.backgroundColor = UIColor(named: "orangeColor")
        btn.tintColor = .white
        btn.layer.cornerRadius = 20
        btn.translatesAutoresizingMaskIntoConstraints = false
        return btn
    }()
    let bagBtn : UIButton = {
        var btn = UIButton()
        let config = UIImage.SymbolConfiguration(pointSize: 16, weight: .light, scale: .large)
        let image = UIImage(systemName: "bag", withConfiguration: config)
        btn.setImage(image, for: .normal)
        btn.backgroundColor = .clear
        btn.tintColor = UIColor(named: "whiteColor")
        btn.translatesAutoresizingMaskIntoConstraints = false
        return btn
    }()
    
    let heartBtn : UIButton = {
        let btn = UIButton()
        let config = UIImage.SymbolConfiguration(pointSize: 16, weight: .light, scale: .large)
        let image = UIImage(systemName: "heart", withConfiguration: config)
        btn.setImage(image, for: .normal)
        btn.backgroundColor = .clear
        btn.tintColor = UIColor(named: "whiteColor")
        btn.translatesAutoresizingMaskIntoConstraints = false
            return btn
        }()
    
    let userBtn : UIButton = {
        let btn = UIButton()
        let config = UIImage.SymbolConfiguration(pointSize: 16, weight: .light, scale: .large)
        let image = UIImage(systemName: "person", withConfiguration: config)
        btn.setImage(image, for: .normal)
        btn.backgroundColor = .clear
        btn.tintColor = UIColor(named: "whiteColor")
        btn.translatesAutoresizingMaskIntoConstraints = false
        return btn
        }()

Back to configTabBar(), we will set the tab bar’s rootViewController to HomeController, add the buttons we created, and then set the tab bar’s background color to black.

    func configTabBar(){
//Set the HomeController we created in the previous articles 
// as the main ViewController for the tabbar
        viewControllers = [HomeController()]

//Add each of the buttons to the tab bar
        tabBar.addSubview(homeBtn)
        tabBar.addSubview(bagBtn)
        tabBar.addSubview(heartBtn)
        tabBar.addSubview(userBtn)
        tabBar.backgroundColor = .black
    }

Finally(maybe, maybe not), inside of configConstraints(), (we’re not actually using constraints this time around, but I figured I’d keep the naming convention) we’ll set the frame of each button to span the width of the tab bar

func configContraints(){
// the x value for each button is unique
// to place each button at a differnet location 
// along the tab bar's X (horizontal) axis.
// You can play with these values as you like
        homeBtn.frame = CGRect(x: self.tabBar.bounds.width / 8, y: 0 , width: 40, height: 40)
        bagBtn.frame = CGRect(x: self.tabBar.bounds.width / 2.95, y: 0 , width: 40, height: 40)
        heartBtn.frame = CGRect(x: self.tabBar.bounds.width / 1.75 , y: 0 , width: 40, height: 40)
        userBtn.frame = CGRect(x: self.tabBar.bounds.width / 1.25, y: 0 , width: 40, height: 40)
        
    }

Running this now will produce the following :

YIKES

This…is not quite what we wanted, but I can explain.

The default appearance of UIKit’s tab bar is rather plain in terms of visual aesthetics. To achieve our desired outcome, we need to apply some customizations.

Let’s head back to configTabBar(), we’ll use CAShapeLayer to create a shape; essentially a black horizontal rectangle with rounded corners, we will specify its width and height and then assign that shape to the Tab bar’s layer.

func configTabBar(){
        //Set the HomeController we created in the previous articles
        // as the main ViewController for the tabbar
        viewControllers = [HomeController()]
        
        //Add each of the buttons to the tab bar
        tabBar.addSubview(homeBtn)
        tabBar.addSubview(bagBtn)
        tabBar.addSubview(heartBtn)
        tabBar.addSubview(userBtn)

// creates a black horizontal rectangle with rounded corners     
        let layer = CAShapeLayer()
        let x: CGFloat = 25
        let y: CGFloat = 20
        let height = self.tabBar.bounds.height + y * 1.5
        layer.path = UIBezierPath(roundedRect: 
        CGRect(x: x, y: self.tabBar.bounds.minY - y, 
        width: self.tabBar.bounds.width - 50, 
        height: height),
        cornerRadius: 16).cgPath
        layer.fillColor = UIColor.black.cgColor
// assign the shape to the tabbar
        tabBar.layer.insertSublayer(layer, at: 0)

// this sets the portions of the tab bar, 
// not governed by the horizontal shape
// to be transparent
        tabBar.backgroundImage = UIImage()
        
    }
Finally!

We now have that customized tab bar and thus concludes this episode. If you enjoyed this series of articles or found them helpful, let me know your thoughts in the comments, stay tuned for more recreations, and as always you can find the completed code in the GitHub repo right here

Swift Programming
Swift
iOS Development
iOS App Development
UI Design
Recommended from ReadMedium