iOS手势学习

来源:互联网 发布:金融it 编辑:程序博客网 时间:2024/05/20 20:18
1. UITouch  Move
实例:让视图跟着手指拖动而移动

UITouch的常见属性:
tapCount
touch.view 点击的视图
previousLocationInView
locationInView
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{

    UITouch *touch = [touches anyObject];
    
    CGPoint prePoint = [touch previousLocationInView:self.view];
    
    NSLog(@"上一次点击时的坐标:%@",NSStringFromCGPoint(prePoint));
    
    CGPoint currentPoint = [touch locationInView:self.view];
    
    NSLog(@"当前点击的坐标:%@",NSStringFromCGPoint(currentPoint));
    
    CGPoint pointDelt = CGPointMake(currentPoint.x-prePoint.x, currentPoint.y-prePoint.y);
    
    CGPoint center = CGPointMake(_myView.center.x+pointDelt.x, _myView.center.y+pointDelt.y);
    
    [_myView setCenter:center];
}


手势
基类UIGestureRecognizer
UITapGestureRecognizer        Tap 点击
UIPanGestureRecognizer           Pan (慢速滑动,拖移)
UILongPressGestureRecognizer LongPress (长按)
UIPinGestureRecognizer          Pinch (捏合,两手指往内或外拨动)
UIRotationGestureRecognizer  Rotation (旋转)
UISwipeGestureRecognizer       Swipe (快速滑动,轻扫)


2. UITapGestureRecognizer
点击:
numberOfTapsRequired // 点击次数
numberOfTouchesRequired // 多少个触摸点(手指)

3. UIPanGestureRecognizer
拖移
CGPoint offset = [pan translationInView:self.view];
CGPoint center = _imageView.center;
center.x += offset.x;
center.y += offset.y;
_imageView.center = center;
[pan setTranslation:CGPointZero inView:self.view];


4. UILongPressGestureRecognizer
长按
minimumPressDuration
- (void)longPress:(UILongPressGestureRecognizer *)longPress {
    NSLog(@"长按手势:");
    switch (longPress.state) {
        case UIGestureRecognizerStateBegan:
            NSLog(@"开始");
            break;
        case UIGestureRecognizerStateEnded:
            NSLog(@"结束");
            break;
        default:
            break;
    }
}

注意加了长按手势和拖移手势的冲突


5. UIPinGestureRecognizer
捏合
- (void)pinch:(UIPinchGestureRecognizer *)pinch {
    NSLog(@"pinch.scale: %f", pinch.scale);
    
    // 我们可以通过 transform 仿射变换 进行 放大 缩小
    _imageView.transform = CGAffineTransformScale(_imageView.transform, pinch.scale, pinch.scale);
    
    // 重置捏合手势的比例 每次都应该相对于当前的
    pinch.scale = 1;   // 下次相对比例应该从1 开始
}

加一个复位按钮
_imageView.transform = CGAffineTransformIdentity;

6. UIRotationGestureRecognizer
旋转
- (void)rotation:(UIRotationGestureRecognizer *)rotation {
    NSLog(@"rotation 弧度:%f", rotation.rotation);
    _imageView.transform = CGAffineTransformRotate(_imageView.transform, rotation.rotation);
    rotation.rotation = 0; // 重置 旋转的弧度 相对于当前的 从0 开始
}
注意加了旋转手势之后和捏合手势的冲突

代理方法
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer

轻扫
- (void)addSwipeGestureToImageView {
    UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe:)];
    swipe.direction = UISwipeGestureRecognizerDirectionDown;
    [_imageView addGestureRecognizer:swipe];
    [swipe release];
}
注意注释掉拖动手势(panGesture),以防止冲突。


手势的运用示例:



图片拉伸:
[image stretchableImageWithLeftCapWidth:5 topCapHeight:20];

————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
Touch begin move end motion(晃动手机)

————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
响应者链

查看UIKit类继承图
UIResponder

IOS中分为两类事件:触摸事件,和移动事件。最原始的事件处理方是touchesBegan:withEvent:,touchesMoved:withEvent:, touchesEnded:withEvent:, and touchesCancelled:withEvent:。无论任何时候手指只要触摸屏幕或是在屏幕上移动拖拽甚至离开屏幕都会导致一个UIEvent对象产生。
There are two general kinds of events: touch events and motion events. The primary event-handling methods for touches are touchesBegan:withEvent:, touchesMoved:withEvent:, touchesEnded:withEvent:, and touchesCancelled:withEvent:. The parameters of these methods associate 连接 touches with their events—€”especially touches that are new or have changed—€”and thus allow responder objects to track and handle the touches as the delivered events progress through the phases of a multi-touch sequence. Any time a finger touches the screen, is dragged on the screen, or lifts from the screen, a UIEvent object is generated. The event object contains UITouch objects for all fingers on the screen or just lifted from it.
在UIResponder中有一个非常重要的概念叫做Responder Chain,
是按照一定规则组织的响应、处理事件的一条链表。在了解UIResponder之前还得在了解一个概念Hit-Testing。在IOS中通常使用 hit-testing 去找到那个被触摸的视图。这个视图叫hit-test view,当IOS找到hit-test view后就把touch event交个那个视图来处理。
下面画个图来说明一下,当点击视图E时看一下hit-testing的工作过程。

1.确定该触摸事件发生在view A范围内,接下来测试view B以及view C。
2.检查发现事件不再view B范围内发生,接下来检查view C发现触摸事件发生在了view C中,所以检查 view D,view E。
3.最后发现事件发生在view E的范围内所以view E成为了hit-test view。
The hitTest:withEvent: method returns the hit test view for a given CGPoint and UIEvent. The hitTest:withEvent: method begins by calling the pointInside:withEvent: method on itself. If the point passed into hitTest:withEvent: is inside the bounds of the view, pointInside:withEvent: returns YES. Then, the method recursively calls hitTest:withEvent: on every subview that returns YES.

Responder Chain 是由UIResponder对象组成的
responder chain是由一系列responder对象连接起来的,他从第一个responder对象开始一直到application对象结束。如果第一个 responder不能够处理该事件则该事件会被发送到下一个在该responder chain中的responder来处理。
当自己定义的一个类想让他成为first responder时需要做两件事:
1.重写 canBecomeFirstResponder 方法让他返回YES
2.接受 becomeFirstResponder 消息
在这里有一个地方需要注意, 当把一个对象变为first responder是要确保这个对象的图形界面已经建立起来,也就是说要在viewDidAppear中调用becomeFirstResponder方 法。如果在veiwWillAppear方法中调用becomeFirstResponder将会得到一个NO。

Responder Chain 遵循一个特定的传播路径
如果hit-test view不能够处理该事件则UIKit会将事件传递给下一个Responder。
- (UIResponder *)nextResponder
Returns the receiver'€™s next responder, or nil if it has none.
The UIResponder class does not store or set the next responder automatically, instead returning nil by default. Subclasses must override this method to set the next responder. UIView implements this method by returning the UIViewController object that manages it (if it has one) or its superview (if it doesn’t); UIViewController implements the method by returning its view’s superview; UIWindow returns the application object, and UIApplication returns nil.

————————————————————————————————————————————————————————————————————————————————————————————————————————————————

// 切割image
- (UIImage *)clipImage:(UIImage *)image withRect:(CGRect)rect   {
    CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, rect);
    return [UIImage imageWithCGImage:imageRef];
}

http://blog.csdn.net/enuola/article/details/8291402


————————————————————————————————————————————————————————————————————————————————————————————————————————————————
作业:
封装一个带block回调的可点击的imageView
[imageView setClickHandler:^(void) {
    // 点击了...
}];









0 0