UIScrollView and Multi-Touch zooming

Let's say you have a nice, big, hi-res photo you want to show to your user on the iPhone. No doubt you want to let your user zoom in to see details of the photo and scroll around, just like the built-in Photos.app.
Most of you would probably come up with something akin to the following structure using Interface Builder:

UIView

|
–UIScrollView
|
–UIImageView
If you are coding the UI by hand, the top level UIView would probably be omitted. This may or may not be relevant to the issue you'll be encountering. See my note at the end.
Now that the view structure is setup, you will probably discover that double tapping to zoom in/out is not implemented out of the box by Apple (surprise!).
"Ok", you thought to yourself, "I just need to implement the touch events in the controller and it will all work."
So you go ahead and added touch event code to the controller class, probably something like this:

– (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

UITouch *touch = [touches anyObject];

NSInteger tapCount = [touch tapCount];

if (tapCount == 2) {

[scrollView_ setZoomScale:zoomScale animated:YES];

}

}

When you run the code, you'll find that the touchesEnded method never get called!
Turns out this is actually by design from Apple. touchesEnded and other touch event methods are no-op methods by default. My guess is that this is probably a performance related design decision.
Regardless of why, here is what you need to do to 'fix' this. First, create a new class that inherits from UIScrollView. Then in this new subclass, implements the touch event method that you want to use and passes on the event to the next responder in the list. Like this:

– (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

{

[super touchesEnded:touches withEvent:event];

[self.nextResponder touchesEnded:touches withEvent:event];

}

This will pass on the touch event to the parent UIView in the hierarchy and thus calls the touch method in the controller.
Problem solved!
(One thing I haven't tried is to removed the top level UIView from the hierarchy, and link the UIScrollView to the view outlet in the controller. My hunch is that this may eliminate the need to subclass UIScrollView.)

Read and post comments

|

Send to a friend

Advertisements

Inoperative Cancel button in UIActionSheet

Let’s say you want to use UIActionSheet to show three buttons to the user with a cancel buttons in a UIView, which itself is managed by a UITabBarController:

Your code would probably look like this:

UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@”Action Title” delegate:self cancelButtonTitle:@”Cancel” destructiveButtonTitle:nil otherButtonTitles:@”Option 1″@”Option 2″@”Option 3″nil];

actionSheet.actionSheetStyle = UIActionSheetStyleDefault;

[actionSheet showInView:self.view];

[actionSheet release];

And you’ll also probably find that all the 3 option buttons works, but the Cancel one doesn’t!
It is because the UIView which the UIAlertSheet belongs to is behind the UITabBarController, and the TabBar’s hitTest method gets called before the UIAlertSheet’s.
To fix this, it is just a simple matter of using the view from the UITabBarController in the showInView method. Like this:

UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@”Action Title” delegate:self cancelButtonTitle:@”Cancel” destructiveButtonTitle:nil otherButtonTitles:@”Option 1″@”Option 2″@”Option 3″nil];

actionSheet.actionSheetStyle = UIActionSheetStyleDefault;

UIApplicationDelegate *appDelegate = (UIApplicationDelegate *)[[UIApplication sharedApplication] delegate];

UITabBarController *tabBarController = appDelegate.tabBarController;

[actionSheet showInView:tabBarController.view];

[actionSheet release];

iPhone development talk in Philly

Last Tuesday I travelled down to Philadelphia to speak at the Philly ALT.NET meeting. Brian Donahue, the group organiser, invited me to talk about my experience of developing iPhone application from a .NET perspective. Over 20 people turned up and I was surprised that most of them already owned an iPhone and a Mac (remember this is a .NET group afterall).

I began with listing out the things require for iPhone development (hardware and software), then moved onto comparing Objective-C/Xcode with C#/Visual Studio. I showed a quick code demo to illustrate my points on language and environment differences. Finally I talked about the good, bad, and ugly things I feel about iPhone development up to this point.

This is the first time I gave this talk and feel the Philly audience got good value from my experience. The event was hosted at Drexel University campus and a few of the iSchool students were in the audience. One of them even came up to me afterward and asked whether I’d be interested in doing more talks on iPhone development for iSchool!

Here are the slides I presented:

 

 

 

One of the attendee also took some videos and I’ll post them as soon as I receive the link.

 

NY Alt.NET April meeting

Last Wednesday's NY Alt.NET meeting topic was Continuous Integration. Being a ThoughtWorker and had worked on build and deployment project at an enterprise level, it fells naturally to me to not only prepare the presentation material but also present it.

I was a bit nervous about the presentation, as it has been a while (over a year) since I last stood up in a group setting and presented. But I think it went fine, though of course there are always improvement to be made.
I also have the honour of speaking at Philly Alt.NET meeting on May 5th. The topic is on iPhone development for .NET developer. It is something completely different and still pretty new to me.

Read and post comments

|

Send to a friend

UX disaster

The elevator company in the ThoughWorks office building (e.g. Viacom building @ 44th St) needs an user experience designer. Who in the right mind would put different door controls on each side of the elevator?

User Experience disaster - Left hand side controlsUser Experience disaster - Right hand side controls

Read and post comments

|

Send to a friend