(Update below)
When I delete items from a section in my collection view (say, section 0), I find that the supplementary views (in this case headers from the UICollectionViewFlowLayout) pop into place as the cells from section zero animate away and a 'duplicate' of the latter sections animates in with them to match the ones that have popped in.
Naturally the ones that pop into place could be the 'duplicates' but it doesn't really matter. It's like the collection view can see the future! and then is catching up with itself. That's how the animation feels.
Do you know if there is some quirk or bug or easy fix to suppressing this extra popping supplementary view?
Update: I've noticed this also occurs with the cells, not just the sections, and it seems to 'double' the bottom few cells and sections on the screen. When I delete cells from the zero section, a handful of sections and cells below it animate properly without duplicates, but beyond a certain point, they pop. A constraints issue?
This is a bug with UICollectionViewFlowLayout. For whatever reason UICollectionViewFlowLayout cannot properly animate cells that are not on screen.
I've done two workarounds that address the issue but none solve it completely. The first is to artificially increase the frame of the collection view so that it creates the cells needed for animation, and thusly animates correctly upon data change. This is a bit of a hack and doesn't work for all cases.
The other option is to write your own flow layout from scratch. This works for me and complexity is entirely up to how complex your layout is. Here is an example I used for writing my own flowlayout: https://github.com/chiahsien/UICollectionViewWaterfallLayout
Related
I am having a problem where my collection view scrolling becomes very choppy/laggy as I get more and more cells. The screen contains a list of messages and comments for the messages, so every single view is dynamically sized. I have a bunch of custom layout attributes which I apply to handle laying and sizing everything.
I apply the custom attributes to the cells by overriding applyLayoutAttributes: and then calculate all the subviews frames from those.
I already cache the calculated sizes of cells but it is not enough.
I assume that there are some techniques people use to address this problem, like caching layout attributes, or somehow preventing the need to layout a cells subviews everytime cellForRow is called?
I assume this is a common problem since it is a problem I have faced with literally every table I make with dynamic content? I would appreciate any ideas :)
P.S. Rasterizing the cells doesn't help.
I'm new in iOS development. Based on my assumption, Feature page in App Store was created using a combination of UITableView and UICollectionView. But how to do that in theory and code? I know it's a bit vague, because it's quite hard to describe it, but I just need some people to help me explain it.
For this case I will try to use these naming:
1. Top section, it's a view which showing banners of apps, people can swipe it to view another banner.
2. Middle section, views which can be scrolled horizontally. (Best New Apps, Best New Games, etc).
3. Bottom section, starts from Quick Links to the bottom.
Questions:
1. The scroll indicator is starts from the root view's top guide, that's normal, but:
a. When we scroll it up, the bounciness is start from the middle section. How to do that? Is the top section and middle section is a separated view? But how can the scroll indicator is started from the root view's top guide if top and middle section is a separated view? (Separated view means that the views should have different scroll indicator unless it's actually subviews of UIScrollView).
b. When we scroll it down, there is nothing that floating. So it looks like that the whole page is a subview of a single scroll view but the bounciness is starts from the middle section. How to create that bounciness effect while only have one scroll indicator for the whole page?
2. In the middle section, there's a several collection view that has horizontal scroll direction. Is it the best way to create it like that is to use UITableView with cell that has UICollectionView inside it? It looks like it was created that way, but:
a. Is it the most efficient way to do that?
b. Because of the case in my first question is my source of confusion.
3. The bottoms section has a different separator from the middle section. The middle section has indentation while the bottom section doesn't. How can I do that if the case is it's a UITableView?
My whole question is just how to create a layout like that. If you cannot help me by providing me some sample codes that's fine, please just explain me the concept or theory of how to do that.
If the whole answer is just I have to create it using vertical/horizontal UIScrollView from scratch that's fine. I just want to make sure of that since I tried to avoid dealing with creating manual tiling.
OK, I think I finally found my own answer.
First, I need a UIScrollView to be root of the view. Then I set the contentSize to be a specific value.
The top section can be a UIPageController or a horizontal UIScrollView.
The middle section is a UITableView with scrollEnabled to NO and cells are static. The static cells (could also be dynamic cells) will contains UICollectionView. Since the scroll is disable, it will use the scroll from the parent UIScrollView. So that's why I can get the same bouncy effect in the middle section.
The bottom section is just another cell of a UITableView.
Thanks.
This might help you with implementing UICollectionViews in your UITableViewCell: http://ashfurrow.com/blog/putting-a-uicollectionview-in-a-uitableviewcell
To make the first cell "float" in the TableView you could make sure that cell never goes out of screen in scrollViewDidScroll
My UITableView has a bunch of reusable cells, and when I tap on one of them, it takes me to another view controller (via push segue) showing the details of that cell (let's say it's an item, so it would show details about an item - name, price, image, etc...). When I pop that view controller (by tapping on the back button), the UITableView has a strange behavior:
a) if it's scrolled all the way to the bottom, it will scroll automatically tad up (around 50 points), leaving the last cell barely visible, so I have to scroll back down again. My cell all have 60 points for height.
b) the scrollbar always shows and then disappears, indicating that something is moving that UITableView (although if not scrolled to the bottom, the content will not move automatically).
This happens in multiple UITableView's I have in my app. I am not forcing a reload of the table view in viewWillAppear, so I don't understand what is happening. My content is static after loading from the server (unless the user changes it, and then the reload is executed). But simply showing details of an item and popping that VC doesn't change anything in the table view.
Edit: Okay, I've figured what the problem is: I'm hiding a UIToolbar when pushing that segue. If I keep it always visible (which I don't want), it still shows the scrollbars animating when popping in my table view but doesn't scroll the table view if on the last few rows.
Add the following to viewDidLoad.
self.automaticallyAdjustsScrollViewInsets = NO;
This solved my problem of table view moving down after navigating back to view controller.
I managed to fix the first issue. It seems like the tableview is not taking into account the 44 points of the UIToolbar.
Save the tableview offset in prepareForSegue: (save it in a CGPoint property)
self.tableViewScrollOffset = self.tableView.contentOffset;
Then, in viewWillAppear:, check if it has been modified. If so, restore it.
if(self.tableView.contentOffset.y != self.tableViewScrollOffset.y) {
[self.tableView setContentOffset:self.tableViewScrollOffset];
self.tableViewScrollOffset = CGPointZero;
}
This behavior is indeed a bug in iOS 8.x.
All answers given so far can not really solve the issue. The issue is, that iOS forgets (or doesn't) consider the previously calculated cell sizes, when a table is being redrawn for instance when the view is being pushed.
One approach to solve this can be found here: UITableView layout messing up on push segue and return. (iOS 8, Xcode beta 5, Swift) (so this question is even a duplicate to this one).
However, the solution provided there is overkill and there are certain situations why this caching will fail (for instance a UIContentSizeCategoryDidChangeNotification is not regarded)
But there is a quite simpler solution even though it is odd:
If you are using a manual performSequeWithIdentifier in didSelectRowAtIndexPath, just add a [self.tableView reloadData] just before.
If you are using a IB seque from the cell, just add [self.tableView reloadData] in your prepareForSeque code.
The reason, why this solves the issue is, that this will force iOS to re-estimate the visible cells and so it no longer scrolls the content to another location. Fortunately, tableView reloadData doesn't cost too much overhead here as only the visible cells will be re-estimated.
Just a hunch, have you got a rogue scrollToRowAtIndexPath:atScrollPosition:animated hanging around?
I was also facing this issue. I managed to find it out. The reason in my case is tableview header height was calculating based text and text height was negative due to which tableview was shifting down even though the contentinset and scrollinset are zero.
This was only occurring for first time. Next time it is calculating correct. One weired thing i found is that when Class A (having tableview) have pushed another Class B from init. When keyboard from Class B is opened viewDidLoad of Class A is called. and before Class B is unloaded from navigation controller. Tableview is reloaded for Class A.
Setting the automaticallyAdjustsScrollViewInsets as suggested above did not work neither did caching and setting the tableViewScrollOffset work.
Hence came up with an workaround which worked like a charm for me.
The workaround was to add an Dummy UIView which has height of 1px and width of 320px and place it between the "Top Layout Guide" and the UITableView. This view's background could be set to clear so that it is invisible.
Now using Autolayouts, fix the Dummy View's top to the Top. Now set the tableview's top constraint with respect to Dummy View. Found that this resolved the issue of the tableview's misplacement.
Screenshot of the Dummy View along with the autolayout constraints have been provided for easy reference. The Dummy View has been set to a larger height and red background colour for illustration purpose only.
I'm trying to figure out what kind of iOS user interface element(s) I should be using to create this interface:
At the bottom of this view, there is a list of items. This list of items can be arbitrarily long. As such, and because of the standard detail disclosure indicator and so on, it makes sense that this is a tableview.
However, the items at the top are not tableview cells. The obvious answer then, is to simply place a tableview on the view, i.e. an embedded tableview. But this leads to another obvious issue, which is that this entire view should be scrollable - there will be a button for "Add Item" underneath the list of items which you will need to be able to scroll to, and the interface will be crappy if the whole view doesn't scroll.
So, I could make it so the tableview is not scrollable, and is just as tall as it needs to be to include as many items as it needs to. Then, the entire view is embedded in a scrollview, and scrolls properly. My concern with this relates to memory management, if I do this, I don't think I'll be taking advantage of the dynamic cell creation that is inherently part of a scrollable tableview, and will instead have dozens or even hundreds of cells instantiated when the view loads.
Another alternative would be to make the entire interface a tableview, with the top portions, and the bottom button, implemented as custom tableview cells that are different from the cells that show items. In the past, however, I've found that this is a pain-in-the-ass too, but perhaps it's a pain I must endure.
In general, I feel like I'm missing an obvious approach here, since this seems like it ought to be extremely simple to implement, but I'm currently at a loss. Help is appreciated!
jjv360 mentioned it correctly, this should be 1 tableview with sections and custom cells. The different look comes from nice images.
It's all a tableview with a single cell type, and 4 sections.
The cell has an optional image, a label and the optional disclosure indicator. If those don't exist, the label expands to encompass the full space.
It's very easy to do, quite standard.
I am trying to configure my CollectionView to have one section be differently sized than the others. I have two sections. Lower part should show a number of cells simultaneously and the upper section should only show one cell at a time but be scrollable to reveal more cells one by one.
I tried to play with the .frame property of the CollectionView but obviously it is not the right approach as it changes the appearance of the whole view.
I also tried to retrieve the FlowLayout object and see if I can get it from there. Did not find a way.
Neither the section Insets are the answer so far ...
It is simple to use two uicollectionviews for upper and lower section, instead of using only one.