Ios 设备定向后的子视图中心

Ios 设备定向后的子视图中心,ios,swift,uiview,uiviewcontroller,autolayout,Ios,Swift,Uiview,Uiviewcontroller,Autolayout,我在这里发布了一个类似的问题 我正在设计一个应用程序,其中包含一个ViewController和主视图的子视图。此子视图是一个地图。最初,它的中心等于主视图的中心(并且等于设备的中心)。此子视图的位置可以使用手势更改,因此它没有任何布局约束。当设备的方向发生更改时,默认行为是子视图的中心以其与设备左上角的水平和垂直距离保持不变的方式移动。我正试图改变这一点,以便保持不变的距离是子视图中心和主视图中心之间的水平和垂直距离(在定向后,该距离仍然等于设备的中心)。我尝试了以下方法: 第一种方法(它适用

我在这里发布了一个类似的问题

我正在设计一个应用程序,其中包含一个ViewController和主视图的子视图。此子视图是一个地图。最初,它的中心等于主视图的中心(并且等于设备的中心)。此子视图的位置可以使用手势更改,因此它没有任何布局约束。当设备的方向发生更改时,默认行为是子视图的中心以其与设备左上角的水平和垂直距离保持不变的方式移动。我正试图改变这一点,以便保持不变的距离是子视图中心和主视图中心之间的水平和垂直距离(在定向后,该距离仍然等于设备的中心)。我尝试了以下方法:

第一种方法(它适用于iphone,但不适用于ipad,因为它有针对垂直和水平方向的常规特征集合。)

第二个问题(它适用于iphone和ipad,但在设备从左向右快速旋转的情况下,即没有首先从protrait经过时,它会失败。它也不能顺利运行)

有什么办法可以实现吗?我觉得很奇怪,在应用程序中添加如此简单的功能如此困难

这里是一些截图。黑点是主视图的中心。当设备旋转到横向时,应该像屏幕截图3中那样,在旋转到横向后,子视图中心和主视图中心之间的距离保持不变。默认设置类似于屏幕截图2,其中子视图的中心与主视图左上角之间的距离在旋转到横向后保持不变


要定位子视图,请尝试使用
viewWillLayoutSubviews
viewdillayoutsubviews
,例如:

重写func viewdilayoutsubviews(){
super.viewDidLayoutSubviews()
view.subview[0].center.x+=view.center.y-view.center.x
view.subview[0].center.y+=view.center.x-view.center.y
}

下面是一个使用约束并让自动布局在设备旋转时处理定位的基本示例

它在视图的中心创建了一个小的、圆形的蓝色“点”,并创建了一个100x100的红色方形视图来拖动-它是半透明的,因此我们可以通过它看到点

viewdideappease()
中,我们将红色“dragView”的左上角设置为视图的中心(如果蓝色“dotView”,则设置为中心):

发射时:

将红色视图向上向左拖动一点:

旋转设备:


您不使用自动布局/约束是有原因的吗?更改大小/特征不需要计算或代码。@DonMag我尝试了以下方法,但效果不好:让边距=视图。布局边距向导视图。子视图[0]。centerYAnchor。约束(等于:边距。centerYAnchor).isActive=true视图。子视图[0]。leadingAnchor.constraint(等式:边距。leadingAnchor).isActive=True此外,我不确定对用户使用手势移动的子视图施加约束是否正确。有点令人困惑…设备是纵向的,从中心100x100视图开始。用户将视图拖动到右下角。用户旋转设备。视图应该在哪里?vie底部下方w(即屏幕外)?以及…您如何移动视图?使用约束并更新其
。常量
值来移动它们并不少见,保留了自动布局的所有优点。IURI感谢您的asnwerDonMag感谢您的回答。它工作得非常好。您帮了我很多,我很感激。
var distanceOfCenters: CGPoint?
override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator)
{
    super.willTransition(to: newCollection, with: coordinator)
    distanceOfCenters = CGPoint(x: view.subviews[0].center.x-view.center.x, y: view.subviews[0].center.y-view.center.y)
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)
{
    super.traitCollectionDidChange(previousTraitCollection)
    if let x = distanceOfCenters?.x, let y = distanceOfCenters?.y
    {
        view.subviews[0].center = CGPoint(x: view.center.x+x, y: view.center.y+y)
    }
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
{
    super.viewWillTransition(to: size, with: coordinator)
    view.subviews[0].center.x += view.center.y - view.center.x
    view.subviews[0].center.y += view.center.x - view.center.y
}
class DragTestViewController: UIViewController {
    
    let dotView: UIView = {
        let v = UIView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.backgroundColor = .systemBlue
        return v
    }()
    
    let dragView: UIView = {
        let v = UIView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.backgroundColor = UIColor.systemRed.withAlphaComponent(0.75)
        return v
    }()
    
    // drag view's center constraints - created in viewDidLoad()
    var centerX: NSLayoutConstraint!
    var centerY: NSLayoutConstraint!

    // these are used by the pan gesture handler
    var currentCenterX: CGFloat = 0
    var currentCenterY: CGFloat = 0

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(dotView)
        view.addSubview(dragView)
        
        // respect safe area
        let g = view.safeAreaLayoutGuide
        
        // create centerX and centerY constraints for dragView
        centerX = dragView.centerXAnchor.constraint(equalTo: g.centerXAnchor)
        centerY = dragView.centerYAnchor.constraint(equalTo: g.centerYAnchor)
        
        NSLayoutConstraint.activate([
            
            // put 8x8 dotView in center
            dotView.widthAnchor.constraint(equalToConstant: 8.0),
            dotView.heightAnchor.constraint(equalTo: dotView.widthAnchor),
            dotView.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            dotView.centerYAnchor.constraint(equalTo: g.centerYAnchor),
            
            // dragView width & height 100x100
            dragView.widthAnchor.constraint(equalToConstant: 100.0),
            dragView.heightAnchor.constraint(equalTo: dragView.widthAnchor),
            
            // activate dragView's center anchors
            centerX,
            centerY
        ])
        
        let pan = UIPanGestureRecognizer(target: self, action: #selector(self.panGestureHandler(_:)))
        dragView.addGestureRecognizer(pan)

    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        // make dotView round
        dotView.layer.cornerRadius = dotView.bounds.width * 0.5
        
        // start with dragView's top-left corner at center of view
        centerX.constant = dragView.bounds.midX
        centerY.constant = dragView.bounds.midY
    }

    @objc func panGestureHandler(_ recognizer: UIPanGestureRecognizer){
        
        switch recognizer.state {
        case .began:
            // save the current center x and y constant value
            currentCenterX = centerX.constant
            currentCenterY = centerY.constant
            break
            
        case .changed:
            // update dragView's center x & y, based on pan motion
            let translation = recognizer.translation(in: self.view)
            centerX.constant = currentCenterX + translation.x
            centerY.constant = currentCenterY + translation.y
            break
            
        case .ended, .cancelled:
            // if you want to do something when pan ends
            break
            
        default:
            break
        }
        
    }

}