iosswiftuiviewframe

How to maintain the UIView C position same in UIView A?


What I want is to move UIViewB and maintain all the views position like nothing happened. I want viewC back to the original place before viewB is moved how ? This must apply to all angles regardless how viewB rotate. How can I do that ?

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Create UIViewA
        let viewA = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
        viewA.backgroundColor = .red
        self.view.addSubview(viewA)

        // Create UIViewB
        let viewB = UIView(frame: CGRect(x: 150, y: 150, width: 200, height: 200))
        viewB.backgroundColor = .green
        viewA.addSubview(viewB)

        // Create UIViewC
        let viewC = UIView(frame: CGRect(x: 50, y: 50, width: 100, height: 100))
        viewC.backgroundColor = .blue
        viewB.addSubview(viewC)

        // Initial position of viewC in viewA's coordinate system
        let initialCPositionInA = viewC.convert(viewC.bounds.origin, to: viewA)
        
        // Rotate viewB by 45 degrees
        viewB.transform = CGAffineTransform(rotationAngle: .pi / 4.5) // 45 degrees

        // Calculate the movement delta of viewB
        let movementDelta = CGPoint(x: 0, y: -50)

        // Move viewB up by -50 pixels
        viewB.center = CGPoint(x: viewB.center.x, y: viewB.center.y + movementDelta.y)
        
        // I want viewC back to the original place before viewB is moved how ? This must apply to all angles regardless how viewB rotate
    }
}

I have tried many different solutions, by moving the y position of the UIViewC but it is returning weird results as there are transform applied to the UIViewB which also applied to UIViewC.


Solution

  • You should work in the coordinate system of view A (or any coordinate system that is fixed).

    Before view B moves, get the centre of view C (as a coordinate in view A). Keep in mind that center is a coordinate in the parent's coordinate system.

    let oldCenter = viewB.convert(viewC.center, to: viewA)
    

    Then after moving view B, set the centre of view C back to oldCenter:

    viewC.center = viewB.convert(oldCenter, from: viewA)