Fast custom animation using CADisplayLink causes stroboscopic effect. How to avoid it? - ios

Scenario:
Horizontally scrolling UIScrollView with reused page views (so that there are only few page viewcontrollers which are being reused similar way like UITableView cells). So that they are able to be updated with new content and reused I need to know exact position of UIScrollView's content view (offset). This works great.
Now I need to implement custom scrolling animation - I mean to programatically move the content view, so that user touches some buttons, and the scroll view scrolls to desired position with this custom animation. The movement can be very quick and very far. I can not use Core Animation for this, as I could not track position during animation (CA reports you only start and end of the movement). So I decided to use CADisplayLink, and calculate each UIScrollView content for each position. This works great too.
The only problem is, that sometimes I see stroboscopic effect - say I am moving the content to the right, and it looks like it is moving to left. If I look at builtin animation within UISCrollView using setContentOffset:animated:, the animation is smooth and nice. Does anyone know, how to get rid of this stroboscopic effect?

Most likely your issue is that timestamp is a double and you're assigning it to a float
Floats have 7 digits while Doubles have 15-16 digits.
So in other words you're experiencing data loss. By using double you should see a silky smooth animation.

Related

Dynamic Movement of Cell Frames in UICollectionView w/ Custom Layout

I'm trying to add dynamic, animated movement to the cells in my UICollectionView / custom layout.
Basically... when a user taps cell A, it moves to the center, pushing all the other nearby cells (radially) out of its way, and then those cells crowd around it, filling up the space.
Now, when the user taps it again, I want the animation to invert.
And if the user scrolls, I want the animation to fluidly, continuously, and incrementally proceed or rewind, until some threshold point where it goes all the way in that direction.
Brainstorm
Recalculating the relevant cells' frames upon every signal from the UIScrollView, then continuously animating the change from the old layout to the new one with setCollectionViewLayout: animated: crossed my mind... but not only does it feel a horribly stupid way to do it... it won't work when new signals come mid-animation.
Can I not just grab the frames of the visible cells and animate their frame changes, like with any regular view? Using transitionWithView:duration:options:animations:completion: and UIViewAnimationOptionBeginFromCurrentState to keep the motion continuous and updatable?
Any other ideas?
EDIT-- Current Tentative Solution
At the moment, I'm going to try...
1) Reach into the collection view's visible cells, to just grab the relevant cells and animate the frame changes when necessary.
2) I'm going to use this CALayer trick Core animation progress callback, so that I can get continuous position update signals for the driving cell, to drive the animations of the cells it needs to push away when they come into contact.
3) I'll use shouldInvalidateLayoutForBoundsChange: with transitionWithView:duration:options:animations:completion: and UIViewAnimationOptionBeginFromCurrentState to implement the fluid, on demand, play / rewind function
(quick visual example)

Very slow deceleration in UIScrollView just in certain cases

I am struggling with aligning a screen to a certain Views inside a UIScrollView. I would like to have same behaviour as paging (same fast and smooth deceleration) but with alignment to a custom views instead of stoping on multiples of the scroll view’s bounds. I have implemented delegate method scrollViewWillEndDragging(_:withVelocity:targetContentOffset:) in order to define my own scroll view’s bounds location. I have also set decelerationRate to UIScrollViewDecelerationRateFast.
It work mostly as desired except the cases when alignment animation is very slow. To be more precise, sometimes, after the dragging is finished, the scrolling animation decelerates to final point very slowly. It finally reach the correct point but after a longer while. I am not able to track down the cases when it happens. I am able to say that everything works fine when final velocity of dragging is zero. Thus, it happens only in some cases when dragging is finished with nonzero velocity.
I wonder if somebody had same problem since I wasn't able to google anything useful. Can you help me please?
I have solved this problem by implementing delegate methods scrollViewDidEndDragging and scrollViewWillBeginDecelerating. Then by using information from scroll view’s pan gesture I found out about translation and I determined final scroll view’s bounds location using setContentOffset method on scroll view.

Circular scrolling in iOS that follows your finger?

So I am trying to figure out how to make a circular scrolling system. So I have for example a wheel like this http://static.cubiq.org/uploads/2009/04/Rotating-wheel.jpeg and you scroll between options (like an old school ipod) Now I currently already have this working with positions. So I have positions 1-6 and as you scroll down, it moves everything down a position and I animate this transition. I am wondering if there is a way to do this using the actual scroll function. So that you can scroll up and down freely while holding down, rather then doing up or down actions and waiting for animation.
So given that information how could I convert a standard vertical scroll up->down and down->up into a circle structure. Thanks for any info

Custom UICollectionViewLayout (Passbook UI replica) - disable fade animations for cells

I'm trying to recreate the passbook UI using a collection view with a custom layout.
So far so good, but there's this thing I can't seem to find a solution for.
Problem: When I click on a cell I want it to move up to the top of the screen (content offset of the cv). Most of the cells don't have a problem with this and they perform as such. However, when the selected cell is near the bottom of the screen, there's no moving at all... just a fade-out and fade-in.
To achieve this animation, I embedded the layout subclass' invalidateLayout in an animation block to be performed by UIView. No matter how high or low I set the time interval, the duration is still the same, and so no effect on the fade-in fade-out behaviour.
I'll paste here the methods that I believe to need to be modified and also a link to a video on youtube. Hopefully, someone can find a solution for this >_<".
YT: https://www.youtube.com/watch?v=3xIL-fFUcJo
Code: http://pastebin.com/QKLKGwdN

How to drag a view inside UIScrollView with scrolling near edges?

I'm trying to create some sort of timeline view like in video editors: media elements in a row, which are UIView's. I can successfully drag these views inside currently visible part of scroll view using UIScrollView touch events like touchesBegan and touchesMoved. I want to scroll the scroll view once subview is dragged to one of the scroll view edges. The best I can think of now is to create a timer that will scroll the view while user holds the subview with the finger near scroll view edge.
There's a lot of questions here on the same topic, but I was unable to find one that covers scrolling.
Is there a good way to do this? Should I use gesture recognizers instead?
Thank you in advance.
Actually what you want IS a timed event. As soon, as the user is at the edge of the scrollview, you start a timer, which regularly increases the contentOffset. If you don't like your animation results (i guess you're using setContentOffset:animated:?), just try another timing and distance of animation.. I guess you have to try some different settings. What I would try first is 1px at a time. Perhaps every 0.3 second?
If that doesn't work you could also try another "extreme". Start a single animation, when the user reaches the edge, which animates the contentOffset until the end of the contentSize. But over a large timespan so the movement is slow. If the user stops dragging, or moves out of the edge, stop the animation at the current position. That would even be a solution without a timer, because the animation would be your timer itself.
I seriously doubt gesture recognizers would part of a good solution to this since they tend to be most helpful with discreet gestures.
I don't think I can improve on your general direction based on the assumption, implied above, that you are looking for continuous/gradual scrolling.
What I suggest instead is that you consider designing this to use a paged scrolling approach. When your user drags the object to the edge of the scrollview, cause the scrollview to move one page in that direction (by setting the contentOffset to move in that direction according to the bounds of the scrollview). When that even occurs, move the object slightly out of the "hot zone" at the edge of the scrollview so that the user is forced to explicitly express that they want to move another page, or something along those lines - that is, since the design approach depends on this "paging events" you need to implement some sort of gestural system for the user to keep paging.
I suppose you could use a timer in that same situation, so that if the user maintains the position and touch for another second, you would page again.

Resources