AlanQuatermain / AQGridView

A grid view for iPhone/iPad, designed to look similar to NSCollectionView.
http://quatermain.tumblr.com/
BSD 3-Clause "New" or "Revised" License
2.37k stars 446 forks source link

HeaderView Question #106

Open BBuff opened 12 years ago

BBuff commented 12 years ago

I'm able to add a UISearchbar to the grid view's HeaderView and it displays properly. However, what I'd like to do is only show the header when the grid is scrolled down. This would allow access to the search bar without it being in the way all of the time. Does anyone have a recommendation on how to accomplish this?

Thanks in advance...

evadne commented 12 years ago

Override its -layoutSubview.

Some may say that doing things in -scrollViewDidScroll: is fine, but it might give artifacts when swiped rapidly… so just subclass. :)

On Jan 18, 2012, at 11:16 AM, BBuff wrote:

I'm able to add a UISearchbar to the grid view's HeaderView and it displays properly. However, what I'd like to do is only show the header when the grid is scrolled down. This would allow access to the search bar without it being in the way all of the time. Does anyone have a recommendation on how to accomplish this?

Thanks in advance...


Reply to this email directly or view it on GitHub: https://github.com/AlanQuatermain/AQGridView/issues/106

BBuff commented 12 years ago

Thanks Monoceroi! That's where I started my search last night, but I can't tell for the life of me where the header view size is taken in to account in layoutSubviews. Any chance you can give me a nudge on this?

Thanks again for taking the time to respond. I really appreciate it and the learning experience is great!

evadne commented 12 years ago

Just take a look at the contentOffset, then you know where to move your header view to. Do this after calling super so your code always run after stuff has happened.

:)

On Jan 18, 2012, at 19:42, BBuff reply@reply.github.com wrote:

Thanks Monoceroi! That's where I started my search last night, but I can't tell for the life of me where the header view size is taken in to account in layoutSubviews. Any chance you can give me a nudge on this?

Thanks again for taking the time to respond. I really appreciate it and the learning experience is great!


Reply to this email directly or view it on GitHub: https://github.com/AlanQuatermain/AQGridView/issues/106#issuecomment-3544443

BBuff commented 12 years ago

Thanks. I'll check this out tonight.

Sent from my iPhone

On Jan 18, 2012, at 7:49 AM, Evadne Wureply@reply.github.com wrote:

Just take a look at the contentOffset, then you know where to move your header view to. Do this after calling super so your code always run after stuff has happened.

:)

On Jan 18, 2012, at 19:42, BBuff reply@reply.github.com wrote:

Thanks Monoceroi! That's where I started my search last night, but I can't tell for the life of me where the header view size is taken in to account in layoutSubviews. Any chance you can give me a nudge on this?

Thanks again for taking the time to respond. I really appreciate it and the learning experience is great!


Reply to this email directly or view it on GitHub: https://github.com/AlanQuatermain/AQGridView/issues/106#issuecomment-3544443


Reply to this email directly or view it on GitHub: https://github.com/AlanQuatermain/AQGridView/issues/106#issuecomment-3545078

BBuff commented 12 years ago

I played around with the contentOffset in layoutSubviews but then the searchbar was hidden but the ScrollView stopped scrolling. Any hints?

evadne commented 12 years ago

Can you post the code?

On Jan 21, 2012, at 5:32 AM, BBuff wrote:

I played around with the contentOffset in layoutSubviews but then the searchbar was hidden but the ScrollView stopped scrolling. Any hints?


Reply to this email directly or view it on GitHub: https://github.com/AlanQuatermain/AQGridView/issues/106#issuecomment-3590903

BBuff commented 12 years ago

The IF below is in layoutSubviews and I added the setContentOffset part.

if ( _headerView != nil ) { rect = _headerView.frame; rect.origin = CGPointZero; rect.size.width = self.bounds.size.width; _headerView.frame = rect;

    [self setContentOffset:CGPointMake(0.0, _headerView.frame.size.height)];
}
evadne commented 12 years ago

Not quite, but I digress. Realized that I might have misunderstood what you mean by “scroll down”.

This should make your header view always appear:

- (void) layoutSubviews {

    [super layoutSubviews];

    self.headerView.center = (CGPoint){
        roundf(0.5f * CGRectGetWidth(self.bounds)),
        roundf(self.contentOffset.y + 0.5f * CGRectGetHeight(self.headerViewbounds))
    };

    [self bringSubviewToFront:self.headerView];

}

If you want a header view that only appears when the user scrolls to the top, just adjust the contentOffset to hide it on the view’s appearance, for example in -viewWillAppear: if you are using a view controller around the grid view.

You can also consider simply adding it above the zero point, then incrementing the content inset. But this is no much different than simply using the gridHeaderView property, just more code, which is usually unnecessary.

- (void) viewDidLoad {

    [super viewDidLoad];

    UIView *aHeaderView = [self gridHeaderView];
    aHeaderView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleBottomMargin;
    aHeaderView.frame = (CGRect){
        (CGPoint){ 0, -1 * CGRectGetHeight(aHeaderView.bounds) },
        (CGSize){ CGRectGetWidth(self.gridView.bounds), CGRectGetHeight(aHeaderView.bounds) }
    };

    [self.gridView addSubview:aHeaderView];

    UIEdgeInsets newContentInset = self.gridView.contentInset;
    newContentInset.top += CGRectGetHeight(aHeaderView.bounds);
    self.gridView.contentInset = newContentInset;

}
evadne commented 12 years ago

Um, guess I am fabulously wrong. If the Grid View actually already makes sure that your header view is always at the top of the visible rect, then you move its center to something like

(CGPoint){ 0, roundf(0.5f * CGRectGetHeight(aHeaderView.bounds)) }

in your overridden -layoutSubviews and things will be fine. I am not sure if the grid view leaves space for the header view, guess we’ll need to implement what you said to be sure…

evadne commented 12 years ago

So I just checked out the source and could verify that the gridHeaderView actually “sticks there”, meaning whenever the grid view is scrolled the header view scrolls with it.

It strongly implies that the original implementation does what you wanted quite perfectly.

Please post more code. If you can put the entire project up, better.

BBuff commented 12 years ago

Thanks for the follow-up. What I'm really looking for is for the headerView to be added to the top of the scrollView but I want the scroll to display starting at the bottom of the headerView. Then, when the user scrolls the view down with their finger the header view displays. The iBooks app, for example, does this. In the Library view you don't see the search bar initially but when you scroll the view down you do.

Does that make sense?

evadne commented 12 years ago

Doh. That means the header view is initially not shown, but pulling the entire list downwards reveals it. Usually, you can just use the gridHeaderView property, but then with an enclosing view controller, do things like this:

- (void) viewDidLoad {

    [super viewDidLoad];

    [self.gridView setContentOffset:(CGPoint){
        0,
        CGRectGetHeight(self.gridView.gridHeaderView)
    } animated:NO];

}

In other words, pre-scroll the entire grid view a bit so the header view is initially not shown. Guess this is what you’d like to do.

BBuff commented 12 years ago

When I add that to viewDidLoad the grid doesn't display any data. When I add it to viewWIllAppear it doesn't scroll. Here's what the grid view looks like in the immediate window. It looks like the contentOffset is getting set correctly.

<AQGridView: 0xa18ba00; baseClass = UIScrollView; frame = (0 0; 320 416); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x9930100>; contentOffset: {0, 44}>