AMScrollingNavbar icon indicating copy to clipboard operation
AMScrollingNavbar copied to clipboard

search controller on ios 11

Open fralways opened this issue 8 years ago • 5 comments

Hi, I have an issue with navigation + search controller on ios11. If I scroll slowly my table view it can happen that search bar doesnt behave as intended-

ex1: I scroll up just a bit more than a half of nav bar height, then release - nav bar gets removed, but parts of search bar remains.

ex2: I scroll very little up, then release - nav bar gets reseted to original height, but search bar now has less height then when I started to scroll. (It doesnt help if I add self.searchController.searchBar as follower)

Any1 else with these issues? Im using objc. For test purpose you could add property - @property UISearchController *searchController; method in viewDidLoad - [self initSearchController] and implementation -

- (void)initSearchController{
    self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
    self.searchController.hidesNavigationBarDuringPresentation = NO;
    self.searchController.searchBar.searchBarStyle = UISearchBarStyleDefault;
    self.searchController.searchBar.placeholder = @"search";
    
    if (@available(iOS 11.0, *)) {
        self.navigationItem.searchController = self.searchController;
    }else{
        self.navigationItem.titleView = self.searchController.searchBar;
    }
}

fralways avatar Dec 22 '17 13:12 fralways

This is being discussed in #219 I don't have a fix unfortunately, any help is welcome.

andreamazz avatar Dec 22 '17 13:12 andreamazz

Ok so after spending a bit of time here, the idea is to prevent scrolling navbar if search bar is visible. What I did is next in ScrollingNavigationController - added property fileprivate var searchController: UISearchController?

added methods:

private func checkSearchController(_ delta: CGFloat) -> Bool {
        if searchController != nil && delta > 0 {
            if searchController!.searchBar.frame.height != 0 {
                return false
            }
        }
        return true
    }
open func followScrollView(_ scrollableView: UIView, delay: Double = 0, scrollSpeedFactor: Double = 1, followers: [UIView] = [], searchController: UISearchController) {
        self.searchController = searchController
        followScrollView(scrollableView, delay: delay, scrollSpeedFactor: scrollSpeedFactor, followers: followers)
    }

(note: I added a complete new method, other solution would be to include searchbar in followers, and then check if any of followers is searchbar)

and last edited method -

func handlePan(_ gesture: UIPanGestureRecognizer) {
        if let superview = scrollableView?.superview {
            let translation = gesture.translation(in: superview)
            let delta = (lastContentOffset - translation.y) / scrollSpeedFactor
            if (!checkSearchController(delta)){
                lastContentOffset = translation.y
                return
            }
            
            if gesture.state != .failed {
                lastContentOffset = translation.y
                if shouldScrollWithDelta(delta) {
                    scrollWithDelta(delta)
                }
            }
        }
        
        if gesture.state == .ended || gesture.state == .cancelled || gesture.state == .failed {
            checkForPartialScroll()
            lastContentOffset = 0
        }
    }

And, of course, the call now is [((ScrollingNavigationController *)self.navigationController) followScrollView:self.tableView delay:0 scrollSpeedFactor:1 followers:@[] searchController:self.searchController];

Could you check this out?

fralways avatar Dec 22 '17 14:12 fralways

That looks good, I'm just wondering if we can just check for topViewController?.navigationItem.searchController instead. That should work, right?

andreamazz avatar Dec 22 '17 14:12 andreamazz

Ok, that seems to work, checkout commit 1123b4e

andreamazz avatar Dec 22 '17 15:12 andreamazz

Just found out there could be setting self.navigationItem.hidesSearchBarWhenScrolling = false; in this case fix doesnt work and quick solution might be to just ignore new code (checkSearchController method returns true in this case), but graphics is very buggy.

fralways avatar Dec 22 '17 16:12 fralways