Here is what I am trying to do:
The screenshot is taken from Iphone:
Code:-
import UIKit
import MSCircularSlider
class HomeViewController: UIViewController {
@IBOutlet weak var lbl_Clock: UILabel!
@IBOutlet weak var circllarSlider: MSCircularSlider!
var timer:Timer?
var timeCount = 0
override func viewDidLoad() {
super.viewDidLoad()
UIViewSetting()
}
internal func drawUnfilledCircle(ctx: CGContext, center: CGPoint, radius: CGFloat, lineWidth: CGFloat, maximumAngle: CGFloat, lineCap: CGLineCap) {
drawArc(ctx: ctx, center: center, radius: radius, lineWidth: 30, fromAngle: 0, toAngle: maximumAngle, lineCap: lineCap)
}
internal func drawArc(ctx: CGContext, center: CGPoint, radius: CGFloat, lineWidth: CGFloat, fromAngle: CGFloat, toAngle: CGFloat, lineCap: CGLineCap) {
let cartesianFromAngle = toCartesian(toRad(Double(fromAngle)))
let cartesianToAngle = toCartesian(toRad(Double(toAngle)))
ctx.addArc(center: center, radius: radius, startAngle: CGFloat(cartesianFromAngle), endAngle: CGFloat(cartesianToAngle), clockwise: false)
ctx.setLineWidth(lineWidth)
ctx.setLineCap(lineCap)
ctx.drawPath(using: CGPathDrawingMode.stroke)
}
private func toCartesian(_ compassRad: Double) -> Double {
return compassRad - (Double.pi / 2)
}
private func toRad(_ degrees: Double) -> Double {
return ((Double.pi * degrees) / 180.0)
}
private func toDeg(_ radians: Double) -> Double {
return ((180.0 * radians) / Double.pi)
}
func UIViewSetting() {
circllarSlider.unfilledColor = ThemeColor.lightThemeImageTintColor
circllarSlider.unfilledColor = .lightGray
}
// MARK: - CLOCK_TIMER_METHOD
func timerMethod() {
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [self] timer in
self.timeCount += 1
print("Timer fired! \(timeCount)")
let hourValue = self.timeCount/3600
let hourRemValue = self.timeCount%3600
let minValue = hourRemValue/60
let minRemValue = hourRemValue%60
var hourValueStr = ""
var minValueStr = ""
if hourValue<10{
hourValueStr = "0\(hourValue.description)"
} else {
hourValueStr = hourValue.description
}
if minValue<10{
minValueStr = "0\(minValue.description)"
} else {
minValueStr = minValue.description
}
self.circllarSlider.currentValue = Double(self.timeCount)
}
}
// MARK: - VIEW_DID_LOAD_CALLING_METHODS
func SetUI(){
circllarSlider.handleType = .smallCircle
circllarSlider.handleColor = .systemGreen
circllarSlider.filledColor = .systemGreen
circllarSlider.currentValue = Double(timeCount)
}
}
Question: How to create same Circular Slider gradient colour?
Can someone please explain to me how to do this? I’ve tried with the above code but have not seen any results yet. Currently, I’m using the third-party library MSCircularSlider
. Please correct me if I’m doing something wrong, or suggest any third-party library that can be used to create the same type of slider.
Any help would be greatly appreciated
You need to work on learning one task at a time...
So, let's look at creating the "inner beveled" circle.
We'll start with creating a view with a CAGradientLayer
:
Next, we can add another CAGradientLayer
, inset a bit from the first one, with the order of the gradient colors reversed:
Now, if we add a circular mask to each layer, we can get this:
Here's the code for that custom view:
class RoundBeveledView: UIView {
public var gradColors: [UIColor] = [
.init(red: 0.95, green: 0.95, blue: 1.0, alpha: 1.0),
.init(red: 0.80, green: 0.80, blue: 0.90, alpha: 1.0),
]
private let outerBevel = CAGradientLayer()
private let innerBevel = CAGradientLayer()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
outerBevel.colors = [
gradColors[0].cgColor,
gradColors[1].cgColor,
]
innerBevel.colors = [
gradColors[1].cgColor,
gradColors[0].cgColor,
]
outerBevel.startPoint = .init(x: 0.20, y: 0.0)
outerBevel.endPoint = .init(x: 0.80, y: 1.0)
innerBevel.startPoint = .init(x: 0.20, y: 0.0)
innerBevel.endPoint = .init(x: 0.80, y: 1.0)
layer.addSublayer(outerBevel)
layer.addSublayer(innerBevel)
}
override func layoutSubviews() {
super.layoutSubviews()
outerBevel.frame = bounds
let obMask = CAShapeLayer()
obMask.path = CGPath.init(ellipseIn: outerBevel.bounds.insetBy(dx: 8.0, dy: 8.0), transform: nil)
outerBevel.mask = obMask
innerBevel.frame = outerBevel.frame.insetBy(dx: 12.0, dy: 12.0)
let ibMask = CAShapeLayer()
ibMask.path = CGPath.init(ellipseIn: innerBevel.bounds.insetBy(dx: 12.0, dy: 12.0), transform: nil)
innerBevel.mask = ibMask
}
}
and a simple controller to show it:
class ViewController: UIViewController {
let testView = RoundBeveledView()
override func viewDidLoad() {
super.viewDidLoad()
testView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(testView)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
//testView.widthAnchor.constraint(equalToConstant: 300.0),
testView.widthAnchor.constraint(equalToConstant: 240.0),
testView.heightAnchor.constraint(equalTo: testView.widthAnchor),
testView.centerXAnchor.constraint(equalTo: g.centerXAnchor),
testView.centerYAnchor.constraint(equalTo: g.centerYAnchor),
])
}
}
To complete your goal, you'll also need to add a "base" circle-masked view, a couple layers for shadows, a CAShapeLayer
for the "round bar", another layer for the tick-marks, etc.
See if you can use this example code to get started on the rest. If you need additional help, come back and ask a single, specific question about what problem you're running into.