简体   繁体   English

如何解决视图居中之谜?

[英]How to Fix View Centering Mystery?

I have a UIStackView, which holds an image view and a text view. 我有一个UIStackView,其中包含一个图像视图和一个文本视图。 The image view has an activity indicator view as a subview (I add this programmatically). 图像视图具有活动指示器视图作为子视图(我以编程方式添加了此视图)。 When the view initially view loads, I center the activity indicator view within the image view and starting the animation for the AIV. 当视图初始视图加载时,我将活动指示器视图置于图像视图的中心,并启动AIV的动画。 But, in the process of waiting for the image to load, if I rotate the image view, the AIV needs to be re-centered. 但是,在等待图像加载的过程中,如果旋转图像视图,则需要将AIV重新居中。 I added code to listen for the status bar orientation change notification, and have a method to invoke upon the notification (UIApplicationDidChangeStatusBarOrientationNotification). 我添加了代码来侦听状态栏方向更改通知,并具有一种在通知时调用的方法(UIApplicationDidChangeStatusBarOrientationNotification)。 In that method, I attempt to get the bounds of the image view and use that to re-center the AIV within the image view. 在这种方法中,我尝试获取图像视图的边界,并使用它在图像视图内重新定位AIV。 But, it seems that the value of the bounds of the image view is not changing when the device orientation changes. 但是,当设备方向改变时,图像视图边界的值似乎没有改变。 Is there a “reliable" way to get the updated bounds for a view after the device orientation has changed? Code -> 设备方向更改后,是否有“可靠”的方法来获取视图的更新边界?

// start listening for orientation changes
NSNotificationCenter.defaultCenter().addObserver(self, selector: "orientationDidChange:",
           name: UIApplicationDidChangeStatusBarOrientationNotification, object: nil)

Then I have: 然后我有:

func orientationDidChange(notification: NSNotification) {

   // get image view bounds
   let viewBounds = _imageView.bounds

   // recenter the activity indicator
   _activityIndicator.center = CGPointMake(CGRectGetMidX(viewBounds), CGRectGetMidY(viewBounds))
}

Update: 更新:

So I got rid of the above and tried this: 所以我摆脱了上面的尝试:

// setup activity indicator
_activityIndicatorView.translatesAutoresizingMaskIntoConstraints = true

        _imageView.addSubview(_activityIndicatorView)

        // set constraints
        let centerXConstraint = NSLayoutConstraint(item: _activityIndicatorView, attribute: .CenterX,
            relatedBy: .Equal, toItem: _imageView,
            attribute: .CenterX, multiplier: 1.0,
            constant: 0.0)
        _activityIndicatorView.addConstraint(centerXConstraint)

        let centerYConstraint = NSLayoutConstraint(item: _activityIndicatorView, attribute: .CenterY,
            relatedBy: .Equal, toItem: _imageView,
            attribute: .CenterY, multiplier: 1.0,
            constant: 0.0)
        _activityIndicatorView.addConstraint(centerYConstraint)

which is in my view did load method. 在我看来这是加载方法。 The console spits out this: 控制台吐出这个:

2015-10-27 19:26:09.303 Historic Sites Navigator[373:93902] The view hierarchy is not prepared for the constraint: When added to a view, the constraint's items must be descendants of that view (or the view itself). 2015-10-27 19:26:09.303 Historic Sites Navigator [373:93902]没有为约束准备视图层次结构:添加到视图时,约束的项目必须是该视图的后代(或视图本身)。 This will crash if the constraint needs to be resolved before the view hierarchy is assembled. 如果在组装视图层次结构之前需要解决约束,则会崩溃。 Break on -[UIView(UIConstraintBasedLayout) _viewHierarchyUnpreparedForConstraint:] to debug. 中断-[UIView(UIConstraintBasedLayout)_viewHierarchyUnpreparedForConstraint:]进行调试。 2015-10-27 19:26:09.308 Historic Sites Navigator[373:93902] View hierarchy unprepared for constraint. 2015-10-27 19:26:09.308古迹导航器[373:93902]视图层次结构未准备好进行约束。 Constraint: Container hierarchy: > | 约束:容器层次结构:> | > View not found in container hierarchy: > That view's superview: > 2015-10-27 19:26:09.310 Historic Sites Navigator[373:93902] * Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to install constraint on view. >在容器层次结构中找不到视图:>该视图的超级视图:> 2015-10-27 19:26:09.310历史景点导航器[373:93902] *由于未捕获的异常'NSGenericException'而终止应用程序,原因:'无法安装约束在视图上。 Does the constraint reference something from outside the subtree of the view? 约束是否引用了视图子树之外的内容? That's illegal. 那是非法的。 constraint: view:>' * First throw call stack: (0x2643767b 0x377b2e17 0x264375c1 0x27177983 0x2a628f85 0x2a628dd5 0x2a628cef 0x2ad33971 0x2a628bd7 0xdf6c4 0xdfe34 0x2a5271c7 0x2a526dad 0x2ad8ca09 0x2a8689ad 0x2a88c095 0x2a88e6c5 0x2a88e931 0x2a61e989 0x2a891bb7 0x2ab33085 0x2ac09b39 0x2ac09967 0x2a883d95 0xccac8 0xccc10 0x2a659487 0x2a71440b 0x2a7cc0b9 0x2a7d79eb 0x2a519ecd 0x263fa4c9 0x263f87cd 0x263f8bff 0x2634c119 0x2634bf05 0x2f502ac9 0x2a58ef15 0xd6e74 0x37f21873) libc++abi.dylib: terminating with uncaught exception of type NSException 约束:视图:>” *第一掷调用堆栈:(0x2643767b 0x377b2e17 0x264375c1 0x27177983 0x2a628f85 0x2a628dd5 0x2a628cef 0x2ad33971 0x2a628bd7 0xdf6c4 0xdfe34 0x2a5271c7 0x2a526dad 0x2ad8ca09 0x2a8689ad 0x2a88c095 0x2a88e6c5 0x2a88e931 0x2a61e98​​9 0x2a891bb7 0x2ab33085 0x2ac09b39 0x2ac09967 0x2a883d95 0xccac8 0xccc10 0x2a659487 0x2a71440b 0x2a7cc0b9 0x2a7d79eb 0x2a519ecd 0x263fa4c9 0x263f87cd 0x263f8bff 0x2634c119 0x2634bf05 0x2f502ac9 0x2a58ef15 0xd6e74 0x37f21873)libc ++ abi.dylib:以类型为NSException的未捕获异常终止

For iOS 8 and 9 the following function is called on size change of the view (which is eg at interface rotation): 对于iOS 8和9,在视图尺寸更改时(例如在界面旋转时)调用以下函数:

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)

    coordinator.animateAlongsideTransition({ (coordinator) -> Void in
        // here the new size is already set, so place your code here
    }, completion: nil)
}

Apart from this you could use constraints (auto layout) for positioning of the UIActivityIndicatorView. 除此之外,您可以使用约束(自动布局)来定位UIActivityIndi​​catorView。

You current autolayout errors are because you have to: 您当前的自动布局错误是因为您必须:

  • set translatesAutoresizingMaskIntoConstraints to false 设置translatesAutoresizingMaskIntoConstraints为false
  • add the constraints to the image view, not to the ai-view 将约束添加到图像视图,而不是AI视图

After watching the Autolayout videos from WWDC 2015 I was able to write the correct and working code: 观看WWDC 2015的自动版式视频后,我能够编写正确且有效的代码:

_activityIndicatorView.translatesAutoresizingMaskIntoConstraints = false

_imageView.addSubview(_activityIndicatorView)

NSLayoutConstraint(item: _activityIndicatorView, attribute: .CenterX,
            relatedBy: .Equal, toItem: _imageView,
            attribute: .CenterX, multiplier: 1.0,
            constant: 0.0).active = true

NSLayoutConstraint(item: _activityIndicatorView, attribute: .CenterY,
            relatedBy: .Equal, toItem: _imageView,
            attribute: .CenterY, multiplier: 1.0,
            constant: 0.0).active = true

@13:48 of this video was the key: https://developer.apple.com/videos/play/wwdc2015-219/ 该视频的@ 13:48是关键: https//developer.apple.com/videos/play/wwdc2015-219/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM