UITableView and UIGestureRecogniser - iphone

I have a UITableView with normal vertical scrolling.
I want to add a UISwipeGestureRecnogiser to it (or somewhere connected in the view hierarchy).
I've done this, but the vertical tolerance on my gesture recogniser is pretty small. So I have to get my horizontal swipe pretty straight, otherwise the UITableView takes over and scrolls vertically. This is pretty annoying for the user.
Has anyone got any suggestions on how to better handle this? Maybe putting a UIView on top of my table view that handles the gesture, but if it fails - somehow pass the event to my table View.....

I ended creating my own gesture recogniser - following the example from the event handling guide for iOS.
I had more control over vertical tolerance using the old touchesMove and touchesBegan.
It still wasn't perfect, but it was a lot better and after testing on a few people, I could see there the swiping was less error prone.

Related

UIScrollView - how to get rid of delay before scrolling?

I'm using a UIScrollView to display a custom UIView. When the user drags a finger across the UIScrollView, there is a noticeable delay before the display begins updating. If the user keeps touching the screen, the UIScrollView becomes very responsive after a short time. Subsequent attempts to scroll result in the same initial delay, followed by high responsiveness. This delay seriously affects the usability of the view and I would like to get rid of it.
In a test project I have written to try to get to the bottom of this issue, I have only been able to partially replicate the behaviour. The first time that the user scrolls is exactly the same - however any subsequent attempts to scroll are responsive straight away.
I have tried both setting delaysContentTouches = NO and subclassing UIScrollView so that touchesShouldBegin returns NO as suggested in multiple places online, but neither has worked.
I'm using MonoTouch on iOS 4.3, but Objective-C answers are fine. I would post code to help illustrate the issue, but since I have been unable to narrow down the problem this would be well over 1000 lines. Hopefully this is enough info to get a solution.
Does anyone know what might be causing this delay, and how I can get rid of it?
Some general suggestions for improving scrolling performance.
Have your scrolling views rasterize offscreen:
myView.layer.shouldRasterize = YES;
Set that property for each sub-view on the scrollview - do not set it for the children of those sub-views or you just eat up memory that way.
If your scrolling views do not need compositing, make sure you turn that blending off:
myView.opaque = YES;
Test using the simulator by leveraging these two features that appear on the Debug menu of the iOS Simulator:
Color Off-screen Rendered
Color Blended Layers
If that doesn't address your problem, and you have implemented UIScrollViewDelegate, double-check to make sure you are not doing anything time consuming in those methods - for example, based on your description, you might be doing something in scrollViewDidScroll, scrollViewWillBeginDragging, or scrollViewWillBeginZooming and if you are, optimize that so it happens before scrolling even begins. Also, make sure you're not doing anything in touchesBegan.
I suspect what is happening is there is some kind of interaction enabled in the content of your scroll view.
The system does not know if the initial touch down is going to be a tap on one of the subviews or a drag on the scroll view, therefore is causing a delay while it waits to see if you are going to lift your finger.
What are the subviews of the UIScroll view?
As an experiment set all the subviews of the UIScrollView to have userInteractionEnabled = NO, this will not be what you want, but its just a test. Is should scroll fine after this, otherwise I am wrong.

Recreate UIPickerView with just one row showing

I need a "PickerView", that behaves like a normal UIPickerView, but only shows one row of data and has a custom design.
Something like you see in the image, showing the transition from subview 1 to subview 2. After the user lifts his finger and after the scrolling stops, only one subview will be shown:
IMAGE
So basically a scrollview which:
is endless in both, positive and negative directions by showing the same entries over and over
uses paging across several subviews
only shows one subview when not scrolling, and no more than two subviews when scrolling.
I can get a endless scrollview to work, but not with paging enabled. Paging will always limit my scrolling to the next subview.
So I'm thinking about creating my own UIView subclass which custom scrolling behaviour to mimic a UIPickerView. But before doing so, I wanted to get some opinions about the idea in general. Is creating a custom UIView the right way to go? Anyone has some experience with the expected performace? (There will be timers to handle the scrolling algorithm, which has to be recreated of course... :)
Another approach would be to subclass UIScrolView and implement the paging myself. I know when the scrollView starts decelerating
, so maybe there is a way to overwrite the contentOffset to have it scroll into the right position...?!
Any help is appreciated! Thanks!
Here is a great custom component, which seems to be able to do everything you need:
http://dev.doukasd.com/2011/04/infinite-scrolling-dial-control-for-ios/
It's not endless, but rather a modified UITableView with a huge number of cells.
Would it be feasible to just use a UIPickerView, but clipped to the middle row? You could turn off showsSelectionIndicator to remove the overlay and have the delegate pass back custom row views.

Nested UITableViews: a way to scroll both the outer vertical UITableView and a child horizontal UITableView at the same time?

When you're working with an atypical nested UITableViews setup - where you have an outer vertical UITableView that hosts 90° rotated UITableViews (see: Looking for a UI library to present Data horizontaly in iOS ):
is there a way to make iOS process vertical and horizontal touches at the same time?
I found that iOS is very clever in processing touches:
horizontal touches make the relevant horizontal UITableView scroll, while a vertical swipe makes the outer UITableView scroll. Perfect.
Only, I'd love to be able to move my finger diagonally and see the outer UITableView and the inner UITableView scroll at the same time.
I tried a few approaches (playing with canCancelContentTouches, delaysContentTouches, and touch messages) but I haven't found a way to make this happen.
EDIT:
Here's a XCode4 project that shows this behavior: http://marcanton.io/other/stackoverflow/nestedtableviews.zip
EDIT:
I submitted this issue to Apple Developer Technical Support, here's their reply:
Thank you for writing to Apple
Worldwide Developer Technical Support.
I am responding to your inquiry
concerning touch events in embedded
UITableViews.
Typically this is an approach that is
not recommended. The issue is that
UITableView inherits from UIScrollView
and as stated in the documentation for
UIScrollView:
"Important: You should not embed
UIWebView or UITableView objects in
UIScrollView objects. If you do so,
unexpected behavior can result because
touch events for the two objects can
be mixed up and wrongly handled."
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIScrollView_Class/Reference/UIScrollView.html%23//apple_ref/occ/cl/UIScrollView
So that this time, there is not a
workaround for getting both to scroll
at the same time.
I recommend that you file an
enhancement request at
http://developer.apple.com/bugreporter/
detailing what you would like to see
us add in a future release.
Still, I think that there has to be a way to enable this functionality, although I understand that this is not recommended. In fact, Apple does not even recommend hosting UITableViews inside another UITableView, but with the exception made above, it works quite beautifully.
I'll keep this question updated with our collective findings.
EDIT: There actually is a way, detailed here: http://marcanton.io/blog/nested-orthogonal-tableviews/
This would have to be a custom mirroring of intercepted touch events. Touch events follow the responder chain model, which means that if an object in the responder chain (the top most (outermost) view) cannot handle the event or action, it resends the message to the next responder (in this case the background UITableView in the chain). This is why you are seeing the horizontal events go to the horizontal UITableView and the vertical events going to the vertical UITableView. A diagonal touch event has applicable horizontal and vertical events, so the top-most view (the outer vertical UITableView) can respond to the vertical touches and swallows the event.
If you think about it, all vertical touches likely have a little bit of horizontal events (think about when you flick your finger), so there is likely some work done in the background to determine how to interpret the touch event (either as a vertical or horizontal).
I found this tread on passing events down to the next object in the responder chain. You might want to give this a try as a partial solution to your puzzle. The rest is to figure out how to capture the horizontal touch events and pass them along to the next responder.
Interesting, I haven't played around with this kind of setup yet, but I would try to intercept touch events on the nested UITableViews and delegate any vertical movement to the outer UITableView - and vice-versa.

Swipe to change UIViewContent

Hej folks,
I got an UIView in my application and want to implement kind of a swipe gesture. I know how I detect this gesture (touchesBegan: and touchesEnded: for example is x coordinates are distanced more than 100 pixels or something else) but I really don´t now how to animate my needs. In fact my UIView will contain subviews which are 9 UIButtons. On swipe I want to change the set of buttons programatically...any solutions out there? Primarily need the animation!
EDIT: I thought about programatically moving the buttons off-screen to the left and at the same time move the new ones on-screen from the right side. But it seems I don't really know how to realize this...isn't it too much leaking at the same time? Please give me a hint!
It's seem that you want to recreate somethings like the springboard but with button instead of icon.
I can suggest you to use UIScrollView.
why you don't load just a new view with the other button set in your window after the swipe gesture was detected?

iPhone: scroll view with arbitrary page/"settling" boundaries?

I'm trying to figure out if I can get what I want out of UIScrollView through some trickery or whether I need to roll my own scroll view:
I have a series of items in row that I want to scroll through. One item should always be centered in the view, but other items should be visible to either side. In other words, I want normal scrolling and edge bouncing, but I want the deceleration when the user ends a touch to naturally settle at some specified stop point. (Actually now that I think of it, this behavior is similar to coverflow in this respect.)
I know UIScrollView doesn't do this out of the box, but does anyone have suggestions for how it might be made to do this, or if anyone's spotted any code that accomplishes something similar (I'm loathe to reimplement all the math for deceleration and edge bounce)
Thanks!
There is not a whole lot of trickery to this. Just use an UIScrollView with paging enabled. Make it the size of one of your items, and locate it where you want that item to appear. Next, disable the "Clip Subviews" option on the scroll view (either in IB, or programmatically), and you are all set.