Weird uitableview behaviour in iOS11. Cells scroll up with navigation push animation

前端 未结 12 1420
粉色の甜心
粉色の甜心 2021-01-29 18:34

I have recently migrated some code to new iOS 11 beta 5 SDK.

I now get a very confusing behaviour from UITableView. The tableview itself is not that fancy. I have custo

相关标签:
12条回答
  • 2021-01-29 19:10

    This seems more like a bug than intended behavior. It happens when navigation bar is not translucent or when background image is set.

    If you just set contentInsetAdjustmentBehavior to .never, content insets won't be set correctly on iPhone X, e.g. content would go into bottom area, under the scrollbars.

    It is necessary to do two things:
    1. prevent scrollView animating up on push/pop
    2. retain .automatic behaviour because it is needed for iPhone X. Without this e.g. in portrait, content will go below bottom scrollbar.

    New simple solution: in XIB: Just add new UIView on top of your main view with top, leading and trailing to superview and height set to 0. You don't have to connect it to other subviews or anything.

    Old solution:

    Note: If you are using UIScrollView in landscape mode, it still doesn't set horizontal insets correctly(another bug?), so you must pin scrollView's leading/trailing to safeAreaInsets in IB.

    Note 2: Solution below also has problem that if tableView is scrolled to the bottom, and you push controller and pop back, it will not be at the bottom anymore.

    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
        }
    }
    
    0 讨论(0)
  • 2021-01-29 19:11
      if #available(iOS 11, *) {
            self.edgesForExtendedLayout = UIRectEdge.bottom
      }
    

    I was using UISearchController with custom resultsControllers that has table view. Pushing new controller on results controller caused tableview to go under search.

    The code listed above totally fixed the problem

    0 讨论(0)
  • 2021-01-29 19:12

    Removing extra space at top of collectionView or tableView

        if #available(iOS 11.0, *) {
            collectionView.contentInsetAdjustmentBehavior  = .never
            //tableView.contentInsetAdjustmentBehavior  = .never
        } else {
            automaticallyAdjustsScrollViewInsets = false
        }
    

    Above code collectionView or tableView goes under navigation bar.
    Below code prevent the collection view to go under the navigation

        self.edgesForExtendedLayout = UIRectEdge.bottom
    

    but I love to use below logic and code for the UICollectionView

    Edge inset values are applied to a rectangle to shrink or expand the area represented by that rectangle. Typically, edge insets are used during view layout to modify the view’s frame. Positive values cause the frame to be inset (or shrunk) by the specified amount. Negative values cause the frame to be outset (or expanded) by the specified amount.

    collectionView.contentInset = UIEdgeInsets(top: -30, left: 0, bottom: 0, right: 0)
    //tableView.contentInset = UIEdgeInsets(top: -30, left: 0, bottom: 0, right: 0)
    

    The best way for UICollectionView

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
            return UIEdgeInsets(top: -30, left: 0, bottom: 0, right: 0)
    }
    
    0 讨论(0)
  • 2021-01-29 19:12

    Delete this code work for me

    self.edgesForExtendedLayout = UIRectEdgeNone
    
    0 讨论(0)
  • 2021-01-29 19:14

    please make sure along with above code, add additional code as follows. It solved the problem

    override func viewDidLayoutSubviews() { 
         super.viewDidLayoutSubviews() 
         tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) // print(thisUISBTV.adjustedContentInset) 
    }
    
    0 讨论(0)
  • 2021-01-29 19:20

    In addition to maggy's answer

    OBJECTIVE-C

    if (@available(iOS 11.0, *)) {
        scrollViewForView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    }
    

    This issue was caused by a bug in iOS 11 where the safeAreaInsets of the view controller's view were set incorrectly during the navigation transition, which should be fixed in iOS 11.2. Setting the contentInsetAdjustmentBehavior to .never isn't a great workaround because it will likely have other undesirable side effects. If you do use a workaround you should make sure to remove it for iOS versions >= 11.2

    -mentioned by smileyborg (Software Engineer at Apple)

    0 讨论(0)
提交回复
热议问题