3

I have requirement to develop below UI screen ios using Swift.

enter image description here Requirement Screen

In above two circles each segment movement is allowed either to push or pull to other circle. enter image description here

I have written below code to achieve it

    import UIKit

    class ArcView: UIView {

        let lineWidth: CGFloat = 40
        var path: UIBezierPath!
        var startAngle:CGFloat?
        var endAngle:CGFloat?
        var radius:CGFloat?
        var strokeColor:UIColor?
        var arcCenter:CGPoint?
        var tapPoint:CGPoint?
        var destPoint:CGPoint?
        var initialCenter:CGPoint?

        override init(frame: CGRect) {
            super.init(frame: frame)
        }
        func setProps(startAngle:CGFloat,endAngle:CGFloat,center:CGPoint, radius:CGFloat,color:UIColor) {
            self.radius=radius
            self.startAngle=startAngle
            self.endAngle=endAngle
            self.strokeColor=color
            self.arcCenter=center
            self.backgroundColor = UIColor.clearColor()
            initGestureRecognizers()
            self.initialCenter=self.center
        }

        func initGestureRecognizers() {
            let panGR = UIPanGestureRecognizer(target: self, action: "didPan:")
            addGestureRecognizer(panGR)
        }

        override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
            let touch = touches.first
            tapPoint = touch!.locationInView(self)
        }

        override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
            let touch = touches.reverse().first
            destPoint = touch!.locationInView(self)
        }

        override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
            let touch = touches.reverse().first
            destPoint = touch!.locationInView(self)
        }


        func didPan(panGR: UIPanGestureRecognizer) {
            self.superview!.bringSubviewToFront(self)

            var translation = panGR.translationInView(self)

            translation = CGPointApplyAffineTransform(translation, self.transform)

            updateLocation(translation)
            panGR.setTranslation(CGPointZero, inView: self)

    //        self.superview!.sendSubviewToBack(self)
        }

        func isMoveAllowed() -> Bool {
            if(arcCenter?.distanceFrom(tapPoint!)<=((arcCenter?.distanceFrom(destPoint!))!+(destPoint?.distanceFrom(tapPoint!))!)) {
                return true
            }
            return false
        }

        func updateLocation(location:CGPoint) {
            if isMoveAllowed() {
                self.center.x += location.x
                self.center.y += location.y
            }
        }

        override func drawRect(rect: CGRect) {
            self.path = UIBezierPath(arcCenter: arcCenter!, radius: radius!, startAngle: startAngle!, endAngle:endAngle!, clockwise: true)
            let circleLayer :CAShapeLayer = CAShapeLayer()
            circleLayer.path = self.path.CGPath
            circleLayer.lineWidth = 40
            circleLayer.strokeColor = strokeColor!.CGColor
            circleLayer.fillColor = UIColor.clearColor().CGColor
            self.layer.addSublayer(circleLayer)
            self.path.fill()
            self.path.stroke()
        }
    }

    extension CGPoint {
        func distanceFrom(p:CGPoint) -> CGFloat {
            return sqrt(pow((p.x - self.x),2) + pow((p.y - self.y),2))
        }
    }

And View Controller code is

    import UIKit

    class ViewController: UIViewController {

        override func viewDidLoad() {
            super.viewDidLoad()

        let center:CGPoint = CGPoint(x: 215,y: 325)
            let innerRadius:CGFloat = CGFloat(55)
            let outerRadius:CGFloat = CGFloat(98)

            let innerCirclePath = UIBezierPath(arcCenter: center, radius: innerRadius, startAngle: CGFloat(M_PI * 1.5), endAngle:CGFloat(M_PI * 3.5), clockwise: true)

            let outerCirclePath = UIBezierPath(arcCenter: center, radius: outerRadius, startAngle: CGFloat(M_PI * 1.5), endAngle:CGFloat(M_PI * 3.5), clockwise: true)

            addBlankColorLayer(0,endHour: totalHours,eachMinute:eachMinute,innerCirclePath: innerCirclePath,blankColor: UIColor.grayColor())

            addBlankColorLayer(0,endHour: totalHours,eachMinute:eachMinute,innerCirclePath: outerCirclePath,blankColor: UIColor.grayColor())

            var eventTimes:[(CGFloat,CGFloat)] = [(0,1),(1.5,2),(2.5,3.0)]

            for times in eventTimes {
            let arc:ArcView=ArcView(frame:self.view.frame)
                arc.setProps(times.0,endAngle:times.1,center:center, radius:outerRadius,color:UIColor.redColor())
                self.view.addSubview(arc)
            }
            // Do any additional setup after loading the view, typically from a nib.
        }
        func addBlankColorLayer(startHour:CGFloat,endHour:CGFloat,eachMinute:CGFloat,innerCirclePath:UIBezierPath,blankColor:UIColor) {
            let circleLayer :CAShapeLayer = CAShapeLayer()
            circleLayer.path = innerCirclePath.CGPath
            circleLayer.strokeStart = eachMinute*startHour*60;
            circleLayer.strokeEnd = eachMinute * 60 * (endHour)
            circleLayer.lineWidth = 40
            circleLayer.strokeColor = blankColor.CGColor
            circleLayer.fillColor = UIColor.clearColor().CGColor
            view.layer.addSublayer(circleLayer)

        }
    }

I am able to achieve this

Result image

In this I am able to achieve Pan gesture moment also like below Allowed

But now I have multiple problems.

  • Unable to select Each layer/segment/view independently. What I approach I should follow to achieve it?
  • How to restrict Each layer/segment/view moment towards center only? Below is wrong moment image

Not allowed

Any help is appreciated.

Koneti
  • 106
  • 4

0 Answers0