Created
May 24, 2020 19:21
-
-
Save joliejuly/a792c2ab8d97d304d731a4a5202f741a 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