2013-08-01 26 views
10

Tôi cần một phát hiện cảm ứng singletap trong phương pháp ontouch của chế độ xem tùy chỉnh của tôi. Tôi đã thử nhận được giá trị x và y trong cả ACTION-DOWN và ACTION-UP và trong ACTION-UP, tôi đã đưa ra một điều kiện là nếu giá trị của X và Y trong ACTIONDOWN và ACTION-UP bằng nhau thì hãy lấy nó như một lần nhấn .phát hiện cảm ứng singletap trong phương pháp Ontouch của chế độ xem

Mã của tôi là như sau

@Override 
public boolean onTouchEvent(MotionEvent ev) { 
    if (!mSupportsZoom && !mSupportsPan) return false; 

    mScaleDetector.onTouchEvent(ev); 

    final int action = ev.getAction(); 
    switch (action & MotionEvent.ACTION_MASK) { 
    case MotionEvent.ACTION_DOWN: { 
     final float x = ev.getX(); 
     final float y = ev.getY(); 

     mLastTouchX = x; //here i get x and y values in action down 
     mLastTouchY = y; 
     mActivePointerId = ev.getPointerId(0); 

     break; 
    } 

    case MotionEvent.ACTION_MOVE: { 
     final int pointerIndex = ev.findPointerIndex(mActivePointerId); 
     final float x = ev.getX(pointerIndex); 
     final float y = ev.getY(pointerIndex); 

     if (mSupportsPan && !mScaleDetector.isInProgress()) { 
      final float dx = x - mLastTouchX; 
      final float dy = y - mLastTouchY; 

      mPosX += dx; 
      mPosY += dy; 
      //mFocusX = mPosX; 
      //mFocusY = mPosY; 

      invalidate(); 
     } 

     mLastTouchX = x; 
     mLastTouchY = y; 

     break; 
    } 

    case MotionEvent.ACTION_UP: { 

     final float x = ev.getX(); 
     final float y = ev.getY(); 

     touchupX=x; //here is get x and y values at action up 
     touchupY=y; 

     if(mLastTouchX == touchupX && mLastTouchY == touchupY){ //my condition if both the x and y values are same . 

      PinchZoomPanActivity2.tapped1(this.getContext(), 100); //my method if the singletap is detected 

     } 
     else{ 

     } 

     mActivePointerId = INVALID_POINTER_ID; 

     break; 
    } 

    case MotionEvent.ACTION_CANCEL: { 
     mActivePointerId = INVALID_POINTER_ID; 
     break; 
    } 

    case MotionEvent.ACTION_POINTER_UP: { 
     final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) 
       >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; 
     final int pointerId = ev.getPointerId(pointerIndex); 
     if (pointerId == mActivePointerId) { 

      final int newPointerIndex = pointerIndex == 0 ? 1 : 0; 
      mLastTouchX = ev.getX(newPointerIndex); 
      mLastTouchY = ev.getY(newPointerIndex); 
      mActivePointerId = ev.getPointerId(newPointerIndex); 
     } 
     break; 
    } 
    } 

    return true; 
} 

nhưng tôi không thể làm cho nó thực hiện. Tôi có nghĩa là ở mỗi hành động lên phương pháp của tôi được gọi là. ngay cả khi các giá trị x và y của cả actionup và actiondown đều không giống nhau. và tôi nghĩ rằng tôi cũng cần phải đặt một số phạm vi vào singletap khi chúng ta chạm ngón tay trên màn hình. Bất cứ ai có thể gợi ý cho tôi một số cách?

+0

Nó sẽ không bao giờ ở cùng một vị trí, ngón tay của bạn sẽ luôn di chuyển nhẹ. Sử dụng kiểm tra phạm vi-đảm bảo rằng abs (upLoc-downLoc) <5. –

+0

tôi cần phải sử dụng kiểm tra phạm vi nhưng tôi không hiểu "abs (upLoc-downLoc) <5" của bạn. –

+0

abs = giá trị tuyệt đối. Điều đó có nghĩa là nếu vị trí đã thay đổi ít hơn 5 pixel. –

Trả lời

6

Tôi cũng đã gặp phải vấn đề tương tự gần đây và đã kết thúc việc phải thực hiện một bản báo cáo để làm cho nó hoạt động. Nó không phải là lý tưởng, nhưng nó khá đáng tin cậy cho đến khi tôi có thể tìm thấy một cái gì đó tốt hơn.

View.onClickListener đáng tin cậy hơn nhiều đối với tôi, nhưng tiếc là tôi cần MotionEvent từ OnTouchListener.

Edit: Removed mã dư thừa có thể gây ra lỗi đối với nó đây

class CustomView extends View { 

    private static long mDeBounce = 0; 

    static OnTouchListener listenerMotionEvent = new OnTouchListener() { 
     @Override 
     public boolean onTouch(View view, MotionEvent motionEvent) { 
      if (Math.abs(mDeBounce - motionEvent.getEventTime()) < 250) { 
       //Ignore if it's been less then 250ms since 
       //the item was last clicked 
       return true; 
      } 

      int intCurrentY = Math.round(motionEvent.getY()); 
      int intCurrentX = Math.round(motionEvent.getX()); 
      int intStartY = motionEvent.getHistorySize() > 0 ? Math.round(motionEvent.getHistoricalY(0)) : intCurrentY; 
      int intStartX = motionEvent.getHistorySize() > 0 ? Math.round(motionEvent.getHistoricalX(0)) : intCurrentX; 

      if ((motionEvent.getAction() == MotionEvent.ACTION_UP) && (Math.abs(intCurrentX - intStartX) < 3) && (Math.abs(intCurrentY - intStartY) < 3)) { 
       if (mDeBounce > motionEvent.getDownTime()) { 
        //Still got occasional duplicates without this 
        return true; 
       } 

       //Handle the click 

       mDeBounce = motionEvent.getEventTime(); 
       return true; 
      } 
      return false; 
     } 
    }; 
} 
+1

Cảm ơn bạn rất nhiều.this working.best chức năng để doubletap trong ontouch theo tôi. bạn có thể tìm thấy một số trục trặc khi multitouch nhưng điều này là tốt nhất. –

+0

không hoạt động đối với tôi, điều này thậm chí còn ghi đè phương pháp nhấp đúp của tôi – Casper

0

Giả sử bạn không cần sử dụng toán tử "bằng". Thay vì sử dụng giá trị khoảng

case MotionEvent.ACTION_DOWN: { 
    final int CONST = 5; 
    final float x = ev.getX(); 
    final float y = ev.getY(); 

    mLastTouchXMax = x+CONST; //here i get x and y values in action down 
    mLastTouchXMin = x-CONST; 
    mLastTouchYMax = y+CONST; 
    mLastTouchYMin = y-CONST; 
    mActivePointerId = ev.getPointerId(0); 

    break; 
} 

Và trong ACTION_UP kiểm tra giá trị X và Y giữa khoảng thời gian.

+0

tôi không hiểu phải làm gì trong hành động Up.i cần phải kiểm tra xem các giá trị x và y trong hành động đi kèm theo bốn giá trị trong hành động down.but làm thế nào tôi sẽ làm điều này. giúp tôi.thank bạn. –

4

Thêm GestureDetector.SimpleOnGestureListener cho xem và sử dụng phương pháp onSingleTapConfirmed trong việc này.

Phương thức này chỉ được gọi khi hệ điều hành Android đã xác nhận liên lạc cụ thể là một lần chạm và không nhấn đúp.

Bạn có thể google cho ví dụ android.

+0

vâng tôi đã thử cách này .. nhưng tôi đang gặp phải một số sự cố khác với đơn hoặc đôi này. dù sao cũng cảm ơn. –

+0

onSingleTapConfirmed sẽ được gọi chỉ khi nhấn là duy nhất. Không có sự nhầm lẫn ở đây. Xem tên chính phương thức cho biết nó thấy onSingleTapConfirmed. Tôi không biết bạn đang đề cập đến vấn đề gì khác, tôi nghĩ bạn chưa xử lý đúng giá trị trả lại. Kiểm tra nó! – Charan

+0

vấn đề của tôi không phải là với người nghe cử chỉ nhưng với ứng dụng của tôi. ứng dụng của tôi có chế độ xem tùy chỉnh với pan đa chạm và thu phóng bằng ontouch, điều này không phù hợp với trình xử lý cử chỉ. –

29

Để phát hiện đơn và Double Tap trong android Tôi đang sử dụng các phương pháp sau:

class GestureTap extends GestureDetector.SimpleOnGestureListener { 
    @Override 
    public boolean onDoubleTap(MotionEvent e) { 
     Log.i("onDoubleTap :", "" + e.getAction()); 
     return true; 
    } 

    @Override 
    public boolean onSingleTapConfirmed(MotionEvent e) { 
     Log.i("onSingleTap :", "" + e.getAction()); 
     return true; 
    } 
} 

Sử dụng nó trong constructor của GestureDetector:

detector = new GestureDetector(this, new GestureTap()); 

Và thêm đoạn mã sau vào onTouch nghe

@Override 
public boolean onTouchEvent(MotionEvent event) { 

    detector.onTouchEvent(event); 

    return true; 
} 
+0

1 Cảm ơn bạn đã cứu công việc và cuộc sống của tôi. Bạn là một thiên thần. Ngoài ra để thêm, đây là tham chiếu cho các cử chỉ được hỗ trợ khác mà bạn có thể ghi đè: https://developer.android.com/training/gestures/detector.html#detect. Nhìn vào phần 'Phát hiện cử chỉ'. –

2

Có một cách đơn giản hơn và thẳng về phía trước. Sử dụng MotionEvent.ACTION_DOWN & & MotionEvent.ACTION_UP và định thời gian sự khác biệt giữa các sự kiện.

Có thể tìm thấy mã đầy đủ tại đây.https://stackoverflow.com/a/15799372/3659481

setOnTouchListener(new OnTouchListener() { 
private static final int MAX_CLICK_DURATION = 200; 
private long startClickTime; 

@Override 
public boolean onTouch(View v, MotionEvent event) { 
    switch (event.getAction()) { 
     case MotionEvent.ACTION_DOWN: { 
      startClickTime = Calendar.getInstance().getTimeInMillis(); 
      break; 
     } 
     case MotionEvent.ACTION_UP: { 
      long clickDuration = Calendar.getInstance().getTimeInMillis() - startClickTime; 
      if(clickDuration < MAX_CLICK_DURATION) { 
       //click event has occurred 
      } 
     } 
    } 
    return true; 
} 

}

7

Thêm câu trả lời cho đầy đủ vì lợi ích và nếu bất cứ ai khác đạt ở đây:

Bạn có thể sử dụng một GestureDetector với một OnTouchListener

final GestureDetector gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() { 
     @Override 
     public boolean onSingleTapConfirmed(MotionEvent e) { 
     //do something 
      return true; 
     } 

     @Override 
     public void onLongPress(MotionEvent e) { 
      super.onLongPress(e); 
     } 

     @Override 
     public boolean onDoubleTap(MotionEvent e) { 
      return super.onDoubleTap(e); 
     } 
    }); 

viewToTouch.setOnTouchListener(new View.OnTouchListener() { 
     @Override 
     public boolean onTouch(View v, MotionEvent event) { 

      return gestureDetector.onTouchEvent(event); 
     } 
    }); 
0
float dX,dY,x,y;  
tv.setOnTouchListener(new View.OnTouchListener() { 
           @Override 
           public boolean onTouch(View view, MotionEvent event) { 
            switch (event.getAction()) { 
             case MotionEvent.ACTION_UP:  //Event for On Click 
              if(x==view.getX() && y==view.getY()){ 
               Toast.makeText(getApplicationContext(),"TextView Clicked",Toast.LENGTH_LONG).show(); 
              } 
              break; 
             case MotionEvent.ACTION_DOWN: 
              x=view.getX(); 
              y=view.getY(); 
              dX = view.getX() - event.getRawX(); 
              dY = view.getY() - event.getRawY(); 
              break; 

             case MotionEvent.ACTION_MOVE: 
              view.animate() 
                .x(event.getRawX() + dX) 
                .y(event.getRawY() + dY) 
                .setDuration(0) 
                .start(); 
              break; 
             default: 
              return false; 
            } 
            return true; 
           } 
          }); 
Các vấn đề liên quan