2010-11-11 22 views
16

Tôi đang cố gắng phát hiện một sự kiện chạy trốn trên một ứng dụng Android đơn giản, nhưng đối số MotionEvent đầu tiên luôn là rỗng. Tại sao phương thức onFling được gọi với một đối số null? Các Android documentation nói rằng nó được gọi khi một sự kiện fling xảy ra với ban đầu trên MotionEvent xuống và phù hợp với MotionEvent.Android SimpleOnGestureListener.onFling nhận được một MotionEvent rỗng

class MyGestureDetector extends SimpleOnGestureListener { 
    @Override 
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 
     // e1 always == null, return early a null reference exception 
     if (e1 == null) { 
      return false; 
     } 
     if (e1.getY() - e2.getY() > 120) { 
      handleFlingEvent(); 
      return true; 
     } 
     return false; 
    } 
} 

Các Hoạt động chính có phương pháp này onTouchEvent:

GestureDetector flingDetector = new GestureDetector(new MyGestureDetector()); 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    if (flingDetector.onTouchEvent(event)) { 
     return true; 
    } 
    return super.onTouchEvent(event); 
} 

Trả lời

2

Tôi đã có những vấn đề tương tự. Điều đó xảy ra khi GestureDetector và phương thức onFling nằm trong lớp xem tùy chỉnh, là một phần của giao diện người dùng hoạt động. Sau một loạt các thử nghiệm, tôi thấy rằng chỉ có Hoạt động chính mới có thể phát hiện cử chỉ vuốt nhanh. Vì vậy, tôi giải quyết vấn đề bằng cách thay thế chúng trong hoạt động. Nhưng tôi không tìm ra nguyên nhân gốc rễ của vấn đề này.

+0

Tôi đã làm việc đó, nhưng tôi chưa bao giờ có thể xác định điều cuối cùng đã làm.Giải pháp của bạn không áp dụng trong trường hợp của tôi, vì vậy tôi đã chấp nhận câu trả lời của bạn. Tôi vẫn muốn biết tại sao nó không hoạt động. – mcrumley

+0

Tôi cũng thế. Tôi muốn biết tại sao nó không hoạt động tốt. Hy vọng ai đó trả lời điều đó. –

+0

Bạn có may mắn theo dõi nguyên nhân của việc này không? Tôi đang gặp vấn đề tương tự nhưng dường như không thể làm cho nó hoạt động ngay cả với phương thức onFling đang hoạt động chính. –

2

Tôi có 3 nút trong bố cục tuyến tính ngang và bố cục này lần lượt được bao quanh bởi horizontalscrollview.

Sau đó, tôi đặt simplegesturelistener trên số horizontalscrollview và gặp lỗi tương tự như trên. Sau đó, tôi cũng đặt simplegesturelistener cho tất cả các nút trong bố cục và nó hoạt động.

12

Lần đầu tiên tôi gặp sự cố này với Android 4.0 vì mã của tôi hoạt động tốt trong tất cả các phiên bản trước. Sau khi lấy một gợi ý từ các gợi ý ở đây, tôi đã tìm thấy một giải pháp dễ dàng là chỉ theo dõi sự kiện onDown và sử dụng nó thay cho tham số đầu tiên của onFling trong trường hợp nó xảy ra là null.

public class MySimpleGestureListener extends SimpleOnGestureListener { 
    protected MotionEvent mLastOnDownEvent = null; 

    @Override 
    public boolean onDown(MotionEvent e) { 
     mLastOnDownEvent = e; 
     return true;//super.onDown(e); 
    } 

    @Override 
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 
     if (e1==null) 
      e1 = mLastOnDownEvent; 
     if (e1==null || e2==null) 
      return false; 
     float dX = e2.getX()-e1.getX(); 
     float dY = e2.getY()-e1.getY(); 
     ...rest of code 
    } 

    ...rest of class 
} 
+0

Tôi đã thử cách này nhưng chưa khắc phục được sự cố cho tôi. onDown không được gọi và e1 vẫn là null. – fobbymaster

+0

@fobbymaster trong 'onDown' gọi lại chỉ trả về' true' thay vì 'super.onDown (e)' – 0neel

0

Tôi nghĩ rằng sự kiện onDown đã được nối lại bởi scrollview, vì vậy chúng tôi không thể có được sự kiện trong hoạt động này. Nếu bạn tùy chỉnh một ScrollView và ghi đè lên dispatchTouchEvent() và onTouchEvent(), vấn đề sẽ được giải quyết.

Hoạt động:

public class TestActivity extends Activity { 
    private MyScrollView scrollView; 
    private TestActivity me; 
    private GestureDetector detector; 

    protected void onCreate(Bundle savedInstanceState) { 
      this.me = this; 
      MySimpleGestureListener gestureListener = new MySimpleGestureListener(); 
      this.detector = new GestureDetector(gestureListener); 
      this.scrollView.setOnTouchListener(onTouchListerner); 
      this.scrollView.setDetector(detector); 
    } 

    private View.OnTouchListener onTouchListener = new View.OnTouchListener() { 
    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     return me.detector.onTouchEvent(event); 
    } 
}; 
} 

MySimpleGestureListener:

public class MySimpleGestureListener extends SimpleOnGestureListener { 
    @Override 
    public boolean onSingleTapUp(MotionEvent e) { 
     return false; 
    } 

    @Override 
    public void onShowPress(MotionEvent e) { 

    } 

    @Override 
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, 
      float distanceY) { 
     return super.onScroll(e1, e2, distanceX, distanceY); 
    } 

    @Override 
    public void onLongPress(MotionEvent e) { 
    } 


    @Override 
    public boolean onDown(MotionEvent e) { 
     return false; 
    } 

    @Override 
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 
      float velocityY) { 
        // TODO do your onFling here 

    } 
} 

Cuối cùng, MyScrollView

public class MyScrollView extends ScrollView { 
    private GestureDetector detector; 

    @Override 
public boolean dispatchTouchEvent(MotionEvent ev){ 
    if (this.detector!= null) { 
      detector.onTouchEvent(ev); 
     super.dispatchTouchEvent(ev); 
     return true; 
    } 
    return super.dispatchTouchEvent(ev); 
} 

@Override 
public boolean onTouchEvent(MotionEvent ev) { 
    super.onTouchEvent(ev); 
    // 
    if (this.detector != null) { 
     return this.detector.onTouchEvent(ev); 
    } 
    return false; 
} 

    // here is the getter and setter 
} 

Hope trợ giúp này.

3

Trong lớp nhóm chế độ xem tùy chỉnh, bạn cần ghi đè 2 phương pháp: onInterceptTouchEventonTouchEvent. Sau đó, bạn cần gọi số GestureDetector.onTouchEvent() trong cả hai phương pháp. Sự kiện ACTION_DOWN chỉ được chuyển đến onInterceptTouchEvent.

@Override 
public boolean onInterceptTouchEvent(MotionEvent event) { 
    if(mDetector.onTouchEvent(event)) { 
     return true; 
    } 
    return super.onInterceptTouchEvent(event); 
} 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    if(mDetector.onTouchEvent(event)) { 
     return true; 
    } 
    return super.onTouchEvent(event); 
} 
Các vấn đề liên quan