Swift:使嵌入导航控制器的UITableViewController的背景图像填充整个屏幕

Swift:使嵌入导航控制器的UITableViewController的背景图像填充整个屏幕,swift,background-image,fullscreen,Swift,Background Image,Fullscreen,我设法在UITableViewController中创建了半透明和圆形的UITableViewCells,该UITableViewController嵌入在导航控制器中,代码行位于viewDidLoad() 但是我想让背景图像填满整个手机屏幕。我将代码(仅此代码行)更改为: 现在背景图像占据了整个手机屏幕,但我的桌子甚至iPhone的时间和电池指示图标都不见了 我想要的是背景图像填满整个屏幕,但tableView、它的电池、iPhone时间、电池电量图标等保持显示。navigationCon

我设法在UITableViewController中创建了半透明和圆形的UITableViewCells,该UITableViewController嵌入在导航控制器中,代码行位于viewDidLoad()

但是我想让背景图像填满整个手机屏幕。我将代码(仅此代码行)更改为:

现在背景图像占据了整个手机屏幕,但我的桌子甚至iPhone的时间和电池指示图标都不见了


我想要的是背景图像填满整个屏幕,但tableView、它的电池、iPhone时间、电池电量图标等保持显示。

navigationController?.setNavigationBarHidden(true,动画:true)

以下是我使用Swift 5,XCode 12所做的工作。

步骤1(可选)-创建自定义UINavigationController类

class CustomNavigationController: UINavigationController {
  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    navigationBar.isTranslucent = true
}
class CustomViewController: UIViewController {
  // your background view
  let bgImageView: UIImageView = {
    let bgImageView = UIImageView()
    bgImageView.image = UIImage(named: "gradient_background")
    bgImageView.contentMode = .scaleAspectFill
    return bgImageView
}()

  // Get the height of the nav bar and the status bar so you
  // know how far up your background needs to go
  var topBarHeight: CGFloat {
    var top = self.navigationController?.navigationBar.frame.height ?? 0.0
    if #available(iOS 13.0, *) {
      top += UIApplication.shared.windows.first?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
    } else {
      top += UIApplication.shared.statusBarFrame.height
    }
    return top
  }

  var isLayoutConfigured = false

  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    title = "Site Visit"

    // you only want to do this once
    if !isLayoutConfigured() {
      isLayoutConfigured = true
      configBackground()
    }
  }

  private func configBackground() {
    view.addSubview(bgImageView)
    configureBackgroundConstraints()
  }
  
  // Set up your constraints, main one here is the top constraint
  private func configureBackgroundConstraints() {
    bgImageView.translatesAutoresizingMaskIntoConstraints = false
    bgImageView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor,
                                     constant: -topBarHeight).isActive = true
    bgImageView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor,
                                         constant: 0).isActive = true
    bgImageView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor,
                                        constant: 0).isActive = true
    bgImageView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor,
                                          constant: 0).isActive = true
    
    view.layoutIfNeeded()
}
用此UINavigationController子类替换UINavigationController。我将其标记为可选,因为这是基于首选项的,如果您不设置此选项,您的导航栏将是不透明的,并且您无法看到它下面的内容

设置
navigationBar.isTranslucent=true
可以让您看到它下面的背景,这正是我喜欢的。子类也是可选的,但您可能需要对导航栏进行其他更新,所以我总是喜欢将其作为子类

步骤2-设置背景视图约束

class CustomNavigationController: UINavigationController {
  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    navigationBar.isTranslucent = true
}
class CustomViewController: UIViewController {
  // your background view
  let bgImageView: UIImageView = {
    let bgImageView = UIImageView()
    bgImageView.image = UIImage(named: "gradient_background")
    bgImageView.contentMode = .scaleAspectFill
    return bgImageView
}()

  // Get the height of the nav bar and the status bar so you
  // know how far up your background needs to go
  var topBarHeight: CGFloat {
    var top = self.navigationController?.navigationBar.frame.height ?? 0.0
    if #available(iOS 13.0, *) {
      top += UIApplication.shared.windows.first?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
    } else {
      top += UIApplication.shared.statusBarFrame.height
    }
    return top
  }

  var isLayoutConfigured = false

  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    title = "Site Visit"

    // you only want to do this once
    if !isLayoutConfigured() {
      isLayoutConfigured = true
      configBackground()
    }
  }

  private func configBackground() {
    view.addSubview(bgImageView)
    configureBackgroundConstraints()
  }
  
  // Set up your constraints, main one here is the top constraint
  private func configureBackgroundConstraints() {
    bgImageView.translatesAutoresizingMaskIntoConstraints = false
    bgImageView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor,
                                     constant: -topBarHeight).isActive = true
    bgImageView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor,
                                         constant: 0).isActive = true
    bgImageView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor,
                                        constant: 0).isActive = true
    bgImageView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor,
                                          constant: 0).isActive = true
    
    view.layoutIfNeeded()
}
在设置约束之前:

设置上述约束后:

我是否仍然可以在导航栏中显示一个栏按钮项目,并且仍然可以使导航栏的背景透明,以便背景图像显示出来?嗯。。。我想不是。根据UINavigationBar的联机文档:允许使用UINavigationBar类的方法和属性自定义导航栏的外观,但决不能更改其框架、边界或alpha值,也不能直接修改其视图层次结构。要显示或隐藏导航栏,您应该始终通过导航控制器更改其isNavigationBarHidden属性或调用setNavigationBarHidden(uu2;:动画:)方法来显示或隐藏导航栏。现在可以了吗?是的,您的答案有效。但我现在看到,通过隐藏navigationBar,任何Bar按钮项都将被隐藏。也因此,现在我正在尝试,而不是简单地隐藏navigationBar,我是否可以将navigationBar改为半透明。我可以使用来自的答案使navigationBar半透明,但是navigationBar上方的区域不是半透明的。我没有隐藏导航栏,而是将其背景图像设置为20x20半透明图像。该图像在navigationController的整个顶部自动重复,但仍允许条形按钮项通过以下方式显示:
navigationController?.navigationBar.setBackgroundImage(UIImage(名为:“semiTransparent20x20”),例如:。默认值)