iOS: Programmatically capture screenshot of view larger than screen - ios

I would like to take a screenshot of an entire UICollectionView (or at least the "top 10" cells). The view doesn't fit on screen.
How do I programmatically capture a snapshot of a view larger than the iPhone's screen?

The problem of capturing a scroll view's content including the offscreen part has been tackled here many times before, so please, search before asking. (See for example: Getting a screenshot of a UIScrollView, including offscreen parts)
But even that won't help you here, because in particular, a collection view's cells that are not shown on the screen do not even exist; that is what cell reuse is about. So there is in fact nothing in existence to take a screen shot of. The cells you can see are the only cells there are.
To put it another way; the collection view does fit on the screen. What's on the screen is the collection view. There isn't any more of it.
You could perhaps construct in code a drawing that looks somewhat like your collection view, but it could be quite a bit of work.

Related

Collection view flickers when page sheet viewcontroller size changes

I have a problem with the screen presented modally.
At some point of scroll offset, whenever I change the screen size, the scroll offset flickers with some cells being re-layout, but the delegate is not asked for the new cells at this time.
I hope that the below GIF illustrates it's quite good.
I guess it's due to a change in the collection view height, which Geoff Hackworth showed here.
I'll be glad for any suggestions.
Probably it is worth noticing that I use Compositional Layout and DiffableDataSource.
EDIT:
I've decided to check how the code sample from Implementing Modern Collection Views will work, when the screen will be presented modally. The result is the same.
It seems that this is a bug in UIKit. When the NSCollectionLayoutSize height is estimated, not absolute it forces the layout to calculate the view size, probably based on preferredLayoutAttributesFitting(layoutAttributes:). On change of the view container height, the view is asked to be layout again. At the beginning of the layout loop, UICollectionViewCompositionalLayout returns estimated, not the actual size of the views, which causes reusable views (both supplementary and cells) to jump across the screen. The overall result looks really weird.
Here it is:

How to correctly animate change of size of a paged UICollectionView

I have an iPad app similar to the iPad Keynote with a narrow overview on the left and a paged UICollectionView of my "slides" on the right. The collection view is using the default FlowLayout. Some of these slides are standard PDFs and some are embedded UIViewControllers that have been scaled (with a CGAffineTransform) and embedded in the cell. I'd like to smoothly animate the overview sidebar offscreen and zoom the current page cell to fullscreen. The collection view should allow paged swiping at whatever size. I'm using storyboards and autolayout.
I think I need to simultaneously animate about three things:
The collection view constraints (to the sidebar) to enlarge/shrink it
The flow layout's sizeForItemAt: value
The CGAffineTransform on the embedded view controller.
I have some pieces working (a single embedded View Controller "slide" that scales correctly) but cannot get the collectionView/cell resize dance to work correctly. The cell resize animation is jerky, or ends up with the wrong offset, or works for the leftmost cell but not for other cells.
I've tried most of the suggestions in the answers to this question but with no convincing success. I can't believe it's impossible but at this point I'm considering the smoke and mirrors approach of animating a static slide and hiding it after the animation completes. The attached video - ignoring the glitches - illustrates the kind of effect I'm after:
It's worth noting, on close inspection, that Keynote cheats somewhat when it comes to swiping between slides in edit mode, and manually manages the next slide sliding onscreen, so probably doesn't use a UICollectionView.
Has anyone done anything similar, or have any suggestions for things to try?
I managed to solve this. There's a proof-of-concept GitHub repo here.
There are a few moving parts:
There are two pieces of UIView scaling code. I suspect these could be combined with suitable delegate references as the nested view controllers are embedded. The first piece scales (statically) correctly when the Collection View cell is created. The second is an animated scale/translate when the sidebar size is changed.
I added a FlowLayout subclass to remove flicker as the collection's layout is invalidated during scaling.
The sidebar-related transform in the top-level VC uses most of the tricks in the book - invalidateLayout(), performBatchUpdates(...), layoutIfNeeded() etc. as well as animating the contentOffset to the correct value. Some manual tracking of the correct page/slide is required.
There's still a slight flicker occasionally at the start of resizing. This may not be an issue with my particular colour-scheme which will be black on dark gray. Bonus points if anyone can suggest how to track this down or alleviate it.

Xcode embed all direct in scrollview without content view

I'm using Xcode 6.4 and I'm struggling with a large page with a bunch of various labels and text fields etc., that has to be scrollable. I looked at various tutorials some of which are obviously outdated and I had all my elements at first in a view that is inside of a scroll view. But that was a big pain with getting all the elements aligned properly using Auto Layout, in addition to not getting it to scroll either.
Now I see one person recommend using the following directly on the elements, without having a content view at all just a scroll view:
Editor -> Embed In -> Scroll View
I like it for the fact that nothing seems out of proportion, all the elements are shown on the iPhone exactly as I have it on the Storyboard without having to set any constraints, however I'm not able to get it to scroll.
This is my class
class ResNotFoundViewController: UIViewController, UIScrollViewDelegate
and I also try to set the height of the scrollview in the code as so:
#IBOutlet weak var scrollviewoutlet: UIScrollView!
and then this in the viewDidLoad as so:
scrollviewoutlet.contentSize = CGSizeMake(375, 840)
.
But I'm not able to get it to scroll at all, it will stay exactly like it opens up with From: Label being the last visible elements.
What am I doing wrong?
You've located the problem, thanks to your logging. (Don't worry about the double call - how many times and when viewDidLayoutSubviews gets called is uninteresting.)
The problem is that you've set the scroll view itself to be taller than the window. In particular, it is 375x809. But so is its contentSize. Thus there is nothing to scroll. A scroll view can only scroll if its contentSize is bigger (in one or two dimensions) than the scroll view. (Moreover, a scroll view bigger than the screen is usually somewhat pointless, since there will be parts of its content that the user will never see - even scrolled all the way, that content will be offscreen.)
So, fix the size of the scroll view itself and you'll be fine. The best way is to assign it constraints that pin its boundaries to its superview, since the superview will have different sizes on different devices.

Change view sizes inside UIScrollView using Autolayout

I'm trying to create a 3x3 menu, based on a grid of buttons, and I'm facing a lot of problems trying to adapt it to different screen sizes.
Since I want my menu to be equally spaced on the screen (using autolayout tricks on the Storyboard), I have created a custom class with this menu that i'm adding to the center part of the main controller view. The problem is that the menu doesn't fit in small screen (3,5" screens).
Trying to solve this problem, I have created a scrollView in the main screen to add the menu and be able to scroll in small screens.
The problem is that since the view I'm loading in the scrollview, automatically fits to the size of the container (in this case the UIScrollView), only a small part of the menu is appearing in the 3,5" screen, without the option of scrolling (In bigger views it appears equally spaced and everything appears correctly).
How can I solve this UIScrollView problem? Or there is a better solution for this problem?
p.s: I'm sorry, but I don't have enough reputation to add images :(
Uiscrollview with autolayout has some pain into it.
You need to place you're inner views so the scrollview Will be able to understand the contentsize it should use.
You can find more detailed info here
http://infinite-edward.tumblr.com/post/66865604683/uiscrollview-contentsize-and-autolayout-gotcha

resizableSnapshotViewFromRect does not resize views within the hierarchy?

I am making an application that displays a bunch of items in a scrollview with different sections having their own items. One feature is to expand each item so it will appear fullscreen, for this effect I use resizableSnapshotViewFromRect to create a snapshot of the view in it's fullscreen dimensions and then scale it down inside the scrollview.
The problem is that for the first displayed section, these views do not get a snapshot of their fullscreen dimensions but rather their downscaled dimensions. For the other sections that do not have their views in the hierarchy the snapshots look fine once you change section so you can view them. I had initially solved this by making a snapshot and then adding the views to the hierarchy in a dispatch_async call, which postponed the view being added after the snapshot finished.
Now I have a case where an image inside the original view for the snapshot might get updated, and thus I'd like to regenerate the snapshot but this fails of course and I have no idea what I should do. In my searchings I haven't found anyone with the same problems so maybe the problem is something else, I don't know, but my findings so far point to the view hierarchy.
Turn off Auto Layout.
Or
Use Constraints as IBOutlets

Resources