2011-01-01 49 views
16

Tôi nghĩ rằng phương thức "onTouchEvent()" của cá thể "ScaleGestureDetector" được cho là trả về "true" chỉ khi nó thực sự xử lý sự kiện chạm, i. e. nếu nó phát hiện cử chỉ mở rộng đa chạm (bằng hai ngón tay). Nếu không tôi nghĩ rằng nó được cho là sẽ trả về "sai" để cho những người xử lý khác xử lý sự kiện, e. g. báo chí dài để kích hoạt menu ngữ cảnh.ScaleGestureDetector.onTouchEvent luôn trả về 'true'

Tôi quan sát thấy điều gì đó khác: scaleGestureDetector.onTouchEvent() luôn trả về "true" trong trường hợp của tôi. Đoạn mã sau đây của lớp MyView tôi:

public boolean onTouchEvent(MotionEvent event) { 
    boolean retval = scaleGestureDetector.onTouchEvent(event); 
    Log.v("MyView.onTouchEvent()", "Action: " + event.getAction() + 
     "; PointerCount: " + event.getPointerCount() + 
     "; scaleGestureDetector.onTouchEvent() RetVal: " + retval); 
    return(retval); 
} 

sản xuất các dữ liệu ghi nhận follwing sau khi tôi chạm vào xem cho khoảng 1 giây bằng một ngón tay, sau đó thực hiện một cử chỉ quy mô với 2 ngón tay:

01-01 19:09:54.484: VERBOSE/MyView.onTouchEvent()(5930): Action: 0; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:09:54.510: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:09:54.541: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:09:54.580: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:09:54.820: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:09:54.910: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:09:55.050: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:09:55.350: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:09:55.400: VERBOSE/MyView.onTouchEvent()(5930): Action: 1; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:09:57.160: INFO/BatteryStatsImpl(96): notePhoneSignalStrengthLocked: 4->3 
01-01 19:10:00.060: ERROR/ClockWidget(215): weatherClock onReceive~ mUseAnimation:false 
01-01 19:10:00.060: ERROR/ClockWidget(215): handleUiMessage~ in pause. msg:36867 
01-01 19:10:00.070: ERROR/ClockWidget(215): weatherClock onReceive~ mUseAnimation:false 
01-01 19:10:00.090: INFO/PI.Alarms(699): Update Alarms start 
01-01 19:10:00.090: INFO/PI.Alarms(699): Task Notifications: Already displaying the same alarms, no update 
01-01 19:10:00.100: INFO/PI.Alarms(699): Event Notifications: Already displaying the same alarms, no update 
01-01 19:10:00.830: VERBOSE/MyView.onTouchEvent()(5930): Action: 0; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:00.840: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:00.870: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:00.900: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:00.922: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:00.931: VERBOSE/MyView.onTouchEvent()(5930): Action: 261; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:00.950: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.002: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.030: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.060: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.090: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.120: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.140: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.172: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.200: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.230: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.252: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.280: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.310: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.342: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.370: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.390: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.424: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.450: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.480: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.510: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.530: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.580: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.690: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.780: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.815: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.830: VERBOSE/MyView.onTouchEvent()(5930): Action: 262; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true 
01-01 19:10:01.840: VERBOSE/MyView.onTouchEvent()(5930): Action: 1; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true 

Như tôi đã nói: Giá trị trả về luôn là "đúng"! Đây có phải là lỗi của ScaleGestureDetector.onTouchEvent() không? Tôi có thể làm gì để cho những người xử lý khác xử lý tất cả các sự kiện cử chỉ không quy mô (ví dụ: bấm và giữ với 1 ngón tay)? Hãy giúp tôi!

Nemax

Trả lời

4

Không biết nếu đó là một lỗi hay cố ý, nhưng đó chắc chắn là những gì các nguồn thực hiện (ScaleGestureDetector.java:156):

public boolean onTouchEvent(MotionEvent event) { 
    final int action = event.getAction(); 
    boolean handled = true; 

    /* ... bunch of code that never updates 'handled' */ 

    return handled; 
} 

Con đường tôi giải quyết này là để kiểm tra tất cả các loại sự kiện chạm khác mà tôi có thể muốn xử lý trước, sau đó gọi trình dò ​​cử chỉ, ví dụ

if (mLongPressGestureDetector != null && mLongPressGestureDetector.onTouchEvent(event)) 
     return true; 
    else if (mIsInMoveMode && mScaleGestureDetector != null) { 
     // Check for a move 
     if (action == MotionEvent.ACTION_MOVE && !mScaleGestureDetector.isInProgress()) { 
      handleMove(event); 
      return true; 
     } 

     // Now a scale 
     mScaleGestureDetector.onTouchEvent(event); 
     return true; 
    } 
+0

Hi Daren, cảm ơn bạn đã trả lời của bạn. Vấn đề là ban đầu tôi muốn cho trình xử lý tiêu chuẩn của View "View.onTouchEvent()" xử lý các nhấp chuột dài để có thể sử dụng trình quản lý menu ngữ cảnh chuẩn. Tự động gọi phương thức "onCreateContextMenu()" của hoạt động này, tạo hộp thoại trình đơn ngữ cảnh, v.v. Nhưng gọi "super.onTouchEvent (event)" từ bên trong phương thức "MyView.onTouchEvent()" của tôi luôn trả về "true" !!! Bạn có thấy bất kỳ khả năng nào để tạo ra a) chuẩn View.onTouchEvent() và b) trình xử lý ScaleGestureDetector.onTouchEvent() hợp tác không? Trân trọng, Nemax – Nemax

+0

Yea, View.onTouchEvent luôn trả về true cho các chế độ xem có thể nhấp. Bạn đã thử gọi super.onTouchEvent() chưa? Nếu điều đó không hiệu quả, hãy thêm máy dò cử chỉ báo chí dài của riêng bạn như trong ví dụ tôi đã đăng ở trên, sau đó gọi performLongClick() khi bạn phát hiện một cú nhấp chuột dài. –

2

Các ScaleGestureDetector cung cấp isInProgress() phương pháp có thể làm những gì bạn muốn ...

Dưới đây là một ví dụ về nó trong sử dụng:

public boolean onTouch(View v, MotionEvent event) { 

    mScaleDetector.onTouchEvent(event); 

    if (!mScaleDetector.isInProgress()) { 
     if (event.getAction() == MotionEvent.ACTION_DOWN || (event.getAction() == MotionEvent.ACTION_MOVE)) { 
      touchX = (int) event.getX(); 
      touchY = (int) event.getY(); 
      isTouched = true; 
     } 

     if (event.getAction() == MotionEvent.ACTION_UP) { 
      isTouched = false; 
     } 
    } else { 
     isTouched = false; 
    } 

    return true; 
} 
+0

Xin chào, trên thực tế, tôi đã sử dụng phương thức "isInProgress()" của ScaleGestureDetector. Cộng với nhiều thủ thuật và phương pháp khác. Xem câu trả lời của tôi cho câu hỏi của tôi ở trên. – Nemax

2

Đây là cách tôi giải quyết được vấn đề: Bằng cách ghi đè phương thức onDispatchTouchEvent() của Acitivity. Bất kỳ giải pháp nào khác dường như không hoạt động. Điều tốt về phương thức onDispatchTouchEvent() là luôn luôn được gọi trước khi chuyển tiếp bất kỳ sự kiện cảm ứng nào tới bất kỳ bộ thu nào khác, vì vậy bạn có thể chặn mọi sự kiện chạm duy nhất tại đây.

Nếu sự kiện được xử lý ở đâu đó ở đây (tỷ lệ hoặc vuốt), tôi quay lại ngay lập tức mà không chuyển tiếp sự kiện đến lớp học siêu hạng, i. e. cho phần còn lại của phân cấp chế độ xem. Nếu không, tôi chuyển tiếp nó đến lớp siêu, vì vậy các quan điểm khác có thể xử lý nó, e. g. để phát hiện các nhấp chuột ngắn hoặc dài.

Có một vài vấn đề khác cần giải quyết: 1. Nếu người dùng bắt đầu một cử chỉ quy mô, tôi phải hủy bất kỳ quy trình phát hiện nhấp chuột dài nào vì chế độ xem nhận sẽ nhận được sự kiện DOWN đầu tiên. ngón tay thứ hai đi xuống và mở rộng quy mô), và sau đó giả tưởng rằng một báo dài đang được thực hiện. 2. Khi một báo dài được thực hiện và menu ngữ cảnh xuất hiện, tôi phải ngăn chặn thao tác vuốt và mở rộng cử chỉ ở đây trong dispatchOnTouchEvent() cho đến khi sự kiện UP tiếp theo, nếu không vuốt và mở rộng sẽ được thực hiện ngay cả khi menu ngữ cảnh ở đó.

Khá phức tạp, nhưng tôi đã dành hàng giờ đồng hồ và rất nhiều thử nghiệm và lỗi, và không thể tìm thấy bất kỳ giải pháp đơn giản nào. Dù sao, xử lý 1. cử chỉ quy mô, 2. cử chỉ swipe ngang, 3. cử chỉ di chuyển dọc, 4. nhấp chuột dài và 5. nhấp chuột ngắn, tất cả trên cùng một mục tiêu (s), không phải là khá đơn giản một nhiệm vụ để thực hiện .. .

Đây là mã (phần liên quan của nó):

@Override 
public boolean dispatchTouchEvent(MotionEvent e) { 
    if (eventInProgress) { 
     // View shall only receive scale gesture event if visible 
     if (targetView.isShown()) 
      scaleGestureDetector.onTouchEvent(e); 
     if (scaleGestureDetector.isInProgress()) 
      motionEventConsumed = true; 
    } 

    if (motionEventConsumed) { 
     if (e.getAction() == MotionEvent.ACTION_UP) 
      motionEventConsumed = false; 
     if (cancelLongPressEvent) { 
      cancelLongPressEvent = false; 
      targetView.cancelLongPress(); 
     } 
     return (true); 
    } 

    // Get the action that was done on this touch event 
    switch (e.getAction()) { 
    case MotionEvent.ACTION_DOWN: { 
     // store the X value when the user's finger was pressed down 
     downXValue = e.getX(); 
     downYValue = e.getY(); 
     cancelLongPressEvent = true; 
     eventInProgress = true; 
     break; 
    } 

    case MotionEvent.ACTION_MOVE: 
     // When having moved by too many x or y pixels, then 
     // cancel any ongoing long klick events 
     if (cancelLongPressEvent 
       && Math.abs(e.getX() - downXValue) 
         + Math.abs(e.getY() - downYValue) > 40) { 
      targetView.cancelLongPress(); 
      cancelLongPressEvent = false; 
     } 
     break; 

    case MotionEvent.ACTION_UP: { 
     if (eventInProgress) { 
      // Get the X value when the user released his/her finger 
      float deltaX = e.getX() - downXValue; 
      float deltaY = e.getY() - downYValue; 
      if (Math.abs(deltaX) > Math.abs(deltaY) 
        && Math.abs(deltaX) > 50) { 
       // going backwards: pushing stuff to the right 
       if (deltaX > 0) { 
        flipRight(); 
        return (true); 
       } 
       // going forwards: pushing stuff to the left 
       if (deltaX < 0) { 
        flipLeft(); 
        return (true); 
       } 
       break; 
      } 
     } 
    } 
    } 

    // If event was not handled here, then forward it to parent, 
    // i. e. to view hierarchy 
    return (super.dispatchTouchEvent(e)); 
} 

[...]

@Override 
public void onCreateContextMenu(ContextMenu menu, View v, 
     ContextMenu.ContextMenuInfo menuInfo) { 
    super.onCreateContextMenu(menu, v, menuInfo); 
    MenuInflater mi = getMenuInflater(); 
    mi.inflate(R.menu.lztv_context_menu, menu); 
    contextMenuTargetView = v; 
    eventInProgress = false; 
} 
Các vấn đề liên quan