You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在移动旋转后的UIViewB时,保持UIViewC在UIViewA中的原位置?

解决UIView变换后子视图回归原坐标系位置的问题

在iOS开发中,视图层级为UIViewA → UIViewB → UIViewC,记录UIViewC在UIViewA坐标系的初始位置后,对UIViewB执行旋转和平移操作,需要让UIViewC回到UIViewA中的原位置,但直接调整UIViewC的Y位置会因UIViewB的transform导致结果异常。

核心问题是UIView应用transform后,其内部坐标系会发生旋转、缩放等变换,直接修改子视图的frame会基于变换后的坐标系计算,导致位置偏差。正确的做法是利用UIKit的坐标转换方法,自动处理变换带来的坐标系变化。

具体实现步骤

  1. 保留已记录的UIViewC在UIViewA中的初始位置 initialCPositionInA
  2. 将该初始位置从UIViewA的坐标系转换到当前状态(已旋转平移)的UIViewB坐标系中
  3. 设置UIViewC的origin为转换后的坐标

修改后的完整代码

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) // 可替换为任意旋转角度

        // 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)
        
        // --- 核心修正代码 ---
        // 将ViewA中的初始位置转换到当前ViewB的坐标系中
        let targetPositionInB = viewB.convert(initialCPositionInA, from: viewA)
        // 设置ViewC的origin为目标位置
        viewC.frame.origin = targetPositionInB
    }
}

原理说明

UIView的convert(_:from:)方法会自动处理以下因素:

  • 视图层级的父子关系
  • 父视图(ViewB)的所有transform(旋转、缩放、平移)
  • 视图的bounds和frame变化

因此无论ViewB设置了何种旋转角度或平移距离,转换后的坐标都能准确对应到ViewB当前坐标系中的位置,确保ViewC回到UIViewA中的初始位置。

内容的提问来源于stack exchange,提问作者WCK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 12:05:58