What's the best way to build a very flexible/dynamic "header" in UICollectionView - ios

I need to build a UICollectionView with a UICollectionViewFlowLayout and a very dynamic "header" (for clarity, I'll call it "view A" to avoid mixing it with a true collection view header) but I'm not sure about what can be the best way to do that: collectionViewCell, header or supplementary view?
What I mean by flexible, the bullet point being ordered by decreasing importance:
View A will contain buttons and subviews that need to detect gestures so I must be able to detect actions on subviews of view A.
I need to be able to reload data on the collection view without reloading view A.
I need to be able to update the layout of subviews of view A whenever I want (on viewDidScroll of the collection view delegate for example, update according to contentOffset changes).
If possible, I'd like to be able to change the frame of view A dynamically (I mean without having to invalidate the layout). I would like view A to be sticky at the top and shrink while scrolling until it disappear. Have a look at recently launched "Secret" app to see what I mean (done on UITableView for them). Though I could just scroll without changing the frame and cheat by changing the layout of subviews (see point 3) in order to give the sensation of a sticky header.
What do you think is the best component to do that? Can I use a UICollectionViewCell, a header or a supplementary view? If so which one? If not, do you think of an alternative way I could use to have the same behavior (transparent header and view A behind the collection view? adding view A somewhere else, where, in the view hierarchy?).
Thanks for your help!

Take a look at the UICollectionReusableView class.
You can register your nib on the CollectionView as "SupplementaryView" (registerNib:forSupplementaryViewOfKind:withReuseIdentifier:, use the UICollectionElementKindSectionHeader kind of view)
then you have to implement the collectionView:viewForSupplementaryElementOfKind:atIndexPath: method in your delegate and make sure to return something for the UICollectionElementKindSectionHeader kind.
and finally you have to implement the collectionView:layout:referenceSizeForHeaderInSection: method of your UICollectionViewDelegateFlowLayout to set the size of your header.
Let me know if it help.

Related

How to setup a UIScrollView to arrange content dynamically?

I am trying to create a user profile screen. The screen will have lots of information about a user. It will look similar to this AirB
From the looks of it, it seems to be some sort of scrollView? or is it a tableView or a collectionView? (because it seems that there are some rows in there i think)
Does any one here know how this type of view can be accomplished or can be setup?
EDIT two answers below says to use a UITableview, and 2 other answers says to avoid it. Are there any benefits/disadvantages to using either?
Use only one child UIView as i will call it ContainerView inside UIScrollView and then place your child views inside that ContainerView. Use constraint to trailing and leading and top and bottom of that ContainerView to UIScrollView. and use constraint for placing child views to viewController.view not to ContainerView to then iOS will find where child views have to be.
Good Tutorial to find out how to use constraint on scrollView
Apple Technical Note
Do Not use tableview in this case, this content is difficult to maintain in a table view, really, use a scrollview, as for how, a simple googling for "swift uiscrollview tutorial"
Tableview is the best solution for this kind of scrolling views but in the screen you have mapview if it updates every moment i.e. updates with current location then it is not recommended to use tableview.
In that case you can use scrollview with custom views add subview changing with parameters.
In one of my app i did same thing using Tableview. And for that tableview i created a custom cell which have such a big height and i added all the images,map,details of user in that. And it work similar to what you want.
If you want help reply to my answer

How to make cell doesn't scroll along with other cell?

I am making an app that use table View Controller and static cell.
I want to make first cell don't scrolling while other can. This is a picture of what i am talking about.(Sorry for my bad English)
For example as in this picture, I want to make 9gag tab stay when scroll. If you play instragram you will see that when you scrolling the name of user will stay until you scroll into another one. However I want it to stay not changing when it encounter second cell.
Any suggestion?
Using UITableViewController would not help here. You can use these steps to get what you want:
1. Create a UIViewController.
2. Add UITableView as its subview.
3. Add another UIView as UIViewController's view's subview.
4. Using auto layout constraints, you can put UIView above UITableView
This way, you will get a sticky view at the top.
Ok, not exactly sure what you're after but i'll take a stab.
Firstly, if you want the section to remain in place until a new section of items is present, you just need have a look at sections. This is an automatic feature. You may not see it occur until you have plenty of items in the sections.
UITableView With Multiple Sections
There's plenty of stuff about it & not too hard to implement.
My other guess of what you want:
If you want it to remain static regardless of anything, perhaps you could just create a view and place it above the table view. why does it need to be a part of it if it doesn't change?

Adding subview to UICollectionView - disables scrolling

I want to add a subview to a UICollectionView in order to make a left panel that scrolls with the collectionview.
Using
[self.collectionView addSubview:myView]
all touches become disabled and I can no longer scroll the view. I've read that adding a subview to a collectionView like this is bad practice.. is this true? Why does it disable touches from reaching the collectionView event when
userInteractionEnabled = NO
I'm trying to do this: imgur link by grabbing the frame position of the first cell in each section, and adding a dot with to myView with the same y value.
Thanks for any help!
Adding subviews using the addSubview: method to a UICollectionView is very bad practice. It can cause a lot of different problems in the normal behaviour of the CollectionView. It can obstruct the views underneath it, capture the touch events, preventing them from reaching the actual scrollView inside the CollectionView, etc. The subviews added using this method will also not scroll as the other elements in the CollectionView do.
The correct way to do what you want is to implement a new type of UICollectionViewCell for the dots, and compute their locations in the prepareForLayout and layoutAttributesForElementsInRect: methods. Basically you'll have either one or two cells in each row. Which ones will have two rows will be determined by you in the methods I've mentioned.
In fact, Apple's docs have a perfect example that's even more complex than what you're trying you achieve. You should check it out from this link.
May I know the purpose of that scroll view ? Because, if you're looking for a subview that displays only a label or image etc., You can use custom collectionview cell instead if I am not wrong... Hope it helps :) :)

How would I create an "About" page like this for my app? How do I have a UITableView (grouped) under a UIView?

Take this about page for Things:
I'm having trouble creating something similar. I just want a UITableView under a UIView with a UIImageView and a UILabel in it.
If I use a UIViewController and so I can position the UITableView downward, I get this error: "Static table views are only valid when embedded in UITableViewController instances."
If I use a UITableViewController with a grouped style and use contentInset on self.tableView to move it down ([self.tableView setContentInset:UIEdgeInsetsMake(150,0,0,0)];) I can't figure out how to place a view above it. If I try to attach anything to self.view it crashes (obviously). Same happens if I attach anything to self.tableView.
I then tried making the UIView the header of my UITableView section (I only need one section) but I can't get it to move up enough. It just sits inside the UITableView almost.
How do I have a UITableView (grouped style) exist with a UIView above it?
This can be achieved easily using the tableHeaderView property of UITableView. If you are using Interface Builder (which it looks like you are), then you can just drag a UIView above the table view and it will be set as the table's header view. All you need is a UITableViewController; no need for UIViewController and manually laying it out.
That's because the view probably isn't placed on top of the table but rather within the table's section 0 header. Or, even more likely, the view in question is just a regular UITableViewCell with a 0 alpha background.
Either of these options would allow the top view to be scrolled out of frame as the user scrolls under every condition.
I recommend [MDAboutController] (https://github.com/mochidev/MDAboutController)
It's easy to integrate and you don't have to waste any time configuring the UITableView.

iOS prevent subview of tableview from scrolling with tableview

I have added a subview to my tableview and when ever the user scrolls the tableview, the subview scrolls with it. How do I prevent this? I know it's probably along the lines of not adding the view to the tableview's subviews, but I have no knowledge of any other ways to do this. Thanks.
If you want to make a view a subview of the table view, then you can make it floating (non-scrolling) by changing its origin.y value in the scrollViewDidScroll method.
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
self.iv.frame = CGRectMake(self.ivOrigin.x, self.ivOrigin.y + self.tableView.bounds.origin.y, self.iv.frame.size.width, self.iv.frame.size.height);
}
In this example, "iv" is a property for an image view, and "ivOrigin" is a property for the initial origin of the image view (defined when I created the image view and its frame in viewDidLoad).
The UITableView is built and intended to be a view of things that scroll.
So, you can either fight that, which as you're discovering is quite hard since everything about the component is built and focused around scrolling and fast display of a subset of the full list data... Or, you can not fight it and put your static item on top of the table as a fixed-position item.
If there's a reason you can't add the table view and your animate-out item in your main view, you can always add a custom UIView class that contains both the table view and your animated view. Have your custom view class expose the contained table view as a .table property, and the container you're putting things in can be tweaked to use "mycontainerObject.tableview" instead of just "tableview" where needed.
Yes, it's a little more work to write the custom UIView subclass and give it a couple properties to hold the UITableView and whatever UIView you're animating out.. but it's likely a lot safer in the long run than trying to "hack" into the UITableView's methods and view hierarchy to try to give it a "fixed in place" behavior.

Resources