0

I'm making an app in which you touch a specific word on the screen and that word gets pronounced. But when I tap on any word, it gets pronounced at least twice and if I hold my finger on the word it gets pronounced so many times and I don't want that. Can I detect the touch as only a tap on the screen? And if the user holds or did a long press, I want something entirely different to happen like copying the word for example.

I tried to do that based on someone's code but both the if and else statements run!

@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);
    }

I also tried the onDown(), onShowPress(), onSingleTapUp() and onLongPress() methods but none of them does anything and I don't know why of should i use them better of the onTouchEvent() method.

Ziad H.
  • 528
  • 1
  • 5
  • 20

3 Answers3

1

There are multiple types of MotionEvent Actions You can differentiate them by checking the actions of the events

@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);
}
Emir
  • 279
  • 2
  • 8
1

You can use all LongClick, Click and touch listener on a single view, I had to occasionally use it in a project so I wrote a utility class that handles Click, Hold(Long Click) start and hold end(release) on a single view.

Check it out at

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

            }
        });

To use it, just pass the view in constructor and add listeners to the manager.

You can customize it by adding more events in onTouchEvent.

(Please excuse some of the methods that should have been private)

Zohaib Amir
  • 3,482
  • 2
  • 11
  • 29
0

So, I was able to perfectly handle touch events by implementing the GestureDetector.OnGestureListener methods in conjunction with the onTouchEvent() methods.

    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) {
    }

Things that helped me through:

Ziad H.
  • 528
  • 1
  • 5
  • 20