如何处理不同的触摸事件,尤其是点击和长按屏幕?

How to probably handle different touch events, especially taps and long press on screen?

我正在制作一个应用程序,您可以在其中触摸屏幕上的特定单词,然后该单词就会发音。但是,当我点击任何单词时,它至少会被发音两次,如果我将手指放在该单词上,它会被发音很多次,我不希望这样。我可以将触摸检测为仅在屏幕上轻按吗?如果用户按住或长按,我希望发生完全不同的事情,例如复制单词。

我试图根据某人的代码来做到这一点,但是 if 和 else 语句 运行!

@Override
    public boolean onTouchEvent(MotionEvent event) {

        int touchX = Math.round(event.getX());
        int touchY = Math.round(event.getY());

        long startClickTime = System.currentTimeMillis();


        //words are surrounded with rect objects because i'm using the TextRecognition library that Google provided
        for(int x=0; x< rects.size();x++) {

                if (System.currentTimeMillis() - startClickTime < ViewConfiguration.getTapTimeout()) {

                    // Touch was a simple tap. Do whatever.
                    Log.i("TTS", "Touch was a simple tap!");

                    if (rects.get(x).contains(touchX, touchY)) {
                        // a word has been clicked -> some code to pronounce the word

                        return true;
                } else {

                    // Touch was a not a simple tap.
                        Log.i("TTS", "Touch was a not a simple tap!");
                }
            }
        }

        return super.onTouchEvent(event);
    }

我也尝试了 onDown()onShowPress()onSingleTapUp()onLongPress() 方法,但是其中的 none 没有任何作用,我不知道为什么我应该更好地使用 onTouchEvent() 方法吗?

有多种类型MotionEvent Actions您可以通过查看事件的动作来区分它们

@Override
public boolean onTouchEvent(MotionEvent event) {
 if (event.getAction() == MotionEvent.ACTION_DOWN) {
 int touchX = Math.round(event.getX());
 int touchY = Math.round(event.getY());

 long startClickTime = System.currentTimeMillis();


    //words are surrounded with rect objects because i'm using the TextRecognition library that Google provided
    for(int x=0; x< rects.size();x++) {

            if (System.currentTimeMillis() - startClickTime < ViewConfiguration.getTapTimeout()) {

                // Touch was a simple tap. Do whatever.
                Log.i("TTS", "Touch was a simple tap!");

                if (rects.get(x).contains(touchX, touchY)) {
                    // a word has been clicked -> some code to pronounce the word

                    return true;
            } else {

                // Touch was a not a simple tap.
                    Log.i("TTS", "Touch was a not a simple tap!");
            }
        }
    }

}

    return super.onTouchEvent(event);
}

您可以在单个视图上使用所有 LongClick、Click 和 Touch 侦听器,我不得不偶尔在项目中使用它,所以 我编写了一个实用程序 class 来处理单个视图上的点击、按住(长按)开始和按住结束(释放)。

查看

https://github.com/Zohaib-Amir/utility-classes/blob/master/ClickAndHoldManager.java

ClickAndHoldManager manager = new ClickAndHoldManager(myButton);
manager.setClickCallback(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
             //Regular Click
            }
        });
manager.setHoldCallback(new ClickAndHoldManager.HoldListener() {
            @Override
            public void holdStarted() {
                // this is same as onLongClick
            }

            @Override
            public void holdEnded() {
                // LongClick released

            }
        });

要使用它,只需在构造函数中传递视图并将监听器添加到管理器。

您可以通过在 onTouchEvent 中添加更多事件来自定义它。

(请原谅一些本应私有的方法)

因此,通过结合实现 GestureDetector.OnGestureListener 方法和 onTouchEvent() 方法,我能够完美地处理触摸事件。

    private GestureDetectorCompat mDetector;
    boolean mIsScrolling;

    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_preview);

            // Instantiate the gesture detector with the
            // application context and an implementation of
            // GestureDetector.OnGestureListener
            mDetector = new GestureDetectorCompat(this,this);


            //set TouchListener on previewLayout
            previewLayout.setOnTouchListener(new View.OnTouchListener() {
                public boolean onTouch(View v, MotionEvent event) {

                    if (mDetector.onTouchEvent(event)) {
                        return true;
                    }

                    if(event.getAction() == MotionEvent.ACTION_UP) { //when user left his finger up
                        if(mIsScrolling) { //if it was a scroll action
                            handleScrollFinished();
                            mIsScrolling  = false; //set mIsScrolling back to false

                        }
                    }

                    return PreviewActivity.super.onTouchEvent(event);
            }

            });
}

.

@Override
    public boolean onDown(MotionEvent event) {
        //Do stuff
        return true;
    }

    @Override
    public boolean onSingleTapUp(MotionEvent event) {
        //So stuff
        return true;
    }

    @Override
    public void onLongPress(MotionEvent event) {
        //Do stuff
    }

    @Override
    public boolean onScroll(MotionEvent event1, MotionEvent event2, float distanceX,
                            float distanceY) {
        mIsScrolling  = true;

        //Do stuff
        return true;
    }

    private void handleScrollFinished() {

        //Do stuff

    }

    @Override
    public boolean onFling(MotionEvent event1, MotionEvent event2,
                           float velocityX, float velocityY) {
        return false; //it has to return false, or I will have to write unnecessary extra code
    }


    @Override
    public void onShowPress(MotionEvent event) {
    }

帮助我度过难关的事情: