UIScrollView event handling - iphone

I'm trying to make my own custom UIScrollView for some reason. The question is, is it possible to exactly mimic the event handling behavior of UIScrollView including 'delayed content touches' and 'cancellable content touches'? That is, the custom scroll view should delay handling the event until it can determine if scrolling is the intent, and it should also be able to cancel its subviews' touches later. The problem is as follows:
1) hitTest: should return immediately so I can't delay the determination of the touch owner.
2) We can't cancel a touch event later programmatically. There's no such api.
3) I tried to override the sendEvent: method, but it didn't help. Having to call [super sendEvent:] will send events to unintended views. Moreover, hit test has been already done when sendEvent: was called and we can't alter the value of UITouch.view later.
So again the question is, is it possible to make a custom UIScrollView including it's touch handling behavior without using UIScrollView?
Thanks in advance!

One thing to keep in mind is that the gestureRecognizers (Pan and Zoom) that are used for regular UIScrollViews are private properties until iOS 5.0 comes out. I suppose when they are public you could transfer them to your own scroll view.

Related

Slide of UIScrollView

I made a slideview using a uiview and detecting touches to move pages. This slideview is almost like this, except that I made it works like a UITableView.
Now I'm using this to uivews with uiscrollviews. The problem is, "how to distribute touch events to scrollview or slideview?". I had the logic to do. Basically, the uiscrollviews are vertical and slideview is horizontal.
I tried hitTest to keep the touchBegan,Moved,Ended in slideview. When I get a touch movement horizontally, I keep to slideview, when vertically, distribute to uiscrollview. But I cannot figure out how to distribute events to uiscrollview.
Calling [scrollView touchesBegan:touches withEvent:event] doesn't work. I supposed uiscrollview has a different way to work.
If you don't find a clue to your answer, probably, you're wrong.
UIScrollView uses a own way to get touchesBegan, Moved and Ended. Way that I don't, but it's mean if you override touchesBegan to make UIScrollView stops to work, you won't get it. Using hitTest in superview of scroll, you can get the touches before UIScrollView but you can't change the touches target while touches is happening.
After all, there is one way to solve this, ashly, three ways.
1- Simulate touches
I didn't test this, you'll know below. Events come from UIWindow and distributed to subview by - (void)sendEvent:(UIEvent *)event. We don't know how touches target is saved, and change this is completely out of question. But we can use the idea of override superview's hitTest to know what the user will do to make a 'WA' to change the target. To do this, simulate a event of touch ended. Supposed target will be reset. Simulate a event of touch begin again, and this time make sure to let hittest get scrollview.
You can find how simulate events here. The problem is, probably your app will be rejected due using private methods.
2- Make your own UIScrollView
This should be the best or the worst, depending what you want to do. I believe it's painful. And isn't what you want to do right now.
3- Surrender to 'Nest UIScrollView'
To make slideshow of pdf, hq, docs and books, it's the best and painless way. Put a UIScrollView inside another and let them reach an agreement of scrolling. http://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/UIScrollView_pg/NestedScrollViews/NestedScrollViews.html

backgroundView for a UITableViewCell that is being reordered?

I'm trying to change the background view for cells that the user starts to drag with the handle out on the right hand side.
Apparently the selectedBackground view is not used in this state, is there any other solution?
This seems to be a tough one. It doesn't seem as if Apple has provided a way to notify the developer that the user has started reordering a table view cell. So I think this is what you'd have to do:
Subclass UITableViewCell.
Override the touchesBegan et al methods (this might get you started: http://devblog.wm-innovations.com/2010/03/30/custom-swipe-uitableviewcell/)
If you detect a "drag" touch event and the cell's showsReorderControl property (see http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewCell_Class/Reference/Reference.html) returns YES, swap out the backgroundView, remembering the previous one.
When the touch event ends, restore the old view.
Realize that it's not as easy as above 4 steps.
Custom touch handling inside a tableview is possible but hard. You might have to temporarily disable touch events in the UITableView (climbing up the responder chain) to make this work.
I hope these pointers get you moving in the right direction, though.

Determining which view touch was in for all touches

I want to determine which view touches occurred in for the entire application, for the purpose of logging touches so that I can go through the logs later and determine what the user did. I know I could subclass UIView and override touchesBegan/Ended to log those, but I am using many instances of UIButton, UISlider, etc in Interface Builder so that wouldn't work unless I also subclassed those classes.
For determining the time since last touch (for an idle screen timeout method) I already have UIApplication subclasses and sendEvent: overridden. The only way I can see to do what I want is to iterate through the main window's subviews, calling touchesForView: on the UIEvent passed into sendEvent:, but I was wondering if there was a cleaner way to tell which view was touched (whether it's through the sendEvent: method or not). Thanks!
See if this will do what you want: Observing pinch multi-touch gestures in a UITableView

How to intercept touch events globally?

I have an view which is sometimes covered by some other views. However, if the user slides the finger across the screen, I want to slide that underlying view across the screen, too.
I could start making custom views for all those covering subviews and forward all kinds of touch events, but that's somewhat cumbersome. Maybe there's some kind of notification or another way that a UIView or UIControl subclass can be aware of touch events happening right now, no matter where they are.
In short: I need an UIView subclass or UIControl subclass which knows about any touch events happening on the entire screen. Or at least if tht's not possible, knowing about any touch events happening above itself in the same underlying superview.
Another description: There are 20 views, all reside inside the same superview. The first view is covered by 19 others. But if the user slides across the screen, that first view must slide too, so it must be aware of touch events.
Is there any better solution that making all 19 views forward touch events? (yes, all 19 views respond to touch events in this example)
Perhaps the hitTest:withEvent: method of UIView will help, it's helped me achieve what you are trying in the past.

Drag & sweep with Cocoa on iPhone

I'm about to start a new iPhone app that requires a certain functionality but I'm not sure if it's doable. I'm willing to research but first I just wanted to know if I should at least consider it or not.
I haven't seen this in an app before (which is my main concern, even though I haven't seen too many apps since I don't own an iPhone), but an example would be the iPhone shortcuts panels: you can hold on an app, and then drag it to another panel, sweeping while still dragging it. But this is the core app, is it possible to reproduce something similar within a normal app?
I only need to be sure it can be done before I start digging, I don't need code examples or anything, but if you have some exact resources that you consider helpful, that would be appreciated.
Thanks!
Yes. If you have your custom UIView subclass instance inside a UIScrollView, your view controller just needs to set the UIScrollView to delay content touches and not allow it to cancel touch events.
[scrollView setCanCancelContentTouches:NO];
[scrollView setDelaysContentTouches:YES];
When the user taps and holds in the custom view, the event goes to that custom view, which can process the touch events to drag an item around, but if the user quickly swipes, it scrolls the view.
The "panel" view that you're referring to appears to be a UIPageControl view — although, perhaps, the specific incarnation of this view that Apple uses for the iPhone's home page may be customized.
Instances of generic UIView views that you might touch-and-drag will receive touch events. By overriding methods in the view, these events can be processed and passed to the page control, in order to tell it to "sweep" between pages.
If I wanted to do what you're asking about, that's how I might approach it. It seems doable to me, in any case.
Start with this: Swip from one view to the next view
Try using a UIButton that tracks the time since the state of the button changed to "highlighted". You may need to do this in order to track the dragging and move the button around:
Observing pinch multi-touch gestures in a UITableView
Check to see if the button starts overlapping one side of the screen while being dragged. If s certain amount of time elapses since the button first started overlapping the edge and then manipulate the UIScrollView so that it switches to the next page on the corresponding side of the screen
You may need to use NSTimer to keep track of how long the button is held down, etc.
In any case there's no reason why this couldn't work.
If UIButton doesn't work then perhaps try a custom subclass of UIControl (which tracks the same touch down actions etc.). If that doesn't work then use the window event intercept thing to track everything.