iOS 7+ swipe back gesture conflict with stateChange animations - javascript

In short when moving from one state to another in an AngularJS application I use CSS animations to animate the view change. For example applying a fade or transform via the .ng-enter and .ng-leave classes.
But in iOS 7+ you can transition from one page to another by swiping your finger off the screen edge left or right and it does a back or forward action the same as clicking the back and forward buttons on the toolbar. However because the OS does its own animation back to the previous page in the history stack, and then AngularJS fires the state change after and then does the CSS animation, you get double animations and a flicker as the content you can already see is then animated back into view... How can we prevent this? As it's a really crappy looking user experience and looks like a bug to end users.
I thought about detecting iOS 7+ then disabling the animations. But I'd only want to disable the animations when doing the slide off the edge with the finger and not for actual clicks or the browser buttons. As far as I can tell there is no way to detect this. But the UX really suffers.
Has anyone had this issue before? Worked around it?

i think you will need to figure out where the swipe started from when a navigation event was triggered. might be as simple as detecting if there's a touch on the page when the event triggers - it implies the user is touching it at that very moment.. in that case, disable the css animation. in theory that's it but i never attempted nothing even close. :)

Related

jScrollPane on touch devices - drag button is in reverse

I've implemented jScrollPane and I'm having an issue on touch devices.
The example I'm using is http://jscrollpane.kelvinluck.com/drag_size.html where I have a vertical scroll using a circular button image for the scroll on the track. The class that's added to this is jspDrag.
On desktop, when you click and scroll the vertical button, it drags down and the content scrolls up, which is natural in my eyes.
The issue I'm facing is on touch devices (check the example URL above in Chrome using iPhone/iPad emulation in dev. tools) where you can't actually drag the button down - you actually have to scroll it up for the content to scroll?!
Users are definitely not going to know this as it's a button rather than a content block that you're using as a control.
I'd like to be able to touch and drag the button down on touch devices, rather than up, to make the content scroll.
Has any one come across this issue and managed to solve it? I've searched SO and Google Groups with no luck.
Thanks.
Unfortunately jScrollPane seems to just work like this, with an annoying caveat, which is unfortunate - I really liked the plugin.
I came across http://manos.malihu.gr/jquery-custom-content-scroller/ which functions the way it should and runs super smooth on touch devices.

Disable bounce back in Mobile Safari Webview using css/js?

I've been trying to find the answer to this question without success.
I am programming some webpages for a webview in MobileSafari. I do not have access to the Objective-C to disable the functionality that way.
I'd like to provide a smooth scrolling page experience, or a normal scrolling page experience, but not allow the user to drag past the top or bottom of the page, and subsequently cause it to show whitespace and "bounce" back.
Is there a good solution for this?
Thank you.
Have a look at iScroll 4 (and the demo). It is a framework used for content scrolling in a fixed width/height area. But it should also solve your problem because you can disable the bounce effect.
How to disable the bounce effect is explained under "PASSING PARAMETERS TO THE ISCROLL".
These two parameters should be interesting:
bounce, enable/disable bouncing outside of the boundaries. Default: true.
fixedScrollbar, on iOS the scrollbar shrinks when you drag over the scroller boundaries. Setting this to true prevents the scrollbar to move outside the visible area (as per Android). Default: true on Android, false on iOS.
UPDATE
I just stumbled upon Nicescroll a jQuery plugin that replaces the browser scrolling.
It doesn't bounce back by default but you can turn it on or off.
It seems that scroller scripts like:
iScroll 4
FT Scroller
Zynga Scroller
don't work with every DOM structure. Or at least not with the more complex ones.
I am not sure why but I could not apply them to your code or some other random webpages.
But I created a little javascript helper that disables the bounce effect and emulates the scroll animation.
noBounce.js
Here you can find an example.
It is really easy to import because it has no dependencies. Just add to your HTML:
<script src="js/noBounce.js" type="text/javascript"></script>
And run somewhere in your javascript:
noBounce.init({preventDefault: false, animate: true});
You need to set preventDefault: false. Otherwise your buttons would not work anymore.

Scroll event on Android Browser not firing. Need workaround

I've created a website with a parallax street scene. See here for an archived version.
It works just fine on all major desktop browsers, and Safari Mobile. It works fine in Mobile Firefox and Chrome for Android Beta also. However the default Android browser has issues with the scroll event. Let me be clear. Scrolling is not the issue. The div scrolls as required. The scroll event doesn't fire. This issue I experience on Honeycomb as well as ICS.
I'm not concerned about other mobile browsers because for mobile screen sizes one usually does not see the parallax scene; mediaqueries and conditional JavaScript loading take care of that. Responsive design and all that jazz.
Basically, I've written a parallise() jQuery plugin that positions each image based on its position and 'depth'. This function is bound to the scroll event.
On Android Browser, this event only fires at the start of the next touch, instead of continuously.
OK, so I thought that perhaps if I bound the function to touchstart, touchmove, and touchend events I would solve my issue. No cigar. Other touch events are also bugged. Applying the suggested workaround causes the events to fire, but as I have to e.preventDefault(), scrolling (the whole point of the exercise) is disabled.
What if I just poll the position of the stage div relative to the window div? Turns out that the position information is only updated at the start of the next touch.
I am at the end of my tether. Any help would be much appreciated.
Even if the touch events worked correctly on the bugged versions of Android, and you were then effectively able to track the native scroll position during a drag, this would be prone to error. For example, it wouldn't account for the momentum animation which happens after the touching has finished.
iOS and Android make sacrifices to improve the performance of scrolling. On both platforms, it's not possible to get the accurate scroll position until the scroll has completed. The scroll event (on the <body>) doesn't fire until the momentum animation is finished. So while your original question is about scroll events on an overflowing <div>, fixing this might not be totally helpful for you anyway.
If you want an animation to update in time with the scroll, then you need to perform the scroll programatically rather than using the browser's native scroll. The best library to do this is iScroll. You can achieve parallax effects very easily as seen in this demo.
If you need more complex effects (the walking character, in your example), you can opt for the "probe" version of iScroll which allows pixel-perfect polling of scroll position in return for reduced performance.
However, there are many downsides to using iScroll:
You may need to change your markup and styling
It is unnecessary overhead for desktop browsers, but due to markup changes may be difficult to use only as a fallback
The scrolling will not feel perfect - on iOS, with its usually excellent scrolling performance - the slight difference in momentum calculation can feel jarring. On Android, the scrolling can become more laggy than usual.
Swipe shim that doesn't need preventdefault on touchstart: https://github.com/TNT-RoX/android-swipe-shim

Browser scrolling versus in page scrolling

I'm using OSX Lion and Chrome which allows you to swipe back and forth to go back/ forward in the browser. However I'm finding it often interferes with scrolling within a page. I have horizontal scroll bars within the website i'm creating and swiping back and forth within them often causes the browser to move forward/ backward in my browse history - definitely not the behaviour i want.
I'm creating my horizontal scroll boxes very simply with html/css and the overflow property. I'm wondering if the correct approach is to use javascript to detect a scroll event, and prevent the default behaviour. It just seems like a more complicated approach to something that should be simple.
http://cubiq.org/iscroll
http://www.azoffdesign.com/plugins/js/overscroll
http://uxebu.com/blog/2010/09/15/touchscroll-0-2-first-alpha-available/
http://plugins.jquery.com/project/jScrollTouch
Tried or seen any of these, you can just disable the browser scrollbars and use these instead..

Javascript and rendering pauses and stays paused on scroll in the android browser

I've found some wierd behaviour related to scrolling and rendering and javascript.
How to make it happen:
On any webpage that is long enough to scroll on. Start to scroll pretty fast (fling the page). then release the touch.
Now while the page is still scrolling because of the momentum. Tap the screen to stop the scroll.
This make the browser enter a wierd mode.
On the nexus one it behaves like this:
The updating of what's shown on the screen stops, you can still click on links and the go to where they are supposed to but what's shown on the screen stays the same.
If you then scroll the screen a bit the update of the screen kicks in again and what you you where suppsed to see all the time is shown.
On all phones with HTC Sense I've tried (Hero, Desire, Legend) this happens:
The updating of the screen is stopped just like on the nexus one, but also the execution of any javascript is stopped.
If you click on a link that takes you to another page however things return to normal again.
The way I tested this was I created a page like this:
http://pastebin.ca/1881620
The changeColor function simply changed the background color of 'container' to a few different colors.
So before the error what happens is that when you click any link the color changes.
after the error this happens:
Nexus one:
when you click on the links nothing happens (except the "orange link selected rounded corner box thing" is shown as if the link is clicked). Then when you scroll abit.
You can see the color has changed (and equal amount of times to the number of times I clicked the link).
On Sense:
The links take me to google.com
Has anyone else noticed this problem? Is there anyway to work around it?
Thanks.
You could try using a plugin that manipulates the browser's scrolling process, such as iScroll4.
iScroll4 let us do some pretty cool stuff (like fixed headers/footers), but it did have some performance problems in some of the older/crappier Android phones...
I can't guarantee that it'd fix your problem, and it'd be kind of a last resort, but it might be worth trying if you're interested in iScroll's other features, or if you've hit a dead end with your bug, and it's a show-stopper for your app.

Categories