UIPinchGestureRecognizer scaling a UICollectionView - ios

I'm trying to use a pinch gesture to scale a collection view only in the y direction. I'm setting the scale correctly (sufficiently), but having trouble keeping the pinched area of the collection view centered.
I've seen many examples of adjusting the translation to keep the pinched content centered, but not to keep a collection view/scroll view content offset centered. Is there something I'm missing here?
I have a sample project which demonstrates it at https://github.com/nickbolton/ScaledCollectionView.
Can anyone offer any suggestions/recommendations/approaches? I'm just not sure where to go with this.
Thanks!

Related

How to implement scaling by dragging view edges/corners like Apply Official Photos app crop control?

The apple official photos application have a edit function which you can crop photos. I would like to implement a similar control for cropping photos. I would like to know how to implement the resizing of the crop mask.
The resizing of the crop mask have the following requirements.
The crop mask can only be resizing by dragging edges or corners.
The anchor point of scaling is opposite the the start edge or corner.
The crop mask can have aspect ratio lock.
The crop mask should not go belong a restricted bounds.
I have done the first 3 requirements, but the 4 requirement is troubling me. Consider a case where the crop mask is at its minimal size at the restricted bounds box bottom left corner. Dragging the top edges will make the view scale with anchor point at the bottom left corner. With this strange behaviour, I think my implementation of changing bounds with opposite anchor point cannot have this behaviour. So I think the apple implementation is different from mine. And I would like to know how these behaviour can be achieved.
The question is what procedure have you even taken.
I would suggest this is done with a simple UIScrollView. Your "crop mask" can be the scroll view which may be resized and repositioned by dragging the corners of it. The scroll view must have the "clip subviews" disabled so you may see the content view outside the scroll view (the content view being the actual image).
So this procedure will already save you all the trouble with bounds when scrolling the image. Moving the scroll view will still have a bit of work... Depending on which corner you are dragging you might need to modify the content offset as you seem to have already figured and should give no trouble at all. Then what is left is putting the image into the crop mask when it gets out of bounds which should be done by calling scroll rect to visible for the whole content view frame; if not it can be easily computed manually as well.
You must also override the hit test method so that the scrolling will happen outside the scroll view.

UICollectionView - a couple of questions

I'm working on an app that is making use of a collecitonview. It's pretty simple as far as the colletionview goes...just displays an array of uiimages in a single-line, horizontal direction view. Here are my questions...
Do I need to have a custom flow layout just to center the images when scrolling? I was able to center the first image the way I want by using insetForSectionAtIndex, however, when I scroll (horizontally), the images are aligned to the left edge of the screen. I was able to fix that by subclassing UICollectionViewFlowLayout and overriding targetContentOffsetForProposedContentOffset. However, I think there has to be a way to do such a simple task without using a custom layout. Also, using this method, while it centers the images when scrolling, it does not allow paging (no snapping the next image in place), which I would prefer. I thought that insetForSectionAtIndex would be called when scrolling through each image, but that does not seem to be the case. Is there any way to force that?
The other question is sort of related to the first...how do I place the cells exactly where I want them? I have the images centered as far as the left and right edges, but I need to move the cells up (- negative) on y axis. Is overriding layoutAttributesForElementsInRect the only way to do this?
Thanks in advance!
In the storyboard, after you add the imageView to the contentView of the cell, use this to center it:
imageView.center = CGPointMake(cell.contentView.bounds.size.width/2,cell.contentView.bounds.size.height/2);

ios - scrollview zooming when scrolling to end, like Fancy

I don't know what this effect is called. Fancy uses it in its app. It works like this.
You have an image at the top of a scrollview.
Drag down and the image gets zoomed to fill the extra top space, so its top edge always remains at the top edge of this scrollview
release your finger and it bounces back
Please give me some idea on how to build this effect. Thanks!
There are many open source implementations of this, such as:
https://github.com/apping/APParallaxHeader
https://github.com/modocache/MDCParallaxView
https://github.com/quemb/QMBParallaxScrollViewController
The basic idea behind these is to have an imageview as a subview of the scrollview. When scrolling, you monitor the content offset of the scrollview, and when you reach a certain threshold, you start increasing the image view's height. If you set the image view's contentMode to UIViewContentModeScaleAspectFill, you will get the effect you want.

Scroll view design feasibility - iOS

Im working on a scroll view design where the 'black boxes are supposed to be image items.The blue box is the scroll view. Is it possible to have a zig zag format? And for the count of the box depends on the images available on the internet. So it is more dynamic. Any suggestions would be greatly appreciated!
Yes, you can definitely do this.
You will be positioning UIImageView objects inside the content area of a UIScrollView. Simply set the contentSize of your UIScrollView to reflect the size of your blue box. Think of UIScrollView as a film strip. The UIScrollView is the visible portion of your film, and the entirety of the film is your contentSize.
Now position each UIImageView by setting its frame as you wish and then add it as a subview to the scrollview. If you find yourself needing more horizontal space, you can resize the contentSize accordingly.

Triple Nested UIScrollView paging issue

Backstory
I have an iPad app that needs to allow the user to navigate through groups of images. Each group is laid out in its own vertical UIScrollView (paged) so the user can swipe up and down down to see each image. Each of the group UIScrollViews is placed in a single (only one exists in the app) outer horizontal UIScrollView (also paged). This works great.... I can swipe up and down to view the images in a group and swipe left and right to go to the next or previous group.
Problem
The problem started when I needed to add zooming for each image. I accomplished this by placing each image inside its own UIScrollView. When the image is zoomed I can pan around the image and when I get to the top or the bottom of the zoomed image the group's vertical UIScrollView pages to the next or previous image as expected. Unfortunately the outer horizontal scrollview will not page to the next group when the image is zoomed and I pan to the leftmost or rightmost edge.
Is there a better(more correct) approach than triple nesting UIScrollViews or can I somehow forward touches to the outer horizontal scrollview?
Any help or suggestions would be greatly appreciated.
hope i'm not too late but I think I have a solution for your problem.
Here you can find an Xcode project demonstrating the scrollview setup you have, your problem and the proposed solution: https://bitbucket.org/reydan/threescrollviews
Basically the solution was to add 1 pixel to the contentSize.width of the vertical scrollviews. This forces the vertical scrollview to scroll a little when you pan to the edge of the zoomed image. It scrolls a little and then continues to the next vertical scrollview.
If you download the project you will see that I've created some scrollviews in the viewDidLoad method. There, I create one horizontal scrollview containing 3 vertical scrollviews, each containing 5 images. Each image is actually incapsulated in a scrollview to enable per-image zooming. In total... triple nested scrollviews.
I've also left some colored borders so that I can easily see how each scrollview scrolls.
the magenta = horizontal scrollview
the white = vertical scrollview
the blue = the image scrollview (the one that contains the image and allows for zooming)
the red = the UIImageView
You will see that I've tagged each image scrollview with value 10. This is used in the implementation of - (UIView*)viewForZoomingInScrollView:(UIScrollView *)scrollView delegate method where I return nil unless the event came from one of the image scrollviews.
If you have any questions about the project I made feel free to ask.
In the end, I would like to say that this browsing method is a little quirky for me as I sometimes scroll in the unwanted direction. Often I think I flick my finger vertically only to find the scrollview going left or right because it interpreted some tiny horizontal movement I had.
The problem I found with paging enabled for both horizontal and vertical movement is that the scrollviews are direction-locked, or so it seemed to me.
EDIT:
Today I've investigated the problem even more. These are my conclusions:
it's not a problem with zooming, it's a problem with having larger content in the innermost scrollview than the visible area(you can try this by zooming or simply initializing the content size larger than the bounds). This enables panning inside the inner-most scrollview and completely changes the behaviour of the touch events.
the bounce for a scrollview flag affects the behaviour of the panning(dragging) gesture when it reaches the edges of the content. If bounces=false then your panning gesture will stop at the edge, not forwarding the drag event up the chain (and thus not scrolling the parent scrollviews to show you other images). If bounces=true then, when you reach the edge and continue to drag the events will be forwarded to the parent scrollview and that scrollview will also be dragged. However, I've found that the dragging while bouncing reduces the distance dragged by aproximately 50%. This also happens in the Photos app.
if you start the dragging while the innermost scrollview is at the edge of the content then the scrollview is smart and will forward all events to the parent scrollview.
for some reason, triple nested scrollviews are problematic as the events are simply not forwarded between the topmost and middle scrollviews while panning inside the innermost scrollview. I have no idea why.
My solution with that +1 pixel to the content size, partially solves the problem.
EDIT 2013
Boy, these scrollviews are something out of this world :(
After more than a year of searching (just kidding... it was actually 2 days) I think I found a good elegant solution to the triple nested scrollviews.
I created a test project here:
https://github.com/reydanro/TripleNestedScrollViews
Inside the app, there is a switch which you can use to test with/without the fix.
The setup I am using in my app is a little different than this question. I have 1 vertical paged scrollview. Inside it, I have multiple horizontal paged scrollviews.
Inside some of the horizontal scrollviews I have another vertical paged scrollview.
Without the fix, once you get to the page with the inner-most scrollview you are pretty much stuck there as the vertical scrolling gestures are not forwarded to the outer-most scroll.
The fix is a custom UIGestureRecognizer that you need to add to the inner-most scrollviews. This recognizer follows touch events and if it detects a drag beyond the contentArea, then it will temporarily disable the rest of the scrollview's recognizers. This is the only method I discovered to make the scrollview forward the events up the chain
The gesture recognizer code is very rough with limited customization but should get the job done. At the moment I am focused on the app I develop, but will continue to update the repository.
PS: I haven't tested what happens with zoom but I see no reason why this method should not work (or be adapted to work).

Resources