Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Beginning iOS5 Development.pdf
Скачиваний:
7
Добавлен:
09.05.2015
Размер:
15.6 Mб
Скачать

CHAPTER 17: Taps, Touches, and Gestures

613

key (while still holding down the option key). Pressing the shift key will lock the position of the two fingers relative to each other, and you can do swipes and other two-finger gestures. You won’t be able to do gestures that require three or more fingers, but you can do most two-finger gestures on the simulator using combinations of the option and shift keys.

If you’re able to run this program on your iPhone or iPod touch, see how many touches you can get to register at the same time. Try dragging with one finger, then two fingers, and then three. Try doubleand triple-tapping the screen, and see if you can get the tap count to go up by tapping with two fingers.

Play around with the TouchExplorer application until you feel comfortable with what’s happening and with the way that the four touch methods work. When you’re ready, continue on to see how to detect one of the most common gestures: the swipe.

The Swipes Application

The application we’re about to build does nothing more than detect swipes, both horizontal and vertical. If you swipe your finger across the screen from left to right, right to left, top to bottom, or bottom to top, the app will display a message across the top of the screen for a few seconds informing you that a swipe was detected (see Figure 17–3).

Figure 17–3. The Swipes application will detect both vertical and horizontal swipes.

www.it-ebooks.info

614

CHAPTER 17: Taps, Touches, and Gestures

Detecting swipes is relatively easy. We’re going to define a minimum gesture length in pixels, which is how far the user needs to swipe before the gesture counts as a swipe. We’ll also define a variance, which is how far from a straight line our user can veer and still have the gesture count as a horizontal or vertical swipe. A diagonal line generally won’t count as a swipe, but one that’s just a little off from horizontal or vertical will.

When the user touches the screen, we’ll save the location of the first touch in a variable. Then we’ll check as the user’s finger moves across the screen to see if it reaches a point where it has gone far enough and straight enough to count as a swipe. Let’s build it.

Create a new project in Xcode using the Single View Application template and a Device Family of iPhone, and name the project Swipes.

Single-click BIDViewController.h, and add the following code:

#import <UIKit/UIKit.h>

@interface BIDViewController : UIViewController

@property (weak, nonatomic) IBOutlet UILabel *label; @property CGPoint gestureStartPoint;

@end

We start by declaring an outlet for our one label and a variable to hold the first spot the user touches. Then we declare a method that will be used to erase the text after a few seconds.

Select BIDViewController.xib to open it for editing. Make sure that the view is set so

User Interaction Enabled and Multiple Touch are both checked using the attributes inspector, and drag a Label from the library and drop it on the View window. Set up the label so it takes the entire width of the view from blue guideline to blue guideline, and its alignment is centered. Feel free to play with the text attributes to make the label easier to read. Control-drag from the File’s Owner icon to the label, and connect it to the label outlet. Finally, double-click the label and delete its text.

Save your nib. Then return to Xcode, select BIDViewController.m, and add the following code at the top:

#import "BIDViewController.h"

#define

kMinimumGestureLength

25

#define

kMaximumVariance

5

@implementation BIDViewController

@synthesize label;

@synthesize gestureStartPoint;

- (void)eraseText { label.text = @"";

}

.

.

.

www.it-ebooks.info

CHAPTER 17: Taps, Touches, and Gestures

615

We start by defining a minimum gesture length of 25 pixels and a variance of 5. If the user were doing a horizontal swipe, the gesture could end up 5 pixels above or below the starting vertical position and still count as a swipe as long as the user moved 25 pixels horizontally. In a real application, you would probably need to play with these numbers a bit to find what works best for your application.

Insert the following lines of code into the existing viewDidUnload method:

- (void)viewDidUnload

{

[super viewDidUnload];

//Release any retained subviews of the main view.

//e.g. self.myOutlet = nil;

self.label = nil;

}

And add the following methods at the bottom of the class:

#pragma mark -

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject];

gestureStartPoint = [touch locationInView:self.view];

}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject];

CGPoint currentPosition = [touch locationInView:self.view];

CGFloat deltaX = fabsf(gestureStartPoint.x - currentPosition.x);

CGFloat deltaY = fabsf(gestureStartPoint.y - currentPosition.y);

if (deltaX >= kMinimumGestureLength && deltaY <= kMaximumVariance) { label.text = @"Horizontal swipe detected";

[self performSelector:@selector(eraseText) withObject:nil afterDelay:2];

} else if (deltaY >= kMinimumGestureLength && deltaX <= kMaximumVariance){

label.text = @"Vertical swipe detected";

[self performSelector:@selector(eraseText) withObject:nil afterDelay:2];

}

}

@end

Let’s start with the touchesBegan:withEvent: method. All we do there is grab any touch from the touches set and store its point. We’re primarily interested in single-finger swipes right now, so we don’t worry about how many touches there are; we just grab one of them.

UITouch *touch = [touches anyObject]; gestureStartPoint = [touch locationInView:self.view];

www.it-ebooks.info

616

CHAPTER 17: Taps, Touches, and Gestures

In the next method, touchesMoved:withEvent:, we do the real work. First, we get the current position of the user’s finger:

UITouch *touch = [touches anyObject];

CGPoint currentPosition = [touch locationInView:self.view];

After that, we calculate how far the user’s finger has moved both horizontally and vertically from its starting position. The function fabsf() is from the standard C math library that returns the absolute value of a float. This allows us to subtract one from the other without needing to worry about which is the higher value:

CGFloat deltaX = fabsf(gestureStartPoint.x - currentPosition.x);

CGFloat deltaY = fabsf(gestureStartPoint.y - currentPosition.y);

Once we have the two deltas, we check to see if the user has moved far enough in one direction without having moved too far in the other to constitute a swipe. If that’s true, we set the label’s text to indicate whether a horizontal or vertical swipe was detected.

We also use performSelector:withObject:afterDelay:to erase the text after it has been on the screen for 2 seconds. That way, the user can practice multiple swipes without needing to worry if the label is referring to an earlier attempt or the most recent one.

if (deltaX >= kMinimumGestureLength && deltaY <= kMaximumVariance) { label.text = @"Horizontal swipe detected";

[self performSelector:@selector(eraseText) withObject:nil afterDelay:2];

} else if (deltaY >= kMinimumGestureLength && deltaX <= kMaximumVariance){

label.text = @"Vertical swipe detected"; [self performSelector:@selector(eraseText)

withObject:nil afterDelay:2];

}

Go ahead and compile and run the application. If you find yourself clicking and dragging with no visible results, be patient. Click and drag straight down or straight across until you get the hang of swiping.

Automatic Gesture Recognition

The procedure we just used for detecting a swipe wasn’t too bad. All the complexity is in the touchesMoved:withEvent: method, and even that wasn’t all that complicated. But there’s an even easier way to do this. iOS includes a class called UIGestureRecognizer, which eliminates the need for watching all the events to see how fingers are moving. You don’t use UIGestureRecognizer directly, but instead create an instance of one of its subclasses, each of which is designed to look for a particular type of gesture, such as a swipe, pinch, double-tap, triple-tap, and so on.

Let’s see how to modify the Swipes app to use a gesture recognizer instead of our hand-rolled procedure. As always, you might want to make a copy of your Swipes project folder and start from there.

www.it-ebooks.info

CHAPTER 17: Taps, Touches, and Gestures

617

Start off by selecting BIDViewController.m, and deleting both the touchesBegan:withEvent: and touchesMoved:withEvent: methods. That’s right, you won’t be needing them. Then add a couple of new methods in their place:

- (void)reportHorizontalSwipe:(UIGestureRecognizer *)recognizer { label.text = @"Horizontal swipe detected";

[self performSelector:@selector(eraseText) withObject:nil afterDelay:2];

}

- (void)reportVerticalSwipe:(UIGestureRecognizer *)recognizer { label.text = @"Vertical swipe detected";

[self performSelector:@selector(eraseText) withObject:nil afterDelay:2];

}

These methods implement the actual “functionality” (if you can call it that) that’s brought about by the swipe gestures, just as the touchesMoved:withEvent: did previously. Now, add the new code shown here to the viewDidLoad method:

- (void)viewDidLoad

{

[super viewDidLoad];

// Do any additional setup after loading the view, typically from a nib.

UISwipeGestureRecognizer *vertical = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(reportVerticalSwipe:)];

vertical.direction = UISwipeGestureRecognizerDirectionUp| UISwipeGestureRecognizerDirectionDown;

[self.view addGestureRecognizer:vertical];

UISwipeGestureRecognizer *horizontal = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(reportHorizontalSwipe:)];

horizontal.direction = UISwipeGestureRecognizerDirectionLeft| UISwipeGestureRecognizerDirectionRight;

[self.view addGestureRecognizer:horizontal];

}

There you have it! To sanitize things even further, you can also delete the lines referring to gestureStartPoint from BIDViewController.h and BIDViewController.m as well (but leaving them there won’t harm anything). Thanks to UIGestureRecognizer, all we needed to do here was create and configure some gesture recognizers, and add them to our view. When the user interacts with the screen in a way that one of the recognizers recognizes, the action method we specified is called.

In terms of total lines of code, there’s not much difference between these two approaches for a simple case like this. But the code that uses gesture recognizers is undeniably simpler to understand and easier to write. You don’t need to give even a moment’s thought to the issue of calculating a finger’s movement over time, because that’s already done for you by the UISwipeGestureRecognizer.

www.it-ebooks.info

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]