Add a floating bar to a scroll view like in the F

2019-03-16 21:04发布

问题:

I've been playing around with adding different interactions to a test project of mine, and I'm having trouble adding something like Facebook's post status bar, the one that sits on the timeline scrollview and scrolls with the scrollview when you're scrolling down the view but stays stuck under the navbar when you're scrolling up it.

I've been creating a separate UIViewController (not UIView) and adding it as a subview to the main ViewController. I'm not exactly too sure where to go from there though... How does the new view scroll with the scrollview? Should I even be using a separate viewcontroller?

Any help would be greatly appreciated! Thanks!

回答1:

Here's some sample code you can use to get started, just add it to your view controller. It uses a generic UIView for the floating bar and a generic UIScrollView for the scroll view but you can change that to whatever you want.

@interface BNLFDetailViewController () <UIScrollViewDelegate> {
    UIScrollView *_scrollView;
    UIView *_floatingBarView;
    CGFloat _lastOffset;
}
@end

And in the @implementation add:

- (void)viewDidLoad {
    [super viewDidLoad];

    _scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
    _scrollView.delegate = self;
    _scrollView.contentSize = CGSizeMake(self.view.bounds.size.width, self.view.bounds.size.height * 2);
    [self.view addSubview:_scrollView];

    CGRect f = self.view.bounds;
    f.size.height = kFloatingBarHeight;
    _floatingBarView = [[UIView alloc] initWithFrame:f];
    _floatingBarView.backgroundColor = [UIColor blackColor];
    [self.view addSubview:_floatingBarView];
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (scrollView == _scrollView) {
        CGFloat offsetChange = _lastOffset - scrollView.contentOffset.y;
        CGRect f = _floatingBarView.frame;
        f.origin.y += offsetChange;
        if (f.origin.y < -kFloatingBarHeight) f.origin.y = -kFloatingBarHeight;
        if (f.origin.y > 0) f.origin.y = 0;
        if (scrollView.contentOffset.y <= 0) f.origin.y = 0; //Deal with "bouncing" at the top
        if (scrollView.contentOffset.y + scrollView.bounds.size.height >= scrollView.contentSize.height) f.origin.y = -kFloatingBarHeight; //Deal with "bouncing" at the bottom
        _floatingBarView.frame = f;

        _lastOffset = scrollView.contentOffset.y;
    }
}

You should be doing it as a UIView, not a UIViewController. The general rule in iOS development is that view controllers take up the entire screen and views are used for "subviews" that take up part of the screen (though this is less the case for iPad). Either way, a UIViewController has it's own lifecycle (willAppear, didAppear, etc.) which is not needed/wanted for the floating bar so it should definitely be a UIView.