iOS:热点指示器抛出的视图定位

iOS: Positioning of view thrown off by hotspot indicator

当我们遇到错误时,我们在 table 视图上显示一个带有标签的矩形:

使用此代码:

    // Fix location of message bar even as user scrolls table - per 
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let newY = self.tableView.contentOffset.y + self.navigationController!.navigationBar.frame.size.height + UIApplication.shared.statusBarFrame.height 
    // Show rectangle using 0 and newY ... 

它运行良好但在某些情况下不起作用,例如启用个人热点时。导航栏和状态矩形之间有一个空隙:

始终将某些内容置于导航栏下方的正确方法是什么?

在第一种情况下,状态栏高度为 20,但在第二种情况下为 40。在这两种情况下,导航栏和内容偏移量都相同。即:

状态栏中的高度变化似乎并没有增加偏移量。

更新:查看(我的)接受的答案。我确定有更好的方法.. 如果您知道,请添加到线程中。

不要使用从框架派生的值来定位您的消息,而是使用自动版式来定位它。

有几种方法可以实现这一点 - 一种方法如下:

//... assuming this is being called from the parent view controller

    //safely unwrap the reference to the navigation controller
    guard let navController = self.navigationController else { return }
    let message = UIView()

    //arbitrary styles for example only
    message.backgroundColor = UIColor.blue
    //set translatesAutoresizingMaskIntoConstraints so constraints will work
    message.translatesAutoresizingMaskIntoConstraints = false

    //create constraints
    let height = NSLayoutConstraint(item: message, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: 50)
    let equalWidth = NSLayoutConstraint(item: message, attribute: NSLayoutAttribute.width, relatedBy: .equal, toItem: navController.navigationBar, attribute: .width, multiplier: 1.0, constant: 0)
    let alignBottom = NSLayoutConstraint(item: message, attribute: .top, relatedBy: .equal, toItem: navController.navigationBar, attribute: .bottom, multiplier: 1, constant: 0)
    //apply constraints
    message.addConstraint(height)
    navController.view.addSubview(message)
    navController.view.addConstraints([equalWidth, alignBottom])

这也可以使用 VFL 来完成 - 但它的冗长在这里可能有点矫枉过正。

否则,您可以使用很棒的库,使它更具声明性并减少样板 - 例如 SnapKit

我的 "poor man's solution" 是硬编码 20 作为状态栏高度:

 var newY = self.tableView.contentOffset.y
 newY += self.navigationController!.navigationBar.frame.size.height
 newY += 20

必须是更好的方法...但这似乎有效。

property view.frame能够捕捉到这样的变化。因此,对任何位置使用 view.frame.height 都可以防止重新定位。

它在有和没有热点栏的情况下找到合适的视图高度的方式:

//with hotspot bar
print (view.frame.height) //540.0   
//without hotspot bar   
print (view.frame.height) //560.0

//setting a navigation bar at top using height of view frame
let navigationBar : UINavigationBar = UINavigationBar(frame: CGRect(x: 0, y: 0, width:view.frame.width, height: view.frame.height/10))
    navigationBar.backgroundColor =  .gray
navigationBar.setItems([UINavigationItem(title: "navigaion bar")], animated: true)    

let statusbar = UITableView()
//placing the status bar below the navigation bar 
statusbar.frame = CGRect(x: 0, y: navigationBar.frame.size.height, width:view.frame.width, height: view.frame.height/10) //any choice for height:
view.addSubview(statusbar)
view.addSubview(navigationBar)