Can't get custom activity indicator to animate - ios

I rewrote a custom activity indicator that was originally in an Objc file into Swift. The activity indicator appears on scene but the animation isn't occurring.
I need some help figuring out why the animation isn't occurring:
vc:
class ViewController: UIViewController {
fileprivate lazy var customActivityView: CustomActivityView = {
let customActivityView = CustomActivityView()
customActivityView.translatesAutoresizingMaskIntoConstraints = false
customActivityView.delegate = self
customActivityView.numberOfCircles = 3
customActivityView.radius = 20
customActivityView.internalSpacing = 3
customActivityView.startAnimating()
return customActivityView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
setAnchors()
}
fileprivate func setAnchors() {
view.addSubview(customActivityView)
customActivityView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
customActivityView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
customActivityView.widthAnchor.constraint(equalToConstant: 100).isActive = true
customActivityView.heightAnchor.constraint(equalToConstant: 100).isActive = true
}
}
extension ViewController: CustomActivityViewDelegate {
func activityIndicatorView(activityIndicatorView: CustomActivityView, circleBackgroundColorAtIndex index: Int) -> UIColor {
let red = CGFloat(Double((arc4random() % 256)) / 255.0)
let green = CGFloat(Double((arc4random() % 256)) / 255.0)
let blue = CGFloat(Double((arc4random() % 256)) / 255.0)
let alpha: CGFloat = 1
return UIColor(red: red, green: green, blue: blue, alpha: alpha)
}
}
Swift file:
import UIKit
protocol CustomActivityViewDelegate: class {
func activityIndicatorView(activityIndicatorView: CustomActivityView, circleBackgroundColorAtIndex index: Int) -> UIColor
}
class CustomActivityView: UIView {
var numberOfCircles: Int = 0
var internalSpacing: CGFloat = 0
var radius: CGFloat = 0
var delay: CGFloat = 0
var duration: CFTimeInterval = 0
var defaultColor = UIColor.systemPink
var isAnimating = false
weak var delegate: CustomActivityViewDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
setupDefaults()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupDefaults()
fatalError("init(coder:) has not been implemented")
}
func setupDefaults() {
self.translatesAutoresizingMaskIntoConstraints = false
numberOfCircles = 5
internalSpacing = 5
radius = 10
delay = 0.2
duration = 0.8
}
func createCircleWithRadius(radius: CGFloat, color: UIColor, positionX: CGFloat) -> UIView {
let circle = UIView(frame: CGRect(x: positionX, y: 0, width: radius * 2, height: radius * 2))
circle.backgroundColor = color
circle.layer.cornerRadius = radius
circle.translatesAutoresizingMaskIntoConstraints = false;
return circle
}
func createAnimationWithDuration(duration: CFTimeInterval, delay: CGFloat) -> CABasicAnimation {
let anim: CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation")
anim.fromValue = 0.0
anim.toValue = 1.0
anim.autoreverses = true
anim.duration = duration
anim.isRemovedOnCompletion = false
anim.beginTime = CACurrentMediaTime()+Double(delay)
anim.repeatCount = .infinity
anim.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
return anim;
}
func addCircles() {
for i in 0..<numberOfCircles {
var color: UIColor?
color = delegate?.activityIndicatorView(activityIndicatorView: self, circleBackgroundColorAtIndex: i)
let circle = createCircleWithRadius(radius: radius,
color: ((color == nil) ? self.defaultColor : color)!,
positionX: CGFloat(i) * ((2 * self.radius) + self.internalSpacing))
circle.transform = CGAffineTransform(scaleX: 0.5, y: 0.5)
circle.layer.add(self.createAnimationWithDuration(duration: self.duration,
delay: CGFloat(i) * self.delay), forKey: "scale")
self.addSubview(circle)
}
}
func removeCircles() {
self.subviews.forEach({ $0.removeFromSuperview() })
}
#objc func startAnimating() {
if !isAnimating {
addCircles()
self.isHidden = false
isAnimating = true
}
}
#objc func stopAnimating() {
if isAnimating {
removeCircles()
self.isHidden = true
isAnimating = false
}
}
func intrinsicContentSize() -> CGSize {
let width: CGFloat = (CGFloat(self.numberOfCircles) * ((2 * self.radius) + self.internalSpacing)) - self.internalSpacing
let height: CGFloat = radius * 2
return CGSize(width: width, height: height)
}
func setNumberOfCircles(numberOfCircles: Int) {
self.numberOfCircles = numberOfCircles
self.invalidateIntrinsicContentSize()
}
func setRadius(radius: CGFloat) {
self.radius = radius
self.invalidateIntrinsicContentSize()
}
func setInternalSpacing(internalSpacing: CGFloat) {
self.internalSpacing = internalSpacing
self.invalidateIntrinsicContentSize()
}
}

I used the wrong key path for the animation:
I used
// incorrect
let anim: CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation")
but I should've used
// correct
let anim: CABasicAnimation = CABasicAnimation(keyPath: "transform.scale")

Related

Animation not happening as it is supposed to be for subclass of UIView with layers

I am trying to animate a subclass of UIView that has a some layers with shadow. In a view controller, I set this view inside a container. I animate container's height constraint. The container (the purple one in the video) animates properly, but the view that is supposed to be animated, doesn't animate the way it should be.
How it looks now
This is how I animate the container view.
func updateWhiteCircle(with progressHeight: CGFloat?) {
guard let progressHeight = progressHeight else {
return
}
neumorphicRingProgressHeightConstraint.constant = progressHeight
UIView.animate(withDuration: 1.0) { [weak self] in
self?.view.layoutIfNeeded()
}
}
Where do I get it wrong? Why doesn't it animate the way it should be?
You didn't show us how you're generating the "white shadow," but likely you're setting it in the view's layoutSubviews() func.
The problem is, that does not animate with the size of the view.
You probably want to animate the path for the "shadow layer."
Here's a quick example:
class WhiteCircleView: UIView {
private let shapeLayer = CAShapeLayer()
// public vars so we can set various properties
public var fillColor: UIColor = .white {
didSet {
shapeLayer.fillColor = fillColor.cgColor
}
}
public var shadowColor: UIColor = .white {
didSet {
shapeLayer.shadowColor = shadowColor.cgColor
}
}
public var shadowOpacity: Float = 1.0 {
didSet {
shapeLayer.shadowOpacity = shadowOpacity
}
}
public var shadowRadius: CGFloat = 20 {
didSet {
shapeLayer.shadowRadius = shadowRadius
}
}
public var shadowOffset: CGSize = .zero {
didSet {
shapeLayer.shadowOffset = shadowOffset
}
}
public var progress: CGFloat = 0 {
didSet {
animCircle()
}
}
private var curProgress: CGFloat = 0
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() -> Void {
shapeLayer.fillColor = fillColor.cgColor
shapeLayer.shadowColor = shadowColor.cgColor
shapeLayer.shadowOffset = shadowOffset
shapeLayer.shadowRadius = shadowRadius
shapeLayer.shadowOpacity = shadowOpacity
layer.addSublayer(shapeLayer)
}
override func layoutSubviews() {
let w: CGFloat = bounds.width * CGFloat(progress)
let wi: CGFloat = (bounds.width - w) * 0.5
let newPath = UIBezierPath(ovalIn: bounds.insetBy(dx: wi, dy: wi)).cgPath
shapeLayer.path = newPath
}
private func animCircle() {
print(progress)
let w: CGFloat = bounds.width * CGFloat(progress)
let wi: CGFloat = (bounds.width - w) * 0.5
let curPath = shapeLayer.path
let newPath = UIBezierPath(ovalIn: bounds.insetBy(dx: wi, dy: wi)).cgPath
CATransaction.begin()
let animation = CABasicAnimation(keyPath: "path")
animation.fromValue = curPath
animation.toValue = newPath
animation.duration = 0.5
animation.fillMode = .forwards
animation.isRemovedOnCompletion = false
CATransaction.setCompletionBlock({
// update to new path on anim end
self.shapeLayer.path = newPath
})
shapeLayer.add(animation, forKey: "grow")
CATransaction.commit()
}
}
class AnimCircleVC: UIViewController {
let wcv = WhiteCircleView()
let bkgColor: UIColor = UIColor(white: 0.75, alpha: 1.0)
var progress: CGFloat = 0
// a "center label" to show progress value
let pLabel: UILabel = {
let v = UILabel()
v.backgroundColor = .systemYellow
v.textAlignment = .center
v.text = "0%"
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = bkgColor
wcv.fillColor = bkgColor
wcv.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(wcv)
pLabel.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(pLabel)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
wcv.centerXAnchor.constraint(equalTo: g.centerXAnchor),
wcv.centerYAnchor.constraint(equalTo: g.topAnchor, constant: 200.0),
wcv.heightAnchor.constraint(equalToConstant: 200.0),
wcv.widthAnchor.constraint(equalTo: wcv.heightAnchor),
pLabel.centerXAnchor.constraint(equalTo: wcv.centerXAnchor),
pLabel.centerYAnchor.constraint(equalTo: wcv.centerYAnchor),
pLabel.widthAnchor.constraint(equalToConstant: 100.0),
pLabel.heightAnchor.constraint(equalTo: pLabel.widthAnchor),
])
pLabel.layer.cornerRadius = 50.0
pLabel.layer.masksToBounds = true
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if progress >= 1.0 {
// shrink it away
progress = 0.0
} else {
if progress == 0.0 {
// start at 60%
progress = 0.6
} else {
// increment by 10%
progress += 0.10
}
}
// floating point can result in 0.99999...
// so round to 1/100th
progress = (progress * 100).rounded() / 100.0
wcv.progress = progress
pLabel.text = "\(Int(progress * 100))%"
}
}

CircleProgressBar around an image

I have a circular ProgressBar and I try to change to .clear the colour of a mask (CAShapeLayer) over a ImageView (under the ProgressBar) but for some reason when the progress is loading then the whole mask disappear instantly instead to vanish during the progress.
Can anyone help me to identify the bug ?
Here is my demo project: https://github.com/tygruletz/CircularProgressBar
Here is the code for my ProgressBar:
class CircularProgressBar: UIView {
var currentProgress = 0
//MARK: awakeFromNib
override func awakeFromNib() {
super.awakeFromNib()
setupView()
label.text = "\(currentProgress)"
}
//MARK: Public
public var lineWidth:CGFloat = 120 {
didSet{
foregroundLayer.lineWidth = lineWidth
backgroundLayer.lineWidth = lineWidth - (0.20 * lineWidth)
}
}
public var labelSize: CGFloat = 20 {
didSet {
label.font = UIFont.systemFont(ofSize: labelSize)
label.sizeToFit()
configLabel()
}
}
public var safePercent: Int = 100 {
didSet{
setForegroundLayerColorForSafePercent()
}
}
public func setProgress(to progressConstant: Double, withAnimation: Bool) {
var progress: Double {
get {
if progressConstant > 1 { return 1 }
else if progressConstant < 0 { return 0 }
else { return progressConstant }
}
}
foregroundLayer.strokeEnd = CGFloat(progress)
if withAnimation {
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = 0
animation.toValue = progress
animation.duration = 2
foregroundLayer.add(animation, forKey: "foregroundAnimation")
}
var currentTime:Double = 0
let timer = Timer.scheduledTimer(withTimeInterval: 0.05, repeats: true) { (timer) in
if currentTime >= 2{
timer.invalidate()
} else {
currentTime += 0.05
let percent = currentTime/2 * 100
self.currentProgress = Int(progress * percent)
self.label.text = "\(self.currentProgress)%"
self.setForegroundLayerColorForSafePercent()
self.configLabel()
}
}
timer.fire()
}
//MARK: Private
private var label = UILabel()
private let foregroundLayer = CAShapeLayer()
private let backgroundLayer = CAShapeLayer()
private var radius: CGFloat {
get{
if self.frame.width < self.frame.height { return (self.frame.width - lineWidth)/2 }
else { return (self.frame.height - lineWidth)/2 }
}
}
private var pathCenter: CGPoint{ get{ return self.convert(self.center, from:self.superview) } }
private func makeBar(){
self.layer.sublayers = nil
drawBackgroundLayer()
drawForegroundLayer()
}
private func drawBackgroundLayer(){
let path = UIBezierPath(arcCenter: pathCenter, radius: self.radius, startAngle: 0, endAngle: 2*CGFloat.pi, clockwise: true)
self.backgroundLayer.path = path.cgPath
self.backgroundLayer.strokeColor = UIColor(red: CGFloat(105/255.0), green: CGFloat(105/255.0), blue: CGFloat(105/255.0), alpha: 0.85).cgColor
self.backgroundLayer.lineWidth = lineWidth - (lineWidth * 20/100)
self.backgroundLayer.fillColor = UIColor.clear.cgColor
self.layer.addSublayer(backgroundLayer)
}
private func drawForegroundLayer(){
let startAngle = (-CGFloat.pi/2)
let endAngle = 2 * CGFloat.pi + startAngle
let path = UIBezierPath(arcCenter: pathCenter, radius: self.radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
foregroundLayer.lineCap = CAShapeLayerLineCap.round
foregroundLayer.path = path.cgPath
foregroundLayer.lineWidth = lineWidth
foregroundLayer.fillColor = UIColor.clear.cgColor
foregroundLayer.strokeColor = UIColor.clear.cgColor
foregroundLayer.strokeEnd = 0
self.layer.addSublayer(foregroundLayer)
}
private func makeLabel(withText text: String) -> UILabel {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
label.text = text
label.font = UIFont.systemFont(ofSize: labelSize)
label.sizeToFit()
label.center = pathCenter
return label
}
private func configLabel(){
label.sizeToFit()
label.center = pathCenter
}
private func setForegroundLayerColorForSafePercent(){
let percent = currentProgress
if percent > 0 && percent < 100 {
self.backgroundLayer.strokeColor = UIColor.clear.cgColor
self.label.textColor = .orange
}
else {
self.backgroundLayer.strokeColor = UIColor(red: CGFloat(105/255.0), green: CGFloat(105/255.0), blue: CGFloat(105/255.0), alpha: 0.85).cgColor
}
}
private func setupView() {
makeBar()
self.addSubview(label)
}
//Layout Sublayers
private var layoutDone = false
override func layoutSublayers(of layer: CALayer) {
if !layoutDone {
let tempText = label.text
setupView()
label.text = tempText
layoutDone = true
}
}
}
Here I call the class in ViewController:
class ViewController: UIViewController {
//MARK: IBOutlets
#IBOutlet weak var progressBar: CircularProgressBar!
override func viewDidLoad() {
super.viewDidLoad()
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap)))
}
#objc func handleTap() {
progressBar.labelSize = 60
progressBar.safePercent = 100
progressBar.setProgress(to: 1, withAnimation: true)
}
}
Here is a record with the bug:
Thanks for reading this.

IOS Step menu using swift

I would like to create the stepper menu in IOS using swift, But I'm facing some issues. Here are the issues.
1) Portrait and landscape stepper menu is not propper.
2) How to set default step position with the method below method, It's working when button clicked. But I want to set when menu loads the first time.
self.stepView.setSelectedPosition(index: 2)
3) If it reached the position last, I would like to change the color for complete path parentPathRect.
4) Progress animation CABasicAnimation is not like the progress bar, I want to show the animation.
5) It should not remove the selected position color when changing the orientation.
As per my organization rules should not use third-party frameworks.
Can anyone help me with the solution? Or is there any alternative solution for this?
Here is my code:
import UIKit
class ViewController: UIViewController, StepMenuDelegate {
#IBOutlet weak var stepView: StepView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.stepView.delegate = self;
self.stepView.titles = ["1", "2", "3"]
self.stepView.lineWidth = 8
self.stepView.offSet = 8
self.stepView.setSelectedPosition(index: 2)
}
func didSelectItem(atIndex index: NSInteger) {
print(index)
}
}
protocol StepMenuDelegate {
func didSelectItem(atIndex index: NSInteger)
}
class StepView: UIView {
var delegate : StepMenuDelegate!
var titles: [String] = [] {
didSet(values) {
setup()
setupItems()
}
}
var lineWidth: CGFloat = 8 {
didSet(values) {
setup()
}
}
var offSet: CGFloat = 8 {
didSet(values) {
self.itemOffset = offSet * 4
setup()
}
}
private var selectedIndex : NSInteger!
private var itemOffset : CGFloat = 8 {
didSet (value) {
setup()
setupItems()
}
}
private var path : UIBezierPath!
var selectedLayer : CAShapeLayer!
private var parentPathRect : CGRect!
override func awakeFromNib() {
super.awakeFromNib()
}
override func layoutSubviews() {
self.setup()
setupItems()
}
func setup() {
self.removeAllButtonsAndLayes()
let layer = CAShapeLayer()
self.parentPathRect = CGRect(origin: CGPoint(x: offSet, y: self.bounds.midY - (self.lineWidth/2) ), size: CGSize(width: self.bounds.width - (offSet * 2), height: lineWidth))
path = UIBezierPath(roundedRect: self.parentPathRect, cornerRadius: 2)
layer.path = path.cgPath
layer.fillColor = UIColor.orange.cgColor
layer.lineCap = .butt
layer.shadowColor = UIColor.darkGray.cgColor
layer.shadowOffset = CGSize(width: 1, height: 2)
layer.shadowOpacity = 0.1
layer.shadowRadius = 2
self.layer.addSublayer(layer)
}
func setupItems() {
removeAllButtonsAndLayes()
let itemRect = CGRect(x: self.itemOffset, y: 0, width: 34, height: 34)
let totalWidth = self.bounds.width
let itemWidth = totalWidth / CGFloat(self.titles.count);
for i in 0..<self.titles.count {
let button = UIButton()
var xPos: CGFloat = itemOffset
self.addSubview(button)
xPos += (CGFloat(i) * itemWidth);
xPos += itemOffset/3
button.translatesAutoresizingMaskIntoConstraints = false
button.leftAnchor.constraint(equalTo: self.leftAnchor, constant: xPos).isActive = true
button.centerYAnchor.constraint(equalTo: self.centerYAnchor, constant: 0).isActive = true
button.heightAnchor.constraint(equalToConstant: itemRect.height).isActive = true
button.widthAnchor.constraint(equalToConstant: itemRect.width).isActive = true
button.backgroundColor = UIColor.red
button.layer.zPosition = 1
button.layer.cornerRadius = itemRect.height/2
let name : String = self.titles[i]
button.tag = i
button.setTitle(name, for: .normal)
button.addTarget(self, action: #selector(selectedItemEvent(sender:)), for: .touchUpInside)
if self.selectedIndex != nil {
if button.tag == self.selectedIndex {
selectedItemEvent(sender: button)
}
}
}
}
#objc func selectedItemEvent(sender:UIButton) {
if self.selectedLayer != nil {
selectedLayer.removeFromSuperlayer()
}
self.delegate.didSelectItem(atIndex: sender.tag)
let fromRect = self.parentPathRect.origin
self.selectedLayer = CAShapeLayer()
let rect = CGRect(origin: fromRect, size: CGSize(width:sender.frame.origin.x - 4, height: 8))
let path = UIBezierPath(roundedRect: rect, cornerRadius: 4)
self.selectedLayer.path = path.cgPath
self.selectedLayer.lineCap = .round
self.selectedLayer.fillColor = UIColor.orange.cgColor
let animation = CABasicAnimation(keyPath: "fillColor")
animation.toValue = UIColor.blue.cgColor
animation.duration = 0.2
animation.fillMode = .forwards
animation.isRemovedOnCompletion = false
self.selectedLayer.add(animation, forKey: "fillColor")
self.layer.addSublayer(self.selectedLayer)
}
func removeAllButtonsAndLayes() {
for button in self.subviews {
if button is UIButton {
button.removeFromSuperview()
}
}
}
func setSelectedPosition(index:NSInteger) {
self.selectedIndex = index
}
}
Here I found One way to achieve the solution.!!
https://gist.github.com/DamodarGit/7f0f484708f60c996772ae28e5e1c615
Welcome to suggestions or code changes.!!

UIPanGestureRecognizer on subclass UIView

I've been trying to lean more about subclassing certain objects.
Now I've subclassed a UIView which has a PanGestureRecognizer for swiping left and right.
Can't seem to find the problem. It won't even move the UIView. I've tried looking the lifecycle of an UIView to set the isUserInteractionEnabled to true, but with no result. See the code below:
VC
import UIKit
class SwipeViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
addNewProfile()
}
private func addNewProfile() {
let swipeView = SwiperView(frame: CGRect(x: self.view.bounds.width / 2 - 150, y: self.view.bounds.height / 2 - 75, width: 300, height: 150))
swipeView.parentView = self.view
swipeView.delegate = self
swipeView.shadow = true
swipeView.isUserInteractionEnabled = true
swipeView.backgroundColor = UIColor.white
swipeView.alpha = 0.0
view.addSubview(swipeView)
UIView.animate(withDuration: 0.3, animations: {
swipeView.alpha = 1.0
}, completion: { (succeed) in
swipeView.isUserInteractionEnabled = true
})
}
}
//MARK: - ChosenSwipeResultDelegate
extension SwipeViewController: ChosenSwipeResultDelegate {
func pickedLeftSide() {
}
func pickedRightSide() {
}
}
SwiperView
import UIKit
protocol ChosenSwipeResultDelegate {
func pickedLeftSide()
func pickedRightSide()
}
#IBDesignable class SwiperView: UIView {
private var _shadow: Bool!
private var _parentView: UIView!
var delegate: ChosenSwipeResultDelegate?
var parentView: UIView {
set {
_parentView = newValue
}
get {
return _parentView
}
}
#IBInspectable var shadow: Bool {
get {
return layer.shadowOpacity > 0.0
}
set {
if newValue == true {
addShadow()
}
}
}
#IBInspectable var cornerRadius: CGFloat {
get {
return layer.cornerRadius
}
set {
layer.cornerRadius = newValue
if shadow == false {
layer.masksToBounds = true
}
}
}
override func setNeedsLayout() {
super.setNeedsLayout()
isUserInteractionEnabled = true
}
override func awakeFromNib() {
super.awakeFromNib()
isUserInteractionEnabled = true
let dragGesture = UIPanGestureRecognizer(target: self, action: #selector(SwiperView.dragging(gesture:)))
addGestureRecognizer(dragGesture)
}
func dragging(gesture: UIPanGestureRecognizer) {
let translation = gesture.translation(in: parentView)
let tinderView = gesture.view!
tinderView.center = CGPoint(x: parentView.bounds.width / 2 + translation.x, y: parentView.bounds.height / 2 + translation.y)
let xFromCenter = tinderView.center.x - parentView.bounds.width / 2
let scale = min(100 / abs(xFromCenter), 1)
var rotation = CGAffineTransform(rotationAngle: xFromCenter / 200)
let stretch = rotation.scaledBy(x: scale, y: scale)
tinderView.transform = stretch
if gesture.state == .ended {
if tinderView.center.x < 100 {
print("left")
UIView.animate(withDuration: 0.3, animations: {
tinderView.alpha = 0.0
}, completion: { (succeed) in
self.delegate?.pickedLeftSide()
})
} else if tinderView.center.x > parentView.bounds.width - 100 {
print("right")
UIView.animate(withDuration: 0.3, animations: {
tinderView.alpha = 0.0
}, completion: { (succeed) in
self.delegate?.pickedRightSide()
})
} else {
print("Not chosen")
rotation = CGAffineTransform(rotationAngle: 0)
let stretch = rotation.scaledBy(x: 1, y: 1)
tinderView.transform = stretch
tinderView.center = CGPoint(x: parentView.bounds.width / 2, y: parentView.bounds.height / 2)
}
}
}
private func addShadow(shadowColor: CGColor = UIColor.black.cgColor, shadowOffset: CGSize = CGSize(width: 1.0, height: 2.0), shadowOpacity: Float = 0.4, shadowRadius: CGFloat = 3.0) {
layer.shadowColor = shadowColor
layer.shadowOffset = shadowOffset
layer.shadowOpacity = shadowOpacity
layer.shadowRadius = shadowRadius
}
}
add these code to your SwiperView see if it solves the problem
override init(frame: CGRect) {
super.init(frame: frame)
isUserInteractionEnabled = true
let dragGesture = UIPanGestureRecognizer(target: self, action: #selector(SwiperView.dragging(gesture:)))
addGestureRecognizer(dragGesture)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
isUserInteractionEnabled = true
let dragGesture = UIPanGestureRecognizer(target: self, action: #selector(SwiperView.dragging(gesture:)))
addGestureRecognizer(dragGesture)
}

class is not working correctly after swift 3 conversion [duplicate]

This question already has answers here:
UIColor not working with RGBA values
(6 answers)
Closed 6 years ago.
my class (UIView) is not working after Xcode 8.1's swift 3 conversion i have no idea whats wrong here , this class is a progress view which is looking fine after conversion but my progress is not visible here's my class after the conversion :
class CircularLoaderView: UIView, CAAnimationDelegate {
let circlePathLayer = CAShapeLayer()
let circleRadius: CGFloat = 60.0
let innerCirclePathLayer = CAShapeLayer()
let innerCircleRadius: CGFloat = 60.0
override init(frame: CGRect) {
super.init(frame: frame)
configure()
innerConfigure()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
configure()
innerConfigure()
}
func configure() {
circlePathLayer.frame = bounds
circlePathLayer.lineWidth = 10
circlePathLayer.fillColor = UIColor.clear.cgColor
circlePathLayer.strokeColor = UIColor.darkGray.cgColor
layer.addSublayer(circlePathLayer)
backgroundColor = UIColor.clear
progress = 0
}
func innerConfigure() {
innerCirclePathLayer.frame = bounds
innerCirclePathLayer.lineWidth = 10
innerCirclePathLayer.fillColor = UIColor.clear.cgColor
innerCirclePathLayer.strokeColor = UIColor(red: 100, green: 60, blue: 70, alpha: 0.2).cgColor
layer.addSublayer(innerCirclePathLayer)
backgroundColor = UIColor.clear
}
func innerCircleFrame() -> CGRect {
var circleFrame = CGRect(x: 0, y: 0, width: 2*innerCircleRadius, height: 2*innerCircleRadius)
circleFrame.origin.x = innerCirclePathLayer.bounds.midX - circleFrame.midX
circleFrame.origin.y = innerCirclePathLayer.bounds.midY - circleFrame.midY
return circleFrame
}
func innerCirclePath() -> UIBezierPath {
return UIBezierPath(ovalIn: innerCircleFrame())
}
func circleFrame() -> CGRect {
var circleFrame = CGRect(x: 0, y: 0, width: 2*circleRadius, height: 2*circleRadius)
circleFrame.origin.x = circlePathLayer.bounds.midX - circleFrame.midX
circleFrame.origin.y = circlePathLayer.bounds.midY - circleFrame.midY
return circleFrame
}
func circlePath() -> UIBezierPath {
return UIBezierPath(ovalIn: circleFrame())
}
override func layoutSubviews() {
super.layoutSubviews()
circlePathLayer.frame = bounds
circlePathLayer.path = circlePath().cgPath
innerCirclePathLayer.frame = bounds
innerCirclePathLayer.path = innerCirclePath().cgPath
}
var progress: CGFloat {
get {
return circlePathLayer.strokeEnd
}
set {
if (newValue > 1) {
circlePathLayer.strokeEnd = 1
} else if (newValue < 0) {
circlePathLayer.strokeEnd = 0
} else {
circlePathLayer.strokeEnd = newValue
}
}
}
func reveal() {
// 1
backgroundColor = UIColor.clear
progress = 1
// 2
circlePathLayer.removeAnimation(forKey: "strokeEnd")
// 3
circlePathLayer.removeFromSuperlayer()
superview?.layer.mask = circlePathLayer
// 1
let center = CGPoint(x: bounds.midX, y: bounds.midY)
let finalRadius = sqrt((center.x*center.x) + (center.y*center.y))
let radiusInset = finalRadius - circleRadius
let outerRect = circleFrame().insetBy(dx: -radiusInset, dy: -radiusInset)
let toPath = UIBezierPath(ovalIn: outerRect).cgPath
// 2
let fromPath = circlePathLayer.path
let fromLineWidth = circlePathLayer.lineWidth
// 3
CATransaction.begin()
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
circlePathLayer.lineWidth = 2*finalRadius
circlePathLayer.path = toPath
CATransaction.commit()
// 4
let lineWidthAnimation = CABasicAnimation(keyPath: "lineWidth")
lineWidthAnimation.fromValue = fromLineWidth
lineWidthAnimation.toValue = 2*finalRadius
let pathAnimation = CABasicAnimation(keyPath: "path")
pathAnimation.fromValue = fromPath
pathAnimation.toValue = toPath
// 5
let groupAnimation = CAAnimationGroup()
groupAnimation.duration = 1
groupAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
groupAnimation.animations = [pathAnimation, lineWidthAnimation]
groupAnimation.delegate = self
circlePathLayer.add(groupAnimation, forKey: "strokeWidth")
}
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
superview?.layer.mask = nil
}
}
this is how i'm setting the progress :
cell.loaderView?.progress = CGFloat(receivedSize)/CGFloat(expectedSize)
still its not showing any progress , anyone have any clue whats wrong here then let me know
You haven't specify what exactly not working, but when I test your code it showing progress the only thing is not working was it is not showing me the innerCirclePathLayer because you have not divide your RGB color with 255 because init(red:green:blue:alpha:) accept values between 0.0 to 1.0 and values above 1.0 are interpreted as 1.0. So try once dividing RGB to 255.
innerCirclePathLayer.strokeColor = UIColor(red: 100/255.0, green: 60/255.0, blue: 70/255.0, alpha: 0.2).cgColor

Resources