avatarYi 🐍🐏

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

3699

Abstract

/span> <span class="hljs-type">BadgeView</span>.defaultTextFont

    <span class="hljs-keyword">self</span>.addSubview(<span class="hljs-keyword">self</span>.displayLabel)
    <span class="hljs-type">NSLayoutConstraint</span>.activate([
        <span class="hljs-keyword">self</span>.displayLabel.topAnchor.constraint(equalTo: <span class="hljs-keyword">self</span>.topAnchor, constant: <span class="hljs-number">16</span>),
        <span class="hljs-keyword">self</span>.displayLabel.bottomAnchor.constraint(equalTo: <span class="hljs-keyword">self</span>.bottomAnchor, constant: <span class="hljs-operator">-</span><span class="hljs-number">16</span>),
        <span class="hljs-keyword">self</span>.displayLabel.leadingAnchor.constraint(equalTo: <span class="hljs-keyword">self</span>.leadingAnchor, constant: <span class="hljs-number">16</span>),
        <span class="hljs-keyword">self</span>.displayLabel.trailingAnchor.constraint(equalTo: <span class="hljs-keyword">self</span>.trailingAnchor, constant: <span class="hljs-operator">-</span><span class="hljs-number">16</span>),
        <span class="hljs-keyword">self</span>.displayLabel.widthAnchor.constraint(equalTo: <span class="hljs-keyword">self</span>.displayLabel.heightAnchor)
    ])
}

<span class="hljs-keyword">required</span> <span class="hljs-keyword">init?</span>(<span class="hljs-params">coder</span>: <span class="hljs-type">NSCoder</span>) {
    <span class="hljs-built_in">fatalError</span>(<span class="hljs-string">"init(coder:) has not been implemented"</span>)
}

<span class="hljs-comment">/// Designate Initializer.</span>
<span class="hljs-keyword">init</span>(<span class="hljs-params">withSize</span> <span class="hljs-params">size</span>: <span class="hljs-type">CGFloat</span>) {
    <span class="hljs-keyword">let</span> frame <span class="hljs-operator">=</span> <span class="hljs-type">CGRect</span>(x: <span class="hljs-number">0</span>, y: <span class="hljs-number">0</span>, width: size, height: size)
    <span class="hljs-keyword">super</span>.<span class="hljs-keyword">init</span>(frame: frame)
    <span class="hljs-keyword">self</span>.setupViews()
}

<span class="hljs-keyword">override</span> <span class="hljs-keyword">func</span> <span class="hljs-title function_">layoutSubviews</span>() {
    <span class="hljs-keyword">super</span>.layoutSubviews()
    <span class="hljs-keyword">self</span>.layer.cornerRadius <span class="hljs-operator">=</span> <span class="hljs-keyword">self</span>.bounds.height <span class="hljs-operator">/</span> <span class="hljs-number">2</span>
}

}

<span class="hljs-keyword">extension</span> <span class="hljs-title class_">BadgeView</span> {

<span class="hljs-keyword">var</span> displayText: <span class="hljs-type">String</span>? {
    <span class="hljs-keyword">get</span> {
        <span class="hljs-keyword">self</span>.displayLabel.text
    }
    <span class="hljs-keyword">set</span> {
        <span class="hljs-keyword">self</span>.displayLabel.text <span class="hljs-operator">=</span> newValue
    }
}

<span class="hljs-keyword">var</span> badgeTextColor: <span class="hljs-type">UIColor</span> {
    <span class="hljs-keyword">get</span> {
        <span class="hljs-keyword">self</span>.displayLabel.textColor
    }
    <span class="hljs-keyword">set</span> {
        <span class="hljs-keyword">self</span>.displayLabel.textColor <span class="hljs-operator">=</span> newValue
    }
}

<span class="hljs-keyword">var</span> badgeTextFont: <span class="hljs-type

Options

">UIFont</span> { <span class="hljs-keyword">get</span> { <span class="hljs-keyword">self</span>.displayLabel.font } <span class="hljs-keyword">set</span> { <span class="hljs-keyword">self</span>.displayLabel.font <span class="hljs-operator">=</span> newValue } }

<span class="hljs-keyword">var</span> badgeBackgroundColor: <span class="hljs-type">UIColor</span> {
    <span class="hljs-keyword">get</span> {
        <span class="hljs-keyword">self</span>.backgroundColor <span class="hljs-operator">??</span> <span class="hljs-type">BadgeView</span>.defaultBadgeBackgroundColor
    }
    <span class="hljs-keyword">set</span> {
        <span class="hljs-keyword">self</span>.backgroundColor <span class="hljs-operator">=</span> newValue
    }
}

}</pre></div><p id="019c">This code pretty much explains itself.</p><ol><li>We have a private property UILabel to display the text, which is a subview of BadgeView. It contains the possibility of customizing text’s color, font and content.</li><li>We use AutoLayout to make it have height and width equal, while expanding it’s area to its parent, while being given proper padding.</li><li>In a view’s lifecycle, layoutSubviews will be called once everything is ready to be presented/seen. It’s the best place to do the layer level customization. Setting layer’s cornerRadius will make view to be a circle.</li></ol><p id="332e">In <code>SwiftUI</code> , the Code is a little more straight forward.</p><div id="55a3"><pre><span class="hljs-comment">//</span> <span class="hljs-comment">// BadgeView.swift</span> <span class="hljs-comment">//</span> <span class="hljs-comment">// Created by Antonio081014 on 2/11/23.</span> <span class="hljs-comment">//</span>

<span class="hljs-keyword">import</span> SwiftUI

<span class="hljs-keyword">struct</span> <span class="hljs-title class_">BadgeView</span>: <span class="hljs-title class_">View</span> { <span class="hljs-meta">@State</span> <span class="hljs-keyword">var</span> displayText <span class="hljs-operator">=</span> <span class="hljs-string">"100"</span> <span class="hljs-meta">@State</span> <span class="hljs-keyword">var</span> badgeBackgroundColor <span class="hljs-operator">=</span> <span class="hljs-type">Color</span>.orange <span class="hljs-meta">@State</span> <span class="hljs-keyword">var</span> badgeTextColor <span class="hljs-operator">=</span> <span class="hljs-type">Color</span>.white <span class="hljs-meta">@State</span> <span class="hljs-keyword">var</span> badgeTextFont <span class="hljs-operator">=</span> <span class="hljs-type">Font</span>.system(.headline)

<span class="hljs-keyword">var</span> body: <span class="hljs-keyword">some</span> <span class="hljs-type">View</span> {
    <span class="hljs-type">Text</span>(displayText)
        .foregroundColor(badgeTextColor)
        .font(badgeTextFont)
        .padding(<span class="hljs-type">EdgeInsets</span>(top: <span class="hljs-number">16</span>, leading: <span class="hljs-number">16</span>, bottom: <span class="hljs-number">16</span>, trailing: <span class="hljs-number">16</span>))
        .background(badgeBackgroundColor)
        .clipShape(<span class="hljs-type">Circle</span>())
}

}</pre></div><p id="9296">We have for <code>State</code> properties to modify style and content of BadgeView.</p><p id="eb55"><b>Conclusion:</b></p><p id="0273">Here, I am not trying to say which is better, but trying to present different solutions to solving the same problem. I believe whatever works for you, then it’s good enough to be chosen.</p></article></body>

Custom View with UIKit vs SwiftUI: BadgeView

Photo by Maxwell Nelson on Unsplash

Customizing views during an iOS app/framework development could be a very common task. In this article, I’ll present how to creating a customized view, a Badge View, in both SwiftUI and UIKit.

Here is an image of what we expect as the final result:

Displaying 100 with orange background.

With UIKit ,

//
//  BadgeView.swift
//
//  Created by Antonio081014 on 2/11/23.
//  Copyright © 2023 Antonio081014.com. All rights reserved.
//

import UIKit

class BadgeView: UIView {
    private lazy var displayLabel: UILabel = {
        let label = UILabel()
        label.textAlignment = .center
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    private static let defaultTextFont = UIFont.preferredFont(forTextStyle: .headline)
    private static let defaultTextColor = UIColor.white
    private static let defaultBadgeBackgroundColor = UIColor.systemOrange
    
    private override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    private func setupViews() {
        self.backgroundColor = BadgeView.defaultBadgeBackgroundColor
        self.displayLabel.textColor = BadgeView.defaultTextColor
        self.displayLabel.font = BadgeView.defaultTextFont
        
        self.addSubview(self.displayLabel)
        NSLayoutConstraint.activate([
            self.displayLabel.topAnchor.constraint(equalTo: self.topAnchor, constant: 16),
            self.displayLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -16),
            self.displayLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 16),
            self.displayLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -16),
            self.displayLabel.widthAnchor.constraint(equalTo: self.displayLabel.heightAnchor)
        ])
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    /// Designate Initializer.
    init(withSize size: CGFloat) {
        let frame = CGRect(x: 0, y: 0, width: size, height: size)
        super.init(frame: frame)
        self.setupViews()
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        self.layer.cornerRadius = self.bounds.height / 2
    }
}

extension BadgeView {
    
    var displayText: String? {
        get {
            self.displayLabel.text
        }
        set {
            self.displayLabel.text = newValue
        }
    }
    
    var badgeTextColor: UIColor {
        get {
            self.displayLabel.textColor
        }
        set {
            self.displayLabel.textColor = newValue
        }
    }
    
    var badgeTextFont: UIFont {
        get {
            self.displayLabel.font
        }
        set {
            self.displayLabel.font = newValue
        }
    }
    
    var badgeBackgroundColor: UIColor {
        get {
            self.backgroundColor ?? BadgeView.defaultBadgeBackgroundColor
        }
        set {
            self.backgroundColor = newValue
        }
    }
}

This code pretty much explains itself.

  1. We have a private property UILabel to display the text, which is a subview of BadgeView. It contains the possibility of customizing text’s color, font and content.
  2. We use AutoLayout to make it have height and width equal, while expanding it’s area to its parent, while being given proper padding.
  3. In a view’s lifecycle, `layoutSubviews` will be called once everything is ready to be presented/seen. It’s the best place to do the layer level customization. Setting layer’s `cornerRadius` will make view to be a circle.

In SwiftUI , the Code is a little more straight forward.

//
//  BadgeView.swift
//
//  Created by Antonio081014 on 2/11/23.
//

import SwiftUI

struct BadgeView: View {
    @State var displayText = "100"
    @State var badgeBackgroundColor = Color.orange
    @State var badgeTextColor = Color.white
    @State var badgeTextFont = Font.system(.headline)
    
    var body: some View {
        Text(displayText)
            .foregroundColor(badgeTextColor)
            .font(badgeTextFont)
            .padding(EdgeInsets(top: 16, leading: 16, bottom: 16, trailing: 16))
            .background(badgeBackgroundColor)
            .clipShape(Circle())
    }
}

We have for State properties to modify style and content of BadgeView.

Conclusion:

Here, I am not trying to say which is better, but trying to present different solutions to solving the same problem. I believe whatever works for you, then it’s good enough to be chosen.

Swift
Uikit
Swiftui
iOS
Badgeview
Recommended from ReadMedium