使用导航栏注意事项获取屏幕中心

Get the center of screen with Navigation Bar considerations

我正在尝试将 UIActivityIndi​​cator 居中并在我的应用程序中重复使用它。我面临一个问题,我的某些视图必须位于导航栏下方,而另一些则不是。这恰好使我的 activity 指示器在视图不在导航栏下方的视图上显示低于中心。例如:

Whosebug 上的所有答案似乎都属于图片 #2。

我只是对 UIView 进行了扩展,通过将 activity 指示器添加为子视图覆盖来显示和隐藏它。检查 Whosebug 上的多个帖子,我没有发现任何可以重复这个问题的内容。

我的问题是,在生产应用程序中,如何在仅使用一个功能的情况下成功地将此视图居中,但仍支持 IOS 版本回到 9.3

你可以得到屏幕高度+顶部和底部

 var height: CGFloat {
        let heightTop = UIApplication.shared.statusBarFrame.height + (
            (self.navigationController?.navigationBar.intrinsicContentSize.height) ?? 0)
        let heightBottom  = self.tabBarController?.tabBar.frame.height ?? 0
        return  UIScreen.main.bounds.height + (heightTop+heightBottom)
    }

// 然后

indicator.center = CGPoint(x: self.view.frame.width/2.0, y: height/2.0 )

你可以使用safeAreaLayoutGuide它给你可见屏幕的区域

   let indicator: UIActivityIndicatorView = {
        let indicator =  UIActivityIndicatorView(activityIndicatorStyle: .gray)
        indicator.translatesAutoresizingMaskIntoConstraints = false
        return indicator
    }()

        self.view.addSubview(indicator)


    let safeAreaGuide = self.view.safeAreaLayoutGuide

    NSLayoutConstraint.activate([
        indicator.centerXAnchor.constraint(equalTo: saveAreaGuide.centerXAnchor),
        indicator.centerYAnchor.constraint(equalTo: saveAreaGuide.centerYAnchor)
        ])

你可以使用这个:

func setActivityIndicatorTo(view: UIView, indicator: UIActivityIndicatorView){

    indicator.setTranslatesAutoresizingMaskIntoConstraints(false)
    view.addConstraint(NSLayoutConstraint(item: indicator, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0))
    view.addConstraint(NSLayoutConstraint(item: indicator, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0))    

}

Or you can found center of screen below:

let w = UIScreen.main.bounds.width
let h = UIScreen.main.bounds.height
activity.center = CGPoint(x: w / 2, y: h / 2)

SWIFT 3:

Extension 将子视图置于您 App delegate 的 keyWindow 中...使其居中,无论它在您的应用程序中的什么位置:

extension UIView {

    public func addSubviewScreenCenter() {
        if let keyWindow = UIApplication.shared.keyWindow {
            keyWindow.addSubview(self)
            self.center()
        }
    }

    public func removeFromWindowView() {
        if self.superview != nil {
            self.removeFromSuperview()
        }
    }
}

UIView 上有在不同视图坐标系之间转换点和框架的方法(iOS 2.0+、https://developer.apple.com/documentation/uikit/uiview/1622424-convert 支持)。

extension UIView {

    func centerInContainingWindow() {
        guard let window = self.window else { return }

        let windowCenter = CGPoint(x: window.frame.midX, y: window.frame.midY)
        self.center = self.superview.convert(windowCenter, from: nil)
    }

}

A UIView 指定其相对于其父视图的坐标,因此 centerInContainingWindow() 使用 UIView.convert(_:from:) 获取相对于其父视图坐标的 window 的中心。

  • 图#1,导航栏下视图:视图占满整个window,所以转换前后中心点相同
  • 图#2,视图不在导航栏下:视图只填充了window的一部分,因此转换后window中心将移动到屏幕上的同一位置。