littleJoe

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
12章 Touch Events and UIResponder
    触摸事件touch events,手势 gestures, 调试 debugging application

    UIView 继承UIResponder,所以可以重写以下四个方法:
        touchBegan:(NSSet *)touches withEvent:
        touchMoved:withEvent:
        touchEnded:withEvent:
        touchCancel:withEvent:

        touche中有个UITouch的对象,包含了触碰的位置等信息
        你不需要保存UITouch的对象,因为在事件中你可以访问得到。
        当手指滑出初始触碰到视图,会受到touchMoved和touchEnded
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 重写几个touch事件,获取location。
// setNeedDisplay,系统自动调用drawRect,
// 如何绘制、设置颜色、stoke等。

            #import "BNRDrawView.h"
            #import "BNRLine.h"

            @interface BNRDrawView()
            
                @property (nonatomic,strong) NSMutableArray *finishedLines;
                @property (nonatomic,strong) BNRLine *currentLine;
            
            @end

            @implementation BNRDrawView

            -(instanceType)initWithFrame:(CGRect)r
            {
                self = [super initWithFrame:r];
                if(self)
                {
                    self.finishedLines = [[NSMutableArray alloc] init];
                    self.backgroundColor = [UIColor grayColor];
                }
                
            }

            - (void) strokeLine: (BNRLine *)line
            {
                UIBezierPath *bp = [UIBezierPath bezierPath];
                bp.lineWith = 10;
                bp.lineCapStyle = kCGLineCapRound;
                
                [bp moveToPoint:line.begin];
                [bp addLineToPoint: line.end];
                [bp stroke];
            }

            -(void)drawRect:(CGRect) rect
            {
                // 每次都要重新遍历finishedLines再重新绘制???
                [[UIColor blackColor] set];
                for(BNRLine *line in self.finishedLines]
                {
                    [self strokeLine:line];
                }
                
                if(self.currentLine){
                    [[UIColor redColor] set];
                    [self strokeLine:self.currentLine];
                }
            }   

            - (void) touchBegan:(NSSet *)touches withEvent:(UIEvent *)event
            {
                UITouch *touch = [touches anyObject];
                CGPoint location = [touch locationInView:self];
                self.currentLine = [[BNRLine alloc] init];
                self.currentLine.begin = location;
                self.currentLine.end = location;
                [self setNeedDisplay];
            }

            - (void) touchMoved:(NSSet *)touches withEvent:(UIEvent *)event
            {
                UITouch *t = [touches anyObject];
                CGPoint location = [t locationInView:self];
                self.currentLine.end = location;
                [self setNeedDisplay];
            }

            -(void) touchEnded:(NSSet *)touches withEvent:(UIEvent *)event
            {
                [self.finishedLines addObject:self.currentLine];
                self.currentLine = nil;
                [self setNeedDisplay];
            }

            @end
-----------------------------------------------------------------------
    多点触控。
        默认情况下一个view只能接受一个finger的touch: 一个手指触发了touchBegan,但是没有ended。则view会忽略其他触碰

     self.multipleTouchEnabled = YES;
     touchCancelled发生在系统事件,比如电话来了~,一般这时候会把当前线段都移除掉

     保存多个数据
         for (UITouch *t in touches) {
            CGPoint location = [t locationInView:self];

            BNRLine *line = [[BNRLine alloc] init];
            line.begin = location;
            line.end = location;

            NSValue *key = [NSValue valueWithNonretainedObject:t];
            self.linesInProgress[key] = line;
        }
        //用NSValue *key来作为字典的key而不是直接用t,因为字典的key是实现了NSCopying协议

    ------------------------------------------------------------------------
        #import "BNRDrawView.h"
        #import "BNRLine.h"

        @interface BNRDrawView
        {
            @property (nonatomic,strong) NSMutableDictionary *linesInProgress;
            @property (nonatomic,strong) NSMutableArray *finishedLines;
            // @property (nonatomic,strong) BNRLine *currentLine;
        }
        @end

        @implementation BNRDrawView

        -(instanceType)initWithFrame:(CGRect)r
        {
            self = [super initWithFrame:r];
            if(self)
            {
                self.linesInProgress = [[NSMutableArray] alloc] init];
                self.finishedLines = [[NSMutableArray alloc] init];
                self.backgroundColor = [UIColor grayColor];
            }
            
        }

        - (void) strokeLine: (BNRLine *)line
        {
            UIBezierPath *bp = [UIBezierPath bezierPath];
            bp.lineWith = 10;
            bp.lineCapStyle = kCGLineCapRound;
            
            [bp moveToPoint:line.begin];
            [bp addLineToPoint: line.end];
            [bp stroke];
        }

        -(void)drawRect:(CGRect) rect
        {
            // finished
            [[UIColor blackColor] set];
            for(BNRLine *line in self.finishedLines]
            {
                [self strokeLine:line];
            }

            // current progress
            [[UIColor redColor] set];
            for(BNRLine *line in self.linesInProgress){
                [self strokeLine:line];
            }
        }   

        - (void) touchBegan:(NSSet *)touches withEvent:(UIEvent *)event
        {
            for(UITouch *t in touches){
                CGPoint location = [t locationInView:self];
                NSValue *key = [NSValue valueWithNonretainedObject:t];
                BNRLine *line = [[BNRLine alloc] init];
                line.begin = location;
                line.end = location;
                self.linesInProgress[key] = line;
            }
            [self setNeedDisplay];
        }

        - (void) touchMoved:(NSSet *)touches withEvent:(UIEvent *)event
        {
            for(UITouch *t in touches){
                CGPoint location = [t locationInView:self];
                NSValue *key = [NSValue valueWithNonretainedObject:t];
                BNRLine *line = self.linesInProgress[key];
                line.end = location;
            }
            [self setNeedDisplay];
        }

        -(void) touchEnded:(NSSet *)touches withEvent:(UIEvent *)event
        {
            for(UITouch *t in touches){
                NSValue *key = [NSValue valueWithNonretainedObject:t];
                BNRLine *line = self.linesInProgress[key];
                [self.finishedLines addObject:line];
                [self.linesInProgress removeObjectForKey:key];
            }
            [self setNeedDisplay];
        }

        -(void) touchCancelled:(NSSet *)touches withEvent:(UIEvent *)event
        {
            for(UITouch *t in touches){
                NSValue *key = [NSValue valueWithNonretainedObject:t];
                [self.linesInProgress removeObjectForKey:key];
            }
            [self setNeedDisplay];
        }

        @end





    Responder chain
        每个responder有一个nextResponder属性,构成chain。 rootView: window's nextResponder is UIApplication
'
    UIControl:can set targets and actions
        the superclass of UIButton,UISlider...
        [rButton addTarget:tempController action:@selector(resetTemperature:) forControlEvents:UIControlEventTouchUpInSide | UIControlEventTouchUpOutSide]

        then you can send event:
        [self sendActionsForControlEvents:UIControlEventTouchUpInSide]

        消息不是直接发送给目标view,而是通过UIApplication来找到target
        -----------重写UIResponder---------------------
        - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
        {
            // Reference to the touch that is ending
            UITouch *touch = [touches anyObject];

            // Location of that point in this control's coordinate system
            CGPoint touchLocation = [touch locationInView:self];

            // Is that point still in my viewing bounds?
            if (CGRectContainsPoint(self.bounds, touchLocation))
            {
                // Send out action messages to all targets registered for this event!
                [self sendActionsForControlEvents:UIControlEventTouchUpInside];
            } else {
                // The touch ended outside the bounds, different control event
                [self sendActionsForControlEvents:UIControlEventTouchUpOutside];
            }
        }

 

posted on 2015-02-04 23:08  littleJoe  阅读(111)  评论(0)    收藏  举报