Android: custom view onClickEvent with X & Y locations

僤鯓⒐⒋嵵緔 提交于 2019-11-29 15:44:17

Now, I don't know about onTouchEvent short circuiting onClick, and I don't know if maybe you need to set android:clickable to true (or setClickable(true)). But, if you can't make it work cleanly, you can use a boolean in the onTouchEvent to mimic click detection if all else fails. in ACTION_DOWN, set it to true (isClicking or something like that), in ACTION_MOVE set it to false (because the user is dragging therefore not clicking) and then in ACTION_UP you can test for it. If it's true, this means the user has pressed down but not dragged. It's hacky, but if you can't get onClick to work it's basically the same thing.

What are you returning at the end of your onTouchEvent? According to the documentation returning true means "The event has been fully handled, do nothing more with it", whereas returning false means the system will continue processing. I haven't tested this with your exact situation, but that suggests that returning false might work. That would make the system continue processing the touch/click and send it to the next View 'underneath'.

If that doesn't work, then I can't yet think of a better solution than doing something similar to what Rich suggested. You could do something like getting the time at ACTION_DOWN and then on ACTION_UP, compare the time that has passed. If it's less than 100 milliseconds, then it should be interpreted as a click. You could then trigger whatever code you wanted to put in your click listener.

For example, here's how you could code this:

long touchDownTime; // This has to be a class field so that it persists 
                    // between calls to onTouchEvent

public boolean onTouchEvent(MotioNEvent event){
    boolean handled = false;

    int action = event.getAction();
    switch (action){
    case MotionEvent.ACTION_DOWN:
        touchDownTime = SystemClock.elapsedRealtime();
        break;

    case MotionEvent.ACTION_UP:
        if (SystemClock.elapsedRealtime() - touchDownTime <= 100){
            int x = event.getX(); //or event.getRawX();
            int y = event.getY();
            performYourClick(x, y);
            handled = true;
        }
        break;
    }

    return handled;
}

Note: I didn't actually test that code so it's possible I've made some syntax mistakes. The general idea should still be fine though.

FYI, in my tests it looks like onTouch does override onClick for a view, irrespective of whether onTouch returns true or false.

-Frink

Manjunath

I have able solve this problem

I created an Custom View public class QuestionBuilderView extends View

In layout File

 < com.example.android.view.QuestionBuilderView

        android:id="@+id/questionbuilderview"

        android:layout_width="fill_parent"

        android:layout_height="wrap_content" />

In an main Activity try to call the custom view and set the Onclick / On Touch Event Listener to the view

 View questionBuilder =  findViewById(R.id.questionbuilderview);
         questionBuilder.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View view, MotionEvent event) {
                // TODO Auto-generated method stub
                float touched_x = event.getX();
               float  touched_y = event.getY();
               Toast.makeText(getApplicationContext(), " "+touched_x +","+touched_y, Toast.LENGTH_LONG).show();
              //  int action = event.getAction();


                return true;
            }

i think you have to call super.onTouchEvent(event) because in that method, the click is detected.

You should use GestureDetector. Subclass GestureDetector.SimpleOnGestureListener and override onDown(MotionEvent event) method to return true. Then override onSingleTapConfirmed. Pass the listener to the GestureDetector constructor. Then call setOnDoubleTapListener with that listener as a parameter:

// in your view class constructor
GestureDetector.SimpleOnGestureListener listener = new GestureDetector.SimpleOnGestureListener() {
   @Override
   public boolean onDown(MotionEvent e) {
      return true;
   }
   @Override
   public boolean onSingleTapConfirmed(MotionEvent e) {
      // do whatever you want
      return true;
   }
};
mDetector = new GestureDetector(getContext(), listener);
mDetector.setOnDoubleTapListener(listener);

Then, you can pass MotionEvents to the detector:

@Override
public boolean onTouchEvent(MotionEvent event) {
   return mDetector.onTouchEvent(event);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!