Scrolling function called simultaneously while rotating the ipad screen - ios

I am creating a UIscroll view with 8 pages. Each page is another view controller class with some functionality which is added to this scrollview.
On loading the app, when I scroll the screens from one page to another,the app just works fine.
But when I rotate the ipad to a different interface orientation, the UIScrollView delegate method - ScrollViewDidScroll is called upon and the current screen(page) is scrolled to the previous screen. Debugging makes me reckon that the scrolling function is called simultaneously with the device rotation.
How to stop/prevent the 'ScrollViewDidScroll' delegate method to be called on rotation so that only the rotation functionality is performed (i.e. the screen shouldn't be moved to previous one)?
I have tried different solutions provided but with little help
I am fairly new to xcode development.

Instead of using scrollViewDidScroll method to set the current page, you can use the scrollViewDidEndDecelerating method which is not called on rotation.
With this, you just have to set right contentOffset after the rotation, based on the current page.

Related

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.

scrollToItemAtIndexPath before the view is shown the first time

I have a UIView where I added a UICollectionView. Now this view is shown on app start up. At the same time I'm scrolling to a certain position in my collection view. Therefore I use scrollToItemAtIndexPath. The problem now is that it scrolls to a wrong position, because the collection view has the wrong size at the beginning: If you start the iPad in the landscape orientation on iOS 7 the collection view always takes 768 as width despite it is in landscape.
How can I scroll to a certain position without the user noticing it? Where in the view hierarchy can I call it?
viewWillAppear: frames have not been set
viewDidAppear: not possible without the user noticing it
layoutSubviews: this is called multiple times and I only need it at startup and when the user presses a button
I also tried to use layoutIfNeeded, but that doesn't help for my edge case (iOS 7, iPad, landscape at startup).
Constraints kick around the time viewDidAppear and layoutSubviews is called for the last time. By that time it's too late.
You can try inheriting your own class from UICollectionView and see if its layoutSubviews has correct constraints and call scrollToIndex from there.
If that fails, you can cheat by setting frame sizes in viewDidLoad and calling scroll to index. ( This one is a tad bit more complicated) –

UIScrollView Resizing Itself

I have a UIScrollView inside of a VC. In my viewDidLoad I call a method to set the content size. The issue, however, is that it sets the contentSize to 638, but that immediately gets set to 800. As soon as I rotate, I call that method again and it corrects itself to be 638.
So, something is happening in the loading of my VC. Additionally, if I delay that method call and call it .01 seconds after my viewDidLoad, it works fine and dandy.
Does anyone know anything inside of iOS 7 that would cause a scroll view to resize itself?
More Info: None of my super classes are touching it. They have a property for a scroll view, but I can remove that property and it builds just fine. So this is the only class I've written that touches the contentSize of the scroll view.
This does not happen on iOS 8, only on iOS 7.
i dont know why this is happing but exactly this was happening in my app as well.
You can fix it by calling your method in both viewDidLoad and ViewWillAppear.

Hiding and showing iADs makes my view disappear

I am using ios7 and I am enabled iAds with "self.canDisplayBannerAds"
The iAd basically reshapes the view when it shifts in or when it shifts out. However, When the banner shifts, my view Moves off screen!
In my story board, I put my view outside of the screen. And when the user presses a button, I set its frame property so that it exists inside of the screen. But when the iAd shifts in or out, the View travels back to its original place in the story board.
How can I prevent my view from sliding off the screen?
Update:
I tried simply adding a view programatically. and placed it in the same place as the one I made in Interface Builder. Initially they both move offscreen and on screen when commanded. however, once the iAd shifts in and out, the view I made in interface builder will slide out. The view I made programatically will stay put.
My best guess at this point was Auto layout or something to do with constraints. The IB view was sliding out rather than simply disappearing and It definitely was not using UIView's animation methods. Thus the only other thing that I could think of that could cause animations to happen are constrains. (eg rotating a view with view's that have constriaints will automatically resize in a smooth fashion.
so I took a look at the constraints of the view by calling the constraints method in an NSLog. It printed out a huge list of constraints. I did not add these explicitly, which means they were added automatically.
There may be a connection between these constraints. The question now is, why is the iAD banner triggering the view to basically spring back to its former place?
When the banner shifts in and out, it will layout the subviews. Views without any constraints are given automatic constraints. These constraints place it in the same location as it's place in the xib.
You can try changing the constraints.

viewDidLayoutSubviews called after touchesBegan - again and again

In an iPhone word game I have an UIScrollView (holding UIImageView) and 7 draggable custom UIViews placed initially at the bottom (and outside the scroll view):
In the single ViewController.m I have overwritten viewDidLayoutSubviews so that it always sets the zoomScale of the scroll view - to have the UIImageView fill exactly 100% of the screen width.
This works well - for portrait and landscape modes. And when the app is just started:
My problem is however, when I first pinch/zoom/double-tap the scroll view and then move one of the seven Tile.m views:
Suddenly (not every time) viewDidLayoutSubviews is called after touchesBegan.
This resets the zoom of the scroll view - unexpectedly for the user.
My question is if there is any way to disable this behavior?
Is it possible to prevent viewDidLayoutSubviews call of the parent, when its child UIView is being touched/dragged?
UPDATE:
I've moved the zoomScale setting code from viewDidLayoutSubviews to didRotateFromInterfaceOrientation and the scroll view zoom is okay now, but its contentOffset is reset to {0,0}, when (not always) I drag a Tile - i.e. the scroll view jumps suddenly, the app is unusable.
Adding the following to viewDidLoad hasn't helped:
if ([self respondsToSelector:#selector(setAutomaticallyAdjustsScrollViewInsets:)])
self.automaticallyAdjustsScrollViewInsets = NO;
viewDidLayoutSubviews is called whenever the system performs layout on the view (layoutSubviews). This can be called for a plethora of reasons; you can subclass your view, implement an empty layoutSubviews method (don't forget to call the super implementation!) and put a breakpoint there to see who causes the layout. You may also want to implement setNeedsLayout and layoutIfNeeded, and put breakpoints there also for your investigation, as these trigger layout on followup runloops.
But you will never be able to prevent layout. The system performs layout on many occasions which are outside of your control. For example, if a user makes a call, exists the phone app and returns to your app; a layout is triggered because the bounds and frame of the window have changed. The call ends; layout is again triggered because now the window is back to previous size.
You should be responsible for figuring out when to set the zoom scale. For example, if the user starts a gesture, you should signal your code not to perform changes, even if a layout was performed.

Resources