【问题标题】:Slide from one button to another without lifting your finger无需抬起手指即可从一个按钮滑到另一个按钮
【发布时间】:2010-02-07 09:57:11
【问题描述】:

我有两个按钮(按钮 1 和按钮 2),如果我按下按钮 1,note1 启动,如果我按下按钮 2,note 2 启动。

所以我尝试做的是:按下按钮 1(note1 启动)并滑动到按钮 2,然后 note2 应该启动。就像在钢琴键盘上滑动而不用抬起手指一样,从 c 到 h 的所有音符都发声。

我用UIImageViews 做了这个,我也用UIButtons 做了这个。

如果我按下c1pianoview,它会发出“c”的声音。如果我按下d1pianoview,它会发出“d”的声音。

但是,如果我没有抬起手指就从c1pianoview 滑到d1pianoview,它只会发出“c”的声音。我做错了什么?我也可以使用UIButtons 执行此操作吗?

触地可以,但滑动不起作用。

有人可以帮帮我吗?这是我的代码:

-(void)touchesBeganNSSet *)touches withEventUIEvent *)event
{
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint location = [touch locationInView:touch.view];

    if(CGRectContainsPoint(c1pianoview.frame, location))
    { 
      NSString *path = [[NSBundle mainBundle]
      pathForResource: @"c1piano" ofType:@"mp3"];
      AVAudioPlayer* theAudio = [[AVAudioPlayer alloc] 
          initWithContentsOfURL:[NSURL fileURLWithPathath] error:NULL];
      [theAudio play];
    }

    if(CGRectContainsPoint(d1pianoview.frame, location))
    { 
      NSString *path = [[NSBundle mainBundle]
      pathForResource: @"d1piano" ofType:@"mp3"];
      AVAudioPlayer* theAudio=[[AVAudioPlayer alloc] 
          initWithContentsOfURL: [NSURL fileURLWithPathath] error:NULL];
      [theAudio play];
    }
}

更新:

我还有一个问题。现在我有两个UIImageVIews。两个白色钢琴键上的黑色钢琴键。如果我按下黑键,它也会从它下面的白键发出音符。

如何防止这种情况发生?

【问题讨论】:

    标签: iphone touchesmoved sliding


    【解决方案1】:

    我认为一个更简单的解决方案是创建一个超级视图来拦截所有的触摸并决定要做什么。然后在 IB 中,您将视图设为 PianoView 的实例,并将所有键子视图设为子视图。每个键都有一个标签来标识它是哪个键,因此 PianoView 知道要演奏什么音符。 PianoView 有一个 currentView 属性,它跟踪 touchesMoved 中的最后一个视图,因此它不会一直尝试播放相同的键。我有一个具有相似但不同要求的键盘,这种方法效果很好。

    下面的示例代码截取hitTest:withEvent: 中的触摸。然后,在 touches* 方法中,它使用 UIView 的默认实现 hitTest:withEvent: 来确定正在播放哪个键。如果您想支持多点触控同时弹奏按键,则必须对其进行一些修改。

    @implementation PianoView
    
    -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
        // intercept touches
        if ([self pointInside:point withEvent:event]) {
            return self;        
        }
        return nil;
    }
    
    -(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        UIView* view = [super hitTest: [[touches anyObject] locationInView: self] withEvent: nil];
        // highlight subview under touch
        if (view != nil && view != self) {
            if ([view isKindOfClass:[UIButton class]]) {
                [(UIControl *)view setHighlighted:YES];
            }
            [self setCurrentView:view];
            [self playKey:view];
        }
    }
    
    -(void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
        // un-highlight everything
        for (UIView *subview in [self subviews]) {
            if ([subview isKindOfClass:[UIButton class]]) {
                [(UIControl *)subview setHighlighted:NO];
            }
        }
        [self stopPlaying];
        [self setCurrentView:nil];
    }
    
    -(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
        UIView* view = [super hitTest: [[touches anyObject] locationInView: self] withEvent: nil];
        if (view != [self currentView]) {
            UIView *oldKey = [self currentView];
            // un-highlight
            if ([oldKey isKindOfClass:[UIButton class]]) {
                [(UIControl *)oldKey setHighlighted:NO];
            }    
            if ([view isKindOfClass:[UIButton class]]) {
                [(UIControl *)view setHighlighted:YES];
            }    
            [self stopPlaying];
            [self playKey:view];
            [self setCurrentView:view];
        }
    }
    
    -(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
        UIView* view = [super hitTest: [[touches anyObject] locationInView: self] withEvent: nil];
        for (UIView *subview in [self subviews]) {
            if ([subview isKindOfClass:[UIButton class]]) {
                [(UIControl *)subview setHighlighted:NO];
            }
        }
        [self stopPlaying];
        [self setCurrentView:nil];
    }
    
    @end
    

    【讨论】:

    • 好答案。看起来不错,虽然还没有测试。似乎除了这个之外,Stackoverflow 上没有其他答案是正确的。
    • touchesMoved 中发现了一个导致崩溃的错误。第二个[(UIControl *)oldKey setHighlighted:YES]; 应该是[(UIControl *)view setHighlighted:YES];。除此之外,这似乎确实有效。
    【解决方案2】:

    [将进一步的问题合并到原始帖子中]

    【讨论】:

      【解决方案3】:

      你不需要:

      - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
      

      【讨论】:

      • 好的,我用 touchesMoved 做到了。但现在每次我在 ImageView 中滑动时,音符都会响起。但我希望音符只响一次。我做错了什么?谢谢帮助!
      • @franhu - Dimitris 打败了我
      【解决方案4】:

      您可以通过使用 UIButton 的“Touch Down”和“Touch Drag Inside”事件轻松实现此目的。

      如果您想使用-touchesMoved: 方法,您可以使用变量来跟踪触发声音的最后一个按钮,并且仅在当前按钮不是最后播放声音的按钮时才播放声音。

      更详细的:

      在标题中声明UIView *lastButton;,然后:

      -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
      {
      UITouch *touch = [[event allTouches] anyObject];
      CGPoint location = [touch locationInView:touch.view];
      
      if(CGRectContainsPoint(c1pianoview.frame, location) && lastButton != c1pianoview) {
          //play c1
          lastButton = c1pianoview;
      }
      else if(CGRectContainsPoint(d1pianoview.frame, location) && lastButton != d1pianoview) {
          //play d1
          lastButton = d1pianoview;
      }
      }
      
      - (void)touchedEnded:(NSSet *)touches withEvent:(UIEvent *)event {
          lastButton = nil;
      }
      
      - (void)touchedCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
          [self touchesEnded:touches withEvent:event];
      }
      

      【讨论】:

      • 好吧,它不能与 TouchDragInside 一起使用......你能帮我处理 touchesMoved.. 至极的 cariable 吗?谢谢
      • 对不起,它仍然不起作用。如果我在 c1pianoview 或 d1pianoview 内移动,它的每一个小动作都会发出音符。因此,如果我从 c1pianoview 滑到 d1pianoview,听起来大约有 10 个 c-notes 和 10 个 d-notes。 =) 但我只想听到一个 c-note 和一个 d-note!知道为什么我不工作吗?谢谢你的帮助!希腊
      • YEEEEESS maaaan...非常感谢..它有效..我做错了..是的,你摇滚..非常感谢!
      • 好的滑动工作。但还有一个小问题。如果我点击 c1 按钮五次,它会发出五次“C”的声音,所以我使用 touchesBegan 方法完成了它。这可行,但知道另一个问题是,如果我单击 c1 按钮,然后在音符内滑动两次。我不知道你是否理解我的问题,但如果你能帮忙,谢谢!希腊
      • 我在答案中添加了更多方法。每当抬起手指时,他们都会重置lastButton 变量。看看吧。
      猜你喜欢
      • 1970-01-01
      • 2021-07-12
      • 2013-08-23
      • 2020-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-08
      相关资源
      最近更新 更多