Saturday, June 25, 2011

Question: Differences in handling touch event between UIView and UIImageView?

I was studying about the "touch" events on iOS4 and looking at some examples from various areas, including books and net. Have a few little projects listed below.

Project 1

This code below is from chapter 8 of iPhone Developer's cookbook 2nd Edition by Erica Sadun. I quite like Erica's style of putting everything in one single "main.m" file, may be not suitable for bigger projects but this is definitely less confusing for beginners like me. You can see it uses a "UIImageView" class called "DragView" to handle the touch events of each flower images. You can freely drag each individual flower images around. (Note: there's a NIB file required, please see link to download source code far below).


/*
 Erica Sadun, http://ericasadun.com
 iPhone Developer's Cookbook, 3.0 Edition
 BSD License, Use at your own risk
 */

#import <UIKit/UIKit.h>

#define COOKBOOK_PURPLE_COLOR [UIColor colorWithRed:0.20392f green:0.19607f blue:0.61176f alpha:1.0f]

@interface DragView : UIImageView
{
CGPoint startLocation;
}
@end

@implementation DragView
- (id) initWithImage: (UIImage *) anImage
{
if (self = [super initWithImage:anImage])
self.userInteractionEnabled = YES;
return self;
}

- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
// Calculate and store offset, and pop view into front if needed
CGPoint pt = [[touches anyObject] locationInView:self];
startLocation = pt;
[[self superview] bringSubviewToFront:self];
}

- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
// Calculate offset
CGPoint pt = [[touches anyObject] locationInView:self];
float dx = pt.x - startLocation.x;
float dy = pt.y - startLocation.y;
CGPoint newcenter = CGPointMake(self.center.x + dx, self.center.y + dy);

// Set new location
self.center = newcenter;
}
@end


@interface TestBedViewController : UIViewController
@end

@implementation TestBedViewController
#define MAXFLOWERS 12

CGPoint randomPoint() 
{
int half = 32; // half of flower size
int freesize = 240 - 2 * half; // inner area
return CGPointMake(random() % freesize + half, random() % freesize + half);
}

- (void) viewDidLoad
{
self.navigationController.navigationBar.tintColor = COOKBOOK_PURPLE_COLOR;
srandom(time(0));
// Add the flowers to random points on the screen
for (int i = 0; i < MAXFLOWERS; i++)
{
NSString *whichFlower = [[NSArray arrayWithObjects:@"blueFlower.png", @"pinkFlower.png", @"orangeFlower.png", nil] objectAtIndex:(random() % 3)];
DragView *dragger = [[DragView alloc] initWithImage:[UIImage imageNamed:whichFlower]];
dragger.center = randomPoint();
[self.view addSubview:dragger];
[dragger release];
}

}
@end

@interface TestBedAppDelegate : NSObject <UIApplicationDelegate>
@end

@implementation TestBedAppDelegate
- (void)applicationDidFinishLaunching:(UIApplication *)application {
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:[[TestBedViewController alloc] init]];
[window addSubview:nav.view];
[window makeKeyAndVisible];
}
@end

int main(int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, @"TestBedAppDelegate");
[pool release];
return retVal;
}






Project 2


Then based on Chapter 7 example code from the iPhone Application Development for iOS4 Visual QuickStart guide book, I created this little NIB-less project with only 1 file: "main.m" which has 3 boxes that you can drag around.

Compared with the previous one, you can see it's using UIView instead of UIImageView. The "touchesMoved" method is also cleaner as you don't need to calculate the offset as the UIImageView ones above.





#import <UIKit/UIKit.h>

@interface TestBedViewController : UIViewController
{
UIView *redBox;
UIView *blueBox;
UIView *greenBox;
}
@end

@implementation TestBedViewController

- (void)loadView {
    
self.view=[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
self.view.backgroundColor=[UIColor whiteColor];
    
float boxSize = 100.0;
CGRect redBoxRect = CGRectMake(0,180,boxSize,boxSize);
redBox = [[UIView alloc] initWithFrame:redBoxRect];
redBox.backgroundColor = [UIColor redColor];
    
CGRect blueBoxRect = CGRectMake(110,180,boxSize,boxSize);
blueBox = [[UIView alloc] initWithFrame:blueBoxRect];
blueBox.backgroundColor = [UIColor blueColor];
    
CGRect greenBoxRect = CGRectMake(220,180,boxSize,boxSize);
greenBox = [[UIView alloc] initWithFrame:greenBoxRect];
greenBox.backgroundColor = [UIColor greenColor];
[self.view addSubview:redBox];
[self.view addSubview:blueBox];
[self.view addSubview:greenBox];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    
UITouch *touch = [[event allTouches] anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
if (touch.view != self.view)
[touch view].center = currentPoint;
    
}
- (void)dealloc {
[redBox release];
redBox = nil;
[blueBox release];
blueBox = nil;
    
[greenBox release];
greenBox = nil;
    
[super dealloc];
}

@end

@interface TestBedAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
    TestBedViewController *viewController;
}
@property (nonatomic, retain) UIWindow *window;
@property (nonatomic, retain) TestBedViewController *viewController;

@end

@implementation TestBedAppDelegate

@synthesize window;
@synthesize viewController;

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];   
self.viewController = [TestBedViewController alloc];
[self.window addSubview:self.viewController.view];
    [self.window makeKeyAndVisible];
    
}

- (void)dealloc {
    [viewController release];
    [window release];
    [super dealloc];
}
@end

int main(int argc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, @"TestBedAppDelegate");
[pool release];
return retVal;
}


My questions then are:
(1) Which is more useful/more frequently used/better?
(2) If I have mixed UIView and UIImageView objects, can I merged them into one method?
(3) I can think about scenarios which you create a little "sprite" which moves around the screen (don't know how to do that yet :-( ...) and user can touch and drag it around the screen. AS it's an image (??) then it should be using the UIImageView way, right?

Still too many unknowns at this early stage... So, iOS programming in indeed not that easy I guess...



The sample code from iPhone Developer's cookbook 2nd Edition is in chapter 8 of http://github.com/erica/iphone-3.0-cookbook-/tree.


The sample code from iPhone Application Development for iOS4 Visual QuickStart guide is in chapter 7 of http://objective-d.com/?page_id=160/.


0 comments:

Post a Comment