UITableview 在 iPhone X 上与主页指示器合并
UITableview merging with the home indicator on iPhone X
我有一个 UITableView
以编程方式创建。此 UITableView
与 iPhone X 设备上的主页指示器合并。
我该如何解决这个问题?
以编程方式,将 tableview 的底部锚点设置为 SafeAreaLayout 的底部锚点。
这里是 sample/test 代码,如何以编程方式设置界面元素的安全区域布局。
if #available(iOS 11, *) {
let guide = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
table.topAnchor.constraintEqualToSystemSpacingBelow(guide.topAnchor, multiplier: 1.0),
guide.bottomAnchor.constraintEqualToSystemSpacingBelow(table.bottomAnchor, multiplier: 1.0)
])
} else {
let standardSpacing: CGFloat = 8.0
NSLayoutConstraint.activate([
table.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 0),
bottomLayoutGuide.topAnchor.constraint(equalTo: table.bottomAnchor, constant: 0)
])
}
以下是有用的参考资料(答案):
您应该在 iOS11 中使用 safeAreaLayoutGuide
并使用 safeArea
设置约束,因此您的内容将不会剪辑。
用于在UITableView
-
中设置约束
ObjC
self.tableView.translatesAutoresizingMaskIntoConstraints = NO;
UILayoutGuide * guide = self.view.safeAreaLayoutGuide;
[self.tableView.leadingAnchor constraintEqualToAnchor:guide.leadingAnchor].active = YES;
[self.tableView.trailingAnchor constraintEqualToAnchor:guide.trailingAnchor].active = YES;
[self.tableView.topAnchor constraintEqualToAnchor:guide.topAnchor].active = YES;
[self.tableView.bottomAnchor constraintEqualToAnchor:guide.bottomAnchor].active = YES;
Swift 4
tableView.translatesAutoresizingMaskIntoConstraints = false
if #available(iOS 11.0, *) {
let guide = self.view.safeAreaLayoutGuide
tableView.trailingAnchor.constraint(equalTo: guide.trailingAnchor).isActive = true
tableView.leadingAnchor.constraint(equalTo: guide.leadingAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: guide.bottomAnchor).isActive = true
tableView.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true
} else {
NSLayoutConstraint(item: tableView, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: tableView, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: tableView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: tableView, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1.0, constant: 0).isActive = true
}
如果您的控制器源自 UITableViewController(而非 UIViewController),屏幕底部的单元格看起来不太好。
我假设您使用的是导航控制器,在这种情况下我的解决方案是:
//dummy view
var bottomX: UIView?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if Device.isIPhoneX {
bottomX = UIView(frame: CGRect(x: 0, y: self.tableView.bounds.size.height - 34, width: self.tableView.bounds.size.width, height: 34))
bottomX!.backgroundColor = self.tableView.backgroundColor
self.navigationController?.view.addSubview(bottomX!)
}
}
别忘了删除虚拟视图
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
bottomX?.removeFromSuperview()
}
结果是:
这个解决方案不是很好,但现在确实有效
这是我"hack"强制在UITableViewController
中设置顶部和底部安全区域。首先你得把它嵌入UINavigationController
(如果不需要隐藏导航栏),然后:
override func viewDidLoad() {
super.viewDidLoad()
configureFakeSafeArea()
}
@available(iOS 11.0, *)
override func viewSafeAreaInsetsDidChange() {
super.viewSafeAreaInsetsDidChange()
topSafeAreaHeight?.constant = view.safeAreaInsets.top
bottomSafeAreaHeight?.constant = view.safeAreaInsets.bottom
}
private var topSafeAreaHeight: NSLayoutConstraint?
private var bottomSafeAreaHeight: NSLayoutConstraint?
private func configureFakeSafeArea() {
guard let view = navigationController?.view else {
return
}
let topSafeArea = UIView()
topSafeArea.backgroundColor = tableView.backgroundColor
var topConstant: CGFloat = 0
if #available(iOS 11.0, *) {
topConstant = view.safeAreaInsets.top
}
topSafeAreaHeight = topSafeArea.heightAnchor.constraint(equalToConstant: topConstant)
view.addSubview(topSafeArea, constraints: [
topSafeArea.leadingAnchor.constraint(equalTo: view.leadingAnchor),
topSafeArea.trailingAnchor.constraint(equalTo: view.trailingAnchor),
topSafeArea.topAnchor.constraint(equalTo: view.topAnchor),
topSafeAreaHeight!
])
let bottomSafeArea = UIView()
bottomSafeArea.backgroundColor = tableView.backgroundColor
var bottomConstant: CGFloat = 0
if #available(iOS 11.0, *) {
bottomConstant = view.safeAreaInsets.bottom
}
bottomSafeAreaHeight = bottomSafeArea.heightAnchor.constraint(equalToConstant: bottomConstant)
view.addSubview(bottomSafeArea, constraints: [
bottomSafeArea.leadingAnchor.constraint(equalTo: view.leadingAnchor),
bottomSafeArea.trailingAnchor.constraint(equalTo: view.trailingAnchor),
bottomSafeArea.bottomAnchor.constraint(equalTo: view.bottomAnchor),
bottomSafeAreaHeight!
])
}
很遗憾我们必须编写所有这些代码,所以如果有人知道实现此目的的更简单方法,请告诉我们。
P.S。我在这里使用了这个小 UIView
扩展:
extension UIView {
func addSubview(_ child: UIView, constraints: [NSLayoutConstraint]) {
addSubview(child)
child.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate(constraints)
}
}
我有一个 UITableView
以编程方式创建。此 UITableView
与 iPhone X 设备上的主页指示器合并。
我该如何解决这个问题?
以编程方式,将 tableview 的底部锚点设置为 SafeAreaLayout 的底部锚点。
这里是 sample/test 代码,如何以编程方式设置界面元素的安全区域布局。
if #available(iOS 11, *) {
let guide = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
table.topAnchor.constraintEqualToSystemSpacingBelow(guide.topAnchor, multiplier: 1.0),
guide.bottomAnchor.constraintEqualToSystemSpacingBelow(table.bottomAnchor, multiplier: 1.0)
])
} else {
let standardSpacing: CGFloat = 8.0
NSLayoutConstraint.activate([
table.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 0),
bottomLayoutGuide.topAnchor.constraint(equalTo: table.bottomAnchor, constant: 0)
])
}
以下是有用的参考资料(答案):
您应该在 iOS11 中使用 safeAreaLayoutGuide
并使用 safeArea
设置约束,因此您的内容将不会剪辑。
用于在UITableView
-
ObjC
self.tableView.translatesAutoresizingMaskIntoConstraints = NO;
UILayoutGuide * guide = self.view.safeAreaLayoutGuide;
[self.tableView.leadingAnchor constraintEqualToAnchor:guide.leadingAnchor].active = YES;
[self.tableView.trailingAnchor constraintEqualToAnchor:guide.trailingAnchor].active = YES;
[self.tableView.topAnchor constraintEqualToAnchor:guide.topAnchor].active = YES;
[self.tableView.bottomAnchor constraintEqualToAnchor:guide.bottomAnchor].active = YES;
Swift 4
tableView.translatesAutoresizingMaskIntoConstraints = false
if #available(iOS 11.0, *) {
let guide = self.view.safeAreaLayoutGuide
tableView.trailingAnchor.constraint(equalTo: guide.trailingAnchor).isActive = true
tableView.leadingAnchor.constraint(equalTo: guide.leadingAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: guide.bottomAnchor).isActive = true
tableView.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true
} else {
NSLayoutConstraint(item: tableView, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: tableView, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: tableView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: tableView, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1.0, constant: 0).isActive = true
}
如果您的控制器源自 UITableViewController(而非 UIViewController),屏幕底部的单元格看起来不太好。
我假设您使用的是导航控制器,在这种情况下我的解决方案是:
//dummy view
var bottomX: UIView?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if Device.isIPhoneX {
bottomX = UIView(frame: CGRect(x: 0, y: self.tableView.bounds.size.height - 34, width: self.tableView.bounds.size.width, height: 34))
bottomX!.backgroundColor = self.tableView.backgroundColor
self.navigationController?.view.addSubview(bottomX!)
}
}
别忘了删除虚拟视图
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
bottomX?.removeFromSuperview()
}
结果是:
这个解决方案不是很好,但现在确实有效
这是我"hack"强制在UITableViewController
中设置顶部和底部安全区域。首先你得把它嵌入UINavigationController
(如果不需要隐藏导航栏),然后:
override func viewDidLoad() {
super.viewDidLoad()
configureFakeSafeArea()
}
@available(iOS 11.0, *)
override func viewSafeAreaInsetsDidChange() {
super.viewSafeAreaInsetsDidChange()
topSafeAreaHeight?.constant = view.safeAreaInsets.top
bottomSafeAreaHeight?.constant = view.safeAreaInsets.bottom
}
private var topSafeAreaHeight: NSLayoutConstraint?
private var bottomSafeAreaHeight: NSLayoutConstraint?
private func configureFakeSafeArea() {
guard let view = navigationController?.view else {
return
}
let topSafeArea = UIView()
topSafeArea.backgroundColor = tableView.backgroundColor
var topConstant: CGFloat = 0
if #available(iOS 11.0, *) {
topConstant = view.safeAreaInsets.top
}
topSafeAreaHeight = topSafeArea.heightAnchor.constraint(equalToConstant: topConstant)
view.addSubview(topSafeArea, constraints: [
topSafeArea.leadingAnchor.constraint(equalTo: view.leadingAnchor),
topSafeArea.trailingAnchor.constraint(equalTo: view.trailingAnchor),
topSafeArea.topAnchor.constraint(equalTo: view.topAnchor),
topSafeAreaHeight!
])
let bottomSafeArea = UIView()
bottomSafeArea.backgroundColor = tableView.backgroundColor
var bottomConstant: CGFloat = 0
if #available(iOS 11.0, *) {
bottomConstant = view.safeAreaInsets.bottom
}
bottomSafeAreaHeight = bottomSafeArea.heightAnchor.constraint(equalToConstant: bottomConstant)
view.addSubview(bottomSafeArea, constraints: [
bottomSafeArea.leadingAnchor.constraint(equalTo: view.leadingAnchor),
bottomSafeArea.trailingAnchor.constraint(equalTo: view.trailingAnchor),
bottomSafeArea.bottomAnchor.constraint(equalTo: view.bottomAnchor),
bottomSafeAreaHeight!
])
}
很遗憾我们必须编写所有这些代码,所以如果有人知道实现此目的的更简单方法,请告诉我们。
P.S。我在这里使用了这个小 UIView
扩展:
extension UIView {
func addSubview(_ child: UIView, constraints: [NSLayoutConstraint]) {
addSubview(child)
child.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate(constraints)
}
}