DEV Community

Cover image for Recreating a design from Dribbble in UIKit  :  Episode 1 - Part 1
Charles E
Charles E

Posted on • Edited on

Recreating a design from Dribbble in UIKit  :  Episode 1 - Part 1

Earlier this week, I stumbled across this youtube video of a dude recreating a design he randomly found on Dribbble using SwiftUI, and it immediately got me thinking two things:

  1. That's kinda interesting, seeing his thought process/choices

2) I should probably try my hand at that, (I think we all should brush up on our UI skills from time to time) but using UIKit.

But, but, but, WHY UIKit you may ask? Well, it boils down to preference. Most tutorials and YouTube vids these days tend to focus more on SwiftUI, understandably, as it is newer and quite easier to work with. I still like UIKit, hopefully this can become a challenge??(Can we get #LongLiveUIKit trending?)

Anyway, I said i'd get straight to the point, so...the design that caught my eye first was this one

by Mahmudur Rahman for Orizon: UI/UX Design Agency

Few things to note, a custom navigation bar is being used…actually no, the space where the navigation bar would be is replaced with (going left to right) a small circular profile image, a greeting, and a notification button. 
My approach for this was: a UIImageView, a UILabel and a UIButton

UIImageView, UILabel UIButton

// UIImageView was assigned an image file named "charles" from the assets folder, and given a corner radius of 16
let profileImage: UIImageView = {
        let iv = UIImageView()
        iv.image =  UIImage(named: "charles")
        iv.layer.cornerRadius = 16
        iv.translatesAutoresizingMaskIntoConstraints = false
        return iv
    }()
//the UILabel's font size is on the smaller size (16)
let greetingLabel: UILabel = {
        let lb = UILabel()
        lb.font = .preferredFont(forTextStyle: .callout)
        lb.translatesAutoresizingMaskIntoConstraints = false
        return lb
    }()

//The UIButton has an SF Symbol image attached, a background color, and rounded corners
let notificationButton: UIButton = {
        var btn = UIButton()
        let image = UIImage(systemName: "bell.badge")
        btn.setImage(image, for: .normal)
        btn.backgroundColor = .systemBackground
        btn.tintColor = .label
        btn.adjustsImageWhenHighlighted = false
        btn.layer.cornerRadius = 16
        btn.translatesAutoresizingMaskIntoConstraints = false
        return btn
    }()
//Add em to the main view
addSubview(profileImage)
addSubview(greetingLabel)
addSubview(notificationButton)

//Add some contraints, laying them out horizontally
NSLayoutConstraint.activate([
profileImage.topAnchor.constraint(equalToSystemSpacingBelow: safeAreaLayoutGuide.topAnchor, multiplier: 1),
// topAnchor.constraintconstraint(equalToSystemSpacingBelow: safeAreaLayoutGuide.topAnchor, multiplier: 1) 
//essentially says, the top anchor of the image is set to the top anchor of the parent view 
//within the safe area(below the notch/dynamic island), by a multiplier of 1, (which is equivalent to 8 pts)

profileImage.leadingAnchor.constraint(equalToSystemSpacingAfter: leadingAnchor, multiplier: 3),
//.leadingAnchor.constraint(equalToSystemSpacingAfter: leadingAnchor, multiplier: 3)
//essentially says, the leftmost anchor of the image is set to the left anchor of the parent view, 
// by a multiplier of 3 (3 * 8 = 24pts)

profileImage.heightAnchor.constraint(equalToConstant: 32),
profileImage.widthAnchor.constraint(equalToConstant: 32),
//height and width set to 32, which  
//along with the corner radius previously set to 16
//gives the image the circular shape


greetingLabel.centerYAnchor.constraint(equalTo: profileImage.centerYAnchor),
greetingLabel.leadingAnchor.constraint(equalToSystemSpacingAfter: profileImage.trailingAnchor, multiplier: 1),
//the greeting's Y anchor is equal to the profile image, aligning them horizontally
//the greeting's left most anchor is set to 8pts from the image's rightmost anchor

notificationButton.heightAnchor.constraint(equalToConstant: 32),
notificationButton.widthAnchor.constraint(equalToConstant: 32),
notificationButton.centerYAnchor.constraint(equalTo: greetingLabel.centerYAnchor),
trailingAnchor.constraint(equalToSystemSpacingAfter: notificationButton.trailingAnchor, multiplier: 3),
//the rightmost anchor of the parent view is set to 24(3 * 8) pts 
//from the notification button's rightmost anchor 
])
Enter fullscreen mode Exit fullscreen mode

Next there's a large title (spanning two lines). Below that there's a search bar (with text and a custom icon within it) and below that, some "pills" containing words, matching the width of the search bar above it…you probably can already visualize the code for this, but if you cant, worry not.

Large title, followed by custom search bar, followed by 'pills'

//An empty uiview with a corner radius of 25, we'll revisit this soon
let searchView: UIView = {
        let v = UIView()
        v.backgroundColor = .white
        v.layer.cornerRadius = 25
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }()

//UIButton, with an SF symbol and background color, similar to the notification button earlier
    let searchIcon : UIButton = {
        var btn = UIButton()
        let image = UIImage(systemName: "magnifyingglass")
        btn.setImage(image, for: .normal)
        btn.backgroundColor = .black
        btn.tintColor = .white
        btn.adjustsImageWhenHighlighted = false
        btn.layer.cornerRadius = 16
        btn.translatesAutoresizingMaskIntoConstraints = false
        return btn
    }()

//Textfield to input text
    let searchTextField: UITextField = {
        var tf = UITextField()
        tf.attributedPlaceholder = NSAttributedString(string: "Search your product", attributes: [.font: UIFont.preferredFont(forTextStyle: .callout),.foregroundColor: UIColor.systemGray4])
        tf.borderStyle = .none
        tf.translatesAutoresizingMaskIntoConstraints = false
        return tf
    }()
// Add to parent view
addSubview(titleLabel)
addSubview(searchView)
//the icon and textfield are ADDED to the searchview (an empty UIView)
searchView.addSubview(searchIcon)
searchView.addSubview(searchTextField)

NSLayoutConstraint.activate([
//Large title is anchored 32 pts below the first set of items, 
//leading anchor is 24 pts, trailing 32
titleLabel.topAnchor.constraint(equalToSystemSpacingBelow: greetingLabel.bottomAnchor, multiplier: 4),
titleLabel.leadingAnchor.constraint(equalToSystemSpacingAfter: leadingAnchor, multiplier: 3),
trailingAnchor.constraint(equalToSystemSpacingAfter: titleLabel.trailingAnchor, multiplier: 4),

searchView.topAnchor.constraint(equalToSystemSpacingBelow: titleLabel.bottomAnchor, multiplier: 3),
searchView.leadingAnchor.constraint(equalToSystemSpacingAfter: leadingAnchor, multiplier: 4),
//Height anchor set to 50, corner radius set to 25, giving it the circular look
searchView.heightAnchor.constraint(equalToConstant: 50),
trailingAnchor.constraint(equalToSystemSpacingAfter: searchView.trailingAnchor, multiplier: 4),

//Remember the search icon is placed WITHIN the searchview
//its Y anchor is then set to the searchview's own, centering it horizontally
searchIcon.centerYAnchor.constraint(equalTo: searchView.centerYAnchor),
searchIcon.heightAnchor.constraint(equalToConstant: 32),
searchIcon.widthAnchor.constraint(equalToConstant: 32),

//since it is to the RIGHTmost side of the searchview...
//set the SEARCHVIEW's trailing anchor to be 16 pts from the icon's trailing
//looking at that piece of code may confuse you, so think of it as...
//the right of the search icon is set to 16 pts FROM the right of the search view
searchView.trailingAnchor.constraint(equalToSystemSpacingAfter: searchIcon.trailingAnchor, multiplier: 2),

//Again, the textfield is WITHIN the searchview
//so it's Y anchor is set to the searchviews, centering it horizontally
searchTextField.centerYAnchor.constraint(equalTo: searchView.centerYAnchor),
searchTextField.leadingAnchor.constraint(equalToSystemSpacingAfter: searchView.leadingAnchor, multiplier: 3)
])
Enter fullscreen mode Exit fullscreen mode

But wait…….what about the 'pills'?

Dont do drugs

That involves a bit more thought (AND code) so we'll stop here for now...but you can always take a peek at the repo for the completed project!

Top comments (0)