用于钢琴应用的onTouchListener

时间:2014-08-11 11:39:46

标签: android audio ontouchlistener soundpool

我正在尝试制作钢琴应用程序。

如何在多个键(VIEWS)上滑动并让它们播放音调? 每把钥匙都有自己的声音。

这会产生很大的性能差异吗?

目前正在运作:

  • 播放音频 - > MotionEvent.ACTION_DOWN
  • 停止音频 - > MotionEvent.ACTION_UP
  • 显示触控反馈 - > MotionEvent.ACTION_DOWN
  • 还原触摸反馈 - > MotionEvent.ACTION_UP
  • 选中切换按钮时保持音频
  • 当我触摸一个键并远离键时,声音会停止。

以下是其中一个关键:

    keyC1.setOnTouchListener(new View.OnTouchListener() {

        private Rect rect;    // Variable rect to hold the bounds of the view

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction() & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_DOWN:
                    // Finger started pressing --> play sound in loop mode
                    rect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
                    Sound_tonC1();
                    keyC1.setBackgroundColor(getResources().getColor(R.color.lightgray));
                    break;
                case MotionEvent.ACTION_MOVE:
                    // Finger released --> stop playback
                    if(!rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())){
                        // User moved outside bounds
                        keyC1.setBackgroundResource(R.drawable.piano_whitekey);

                        if(!sustain){
                            spool.stop(streamID_C1);
                        }
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    // Finger released --> stop playback
                    keyC1.setBackgroundResource(R.drawable.piano_whitekey);

                    if(!sustain){
                        spool.stop(streamID_C1);
                    }
                    break;
            }
            return true;
        }
    });

1 个答案:

答案 0 :(得分:1)

要理解的一件事是,当您按下一个对象并将手指从对象上移开时,被调用的事件是一个ACTION_CANCEL事件。这就是为什么当您按下应用程序中的任何元素但将手指滑离应用程序时,您将要执行的操作不会发生。因此,您应该在代码中处理cancel事件,并在此情况下放置ACTION_UP代码:

keyC1.setOnTouchListener(new View.OnTouchListener() {

    boolean keyIsPressed = false;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // Finger started pressing --> play sound in loop mode
                Sound_tonC1();
                keyIsPressed = true;
                keyC1.setBackgroundColor(getResources().getColor(R.color.lightgray));
                break;
            case MotionEvent.ACTION_CANCEL:
                // Finger released --> stop playback
                keyC1.setBackgroundResource(R.drawable.piano_whitekey);

                if(!sustain){
                    keyIsPressed = false;
                    spool.stop(streamID_C1);
                }
                break;
            case MotionEvent.ACTION_UP:
                // Finger released --> stop playback
                keyC1.setBackgroundResource(R.drawable.piano_whitekey);

                if(!sustain){
                    keyIsPressed = false;
                    spool.stop(streamID_C1);
                }
                break;
            case MotionEvent.ACTION_MOVE:
                // Finger is moving on key --> start playback if the key is not already played
                if(!keyIsPressed) {
                    Sound_tonC1();
                    keyIsPressed = true;
                    keyC1.setBackgroundColor(getResources().getColor(R.color.lightgray));
                }
        }
        return true;
    }
});

注意:使用ACTION_CANCEL并删除ACTION_MOVE,因为您不需要处理某个键的移动事件,只需按下该键并将其释放即可。

您的代码未检测到手指何时离开该键的原因是因为一旦触摸事件离开该区域,您的对象就不再接收任何事件。希望这有帮助。