Forked from joliejuly/custom-progress-bar-with-text.swift
Created
October 4, 2022 21:01
-
-
Save narciszait/ac8bacc78a75e5d8ff6b0fa35ec0796f to your computer and use it in GitHub Desktop.
Custom progress bar with text
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// PlainHorizontalProgressBar.swift | |
// | |
// Created by Julia Nikitina on 23.05.2020. | |
// Copyright © 2020 Julia Nikitina. All rights reserved. | |
// | |
import UIKit | |
@IBDesignable | |
final class PlainHorizontalProgressBar: UIView { | |
@IBInspectable | |
private var color: UIColor? = .systemPurple | |
var progress: CGFloat = 0.0 { | |
didSet { | |
setNeedsDisplay() | |
} | |
} | |
private let progressLayer = CALayer() | |
private let yellowTextLayer = CATextLayer() | |
private let purpleTextLayer = CATextLayer() | |
private let yellowMaskLayer = CAShapeLayer() | |
private let purpleMaskLayer = CAShapeLayer() | |
override init(frame: CGRect) { | |
super.init(frame: frame) | |
setupTextLayers() | |
setupProgressLayer() | |
} | |
required init?(coder: NSCoder) { | |
super.init(coder: coder) | |
setupTextLayers() | |
setupProgressLayer() | |
} | |
override func draw(_ rect: CGRect) { | |
let progressRect = CGRect( | |
origin: .zero, | |
size: CGSize(width: bounds.width * progress, height: bounds.height) | |
) | |
let leftProgressRect = CGRect( | |
origin: CGPoint(x: bounds.width * progress, y: 0), | |
size: CGSize(width: bounds.width - bounds.width * progress, height: bounds.height) | |
) | |
let yellowMask = createMaskLayer(layer: yellowMaskLayer, leftProgressRect) | |
let purpleMask = createMaskLayer(layer: purpleMaskLayer, progressRect) | |
yellowTextLayer.mask = yellowMask | |
purpleTextLayer.mask = purpleMask | |
progressLayer.frame = progressRect | |
} | |
private func setupProgressLayer() { | |
layer.addSublayer(progressLayer) | |
progressLayer.backgroundColor = color?.cgColor | |
let backgroundMask = CAShapeLayer() | |
backgroundMask.path = UIBezierPath(roundedRect: bounds, cornerRadius: bounds.height * 0.25).cgPath | |
layer.mask = backgroundMask | |
} | |
private func setupTextLayers() { | |
[yellowTextLayer, purpleTextLayer].forEach { | |
$0.string = "Optimization..." | |
$0.fontSize = 17 | |
$0.contentsScale = UIScreen.main.scale | |
$0.alignmentMode = .center | |
$0.frame = bounds | |
layer.addSublayer($0) | |
} | |
yellowTextLayer.foregroundColor = UIColor.systemYellow.cgColor | |
purpleTextLayer.foregroundColor = UIColor.systemPurple.cgColor | |
} | |
private func createMaskLayer(layer: CAShapeLayer, _ holeRect: CGRect) -> CAShapeLayer { | |
let path = CGMutablePath() | |
path.addRect(holeRect) | |
path.addRect(bounds) | |
layer.path = path | |
layer.fillRule = .evenOdd | |
layer.opacity = 1 | |
return layer | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment