怪异的iOS11中的可视化行为。 单元格通过导航推animation面向上滚动
我最近将一些代码迁移到新的iOS 11 beta 5 SDK。
我现在从UITableView得到一个非常混乱的行为。 桌面本身并不是那种幻想。 我有自定义的单元格,但大部分只是为了他们的高度。
当我推我的视图控制器与tableview我得到一个额外的animation,单元格“向上滚动”(或可能整个tableview框架被改变),并沿着推/stream行导航animation下来。 请参阅gif:
我手动在loadView
方法中创buildtableview
,并设置自动布局约束等于tableview的superview的前导,尾随,顶部,底部。 超级视图是视图控制器的根视图。
视图控制器推送代码非常标准: self.navigationController?.pushViewController(notifVC, animated: true)
相同的代码提供了iOS 10上的正常行为。
你能指点我什么是错的方向?
编辑:我做了一个非常简单的tableview控制器,我可以在那里重现相同的行为。 码:
class VerySimpleTableViewController : UITableViewController { override func viewDidLoad() { super.viewDidLoad() self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell") } override func numberOfSections(in tableView: UITableView) -> Int { return 1 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 4 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel?.text = String(indexPath.row) cell.accessoryType = .disclosureIndicator return cell } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) let vc = VerySimpleTableViewController.init(style: .grouped) self.navigationController?.pushViewController(vc, animated: true) } }
编辑2:我能够缩小问题,以我的UINavigationBar的自定义。 我有这样的定制:
rootNavController.navigationBar.setBackgroundImage(createFilledImage(withColor: .white, size: 1), for: .default)
createFilledImage
创build具有给定大小和颜色的方形图像。
如果我注释掉这条线,我会恢复正常的行为。
对于这个问题,我将不胜感激。
这是由于UIScrollView's
(UITableView是 UIScrollView's
一个子类)新的contentInsetAdjustmentBehavior
属性,它默认设置为contentInsetAdjustmentBehavior
。
您可以在任何受影响的控制器的viewDidLoad中使用以下片段覆盖此行为:
tableView.contentInsetAdjustmentBehavior = .never
https://developer.apple.com/documentation/uikit/uiscrollview/2902261-contentinsetadjustmentbehavior
除了maggy的回答
Objective-C的
if (@available(iOS 11.0, *)) { scrollViewForView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; }
您可以在整个应用程序中通过在例如didFinishLaunchingWithOptions中使用NSProxy来一次性编辑此行为:
if (@available(iOS 11.0, *)) { [UIScrollView appearance].contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; }
另外,如果您使用标签栏,集合视图的底部内容插入将为零。 为此,把下面的代码放在viewDidAppear中:
if #available(iOS 11, *) { tableView.contentInset = self.collectionView.safeAreaInsets }
这看起来更像是一个比预期行为更糟的错误。 导航栏不透明或设置背景图像时发生。
如果您只是将contentInsetAdjustmentBehavior设置为“。”,则不会在iPhone X上正确设置内容插入,例如内容将进入滚动条下方的底部区域。
有必要做两件事情:
1.防止scrollViewanimation推/stream行
2.保留自动行为,因为它是iPhone X所需要的。没有这个例如纵向,内容将低于底部滚动条。
注意:如果在横向模式下使用UIScrollView,它仍然不会正确设置水平插入(另一个bug?),所以您必须将scrollView的前导/尾随挂接到IB中的safeAreaInsets。
注2:下面的解决scheme也有问题,如果tableView滚动到底部,并且你推控制器和popup,它不会在底部了。
override func viewDidLoad() { super.viewDidLoad() // This parts gets rid of animation when pushing if #available(iOS 11, *) { self.tableView.contentInsetAdjustmentBehavior = .never } } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) // This parts gets rid of animation when popping if #available(iOS 11, *) { self.tableView.contentInsetAdjustmentBehavior = .never } } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // This parts sets correct behaviour(insets are correct on iPhone X) if #available(iOS 11, *) { self.tableView.contentInsetAdjustmentBehavior = .automatic } }
以下是我如何设法解决这个问题, 同时仍然允许iOS 11自动设置插入 。 我正在使用UITableViewController
。
- 在视图控制器的故事板中(或以编程方式 )select“扩展顶部条下方的边”和“在不透明条之下延伸边”。 安全区域插入将阻止您的视图在顶部栏之下。
- 检查故事板中桌面视图上的“插入到安全区域”button。 (或
tableView.insetsContentViewsToSafeArea = true
) – 这可能不是必要的,但这是我做的。 - 设置内容调整行为为“Scrollable Axes”(或
tableView.contentInsetAdjustmentBehavior = .scrollableAxes
).always
也可以,但是我没有testing。
还有一件事要尝试,如果一切都失败了:
覆盖viewSafeAreaInsetsDidChange
UIViewController
方法获取表视图强制设置滚动视图插图到安全区域插页。 这与马吉的回答中的“从不”设置相结合。
- (void)viewSafeAreaInsetsDidChange { [super viewSafeAreaInsetsDidChange]; self.tableView.contentInset = self.view.safeAreaInsets; }
注意: self.tableView
和self.view
应该是UITableViewController
相同的东西
删除此代码为我工作
self.edgesForExtendedLayout = UIRectEdgeNone
在我的情况下,这工作(把它放在viewDidLoad):
self.navigationController.navigationBar.translucent = YES;
请确保与上面的代码一起,添加如下代码。 它解决了这个问题
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) // print(thisUISBTV.adjustedContentInset) }