2015-12-23 142 views
6

我試圖實現一個可拖動的按鈕,它也應該是可以扔掉的。Drag and Drop + Fling Detector not working

不幸的是,系統在拖動開始後停止發送MotionEvents。因此GestureDetector.OnGestureListener.onFling()方法永遠不會被調用。

有沒有辦法在阻塞系統消耗這些事件之前攔截這些事件?

我也試圖創建自己的FlingDetector,但它不是在不同的設備和屏幕密度可靠:

public class FlingDetector { 

private final int MIN_FLING_SPEED = 3; 

private OnFlingListener mOnFlingListener; 

private float mCurrentX = 0; 
private float mCurrentY = 0; 
private long mLastMovementTime = 0; 
private double mCurrentVelocity = 0; 

private final float mDensity; 

public FlingDetector(OnFlingListener onFlingListener, Context context) { 
    mOnFlingListener = onFlingListener; 
    mDensity = context.getResources().getDisplayMetrics().density; 
} 


public void onMovementStart(float x, float y) { 
    mCurrentX = x; 
    mCurrentY = y; 
    mLastMovementTime = System.currentTimeMillis(); 
    mCurrentVelocity = 0; 
} 

public void onMovementEnd(float x, float y) { 

    long currentTime = System.currentTimeMillis(); 

    float distanceX = Math.abs(mCurrentX - x)/mDensity; 
    float distanceY = Math.abs(mCurrentY - y)/mDensity; 

    float distance = (float) Math.sqrt(Math.pow(distanceX, 2) + 
      Math.pow(distanceY, 2)); 

    mCurrentVelocity = (distance/(currentTime - mLastMovementTime)); 

    if(mCurrentVelocity > MIN_FLING_SPEED) { 
     mOnFlingListener.onFling((int) (mCurrentVelocity + 0.5)); 
    } else { 
     Log.d("test", "Distance: " + distance); 
     Log.d("test", "Time Delta: " + (currentTime - mLastMovementTime)); 
     Log.d("test", "Speed: " + mCurrentVelocity); 
    } 
} 

public interface OnFlingListener { 
    void onFling(int speed); 
} 

} 
+0

我在庫中實現了類似的東西。請參閱'GestureDetectorCompat' [here](https://github.com/ericbhatti/floaties/blob/master/FloatiesLibrary/floaties/src/main/java/com/bezyapps/floatieslibrary/Floaty.java)。希望能幫助到你。 –

+0

@timoschloesser嘗試訪問位置,而拖動....,如果位置變化非常快。它被絆倒。嘗試使用getAction()和ACTION_DRAG_LOCATION。我不知道你如何測量速度。 –

回答

0

可以達到既一扔並拖動使用GestureDetector按鈕。GestureDetector有點簡單,它有它自己的Default方法來處理下面的運動事件。

  1. 長按
  2. 一扔
  3. onDown
  4. onShowPress
  5. onSingleTapUp
  6. onScroll

可以實現諸如此。

public class MainActivity extends AppCompatActivity { 

    Button button; 
    GestureDetector buttonGestureDetector; 
    static final int SWIPE_MIN_DISTANCE = 60; 
    static final int SWIPE_THRESHOLD_VELOCITY = 100; 




    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     button=(Button) findViewById(R.id.button); 

     buttonGestureDetector=new GestureDetector(this,new GestureDetector.OnGestureListener() { 
      @Override 
      public boolean onDown(MotionEvent e) { 
       return false; 
      } 

      @Override 
      public void onShowPress(MotionEvent e) { 

      } 

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

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

      @Override 
      public void onLongPress(MotionEvent e) { 
       Log.i("Drag","DragListening"); 
       View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(button); 
       button.startDrag(null, shadowBuilder, button, 0); 
       button.setVisibility(View.INVISIBLE); 



      } 

      @Override 
      public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 

       Log.i("FlingListened","FlingListened"); 

       if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
        Toast.makeText(MainActivity.this,"OnRightToLeft Fling",Toast.LENGTH_SHORT).show(); 
       } 
       else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) 
       { 
        Toast.makeText(MainActivity.this,"OnLeftToRight Fling",Toast.LENGTH_SHORT).show(); 
       } 
       if (e1.getY() - e2.getY() > SWIPE_MIN_DISTANCE && Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) { 

        Toast.makeText(MainActivity.this,"onBottomToTop Fling",Toast.LENGTH_SHORT).show(); 

       } 
       else if (e2.getY() - e1.getY() > SWIPE_MIN_DISTANCE && Math.abs(velocityY) > SWIPE_THRESHOLD_VELOCITY) { 
        Toast.makeText(MainActivity.this,"OnTopToBottom Fling",Toast.LENGTH_SHORT).show(); 

       } 
       return true; 


      } 
     }); 

     button.setOnTouchListener(new View.OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       buttonGestureDetector.onTouchEvent(event); 
       return false; 


      } 
     }); 

      button.setOnDragListener(new View.OnDragListener() { 
      @Override 
      public boolean onDrag(View dragView, DragEvent event) 
      { 

       int action = event.getAction(); 
       switch (action) { 
        case DragEvent.ACTION_DRAG_STARTED: 
         Log.d("Drag", "Drag event started"); 
         break; 
        case DragEvent.ACTION_DRAG_ENTERED: 
         Log.d("Drag", "Drag event entered into "+dragView.toString()); 
         break; 
        case DragEvent.ACTION_DRAG_EXITED: 
         Log.d("Drag", "Drag event exited from "+dragView.toString()); 
         break; 
        case DragEvent.ACTION_DROP: 
         Log.d("Drag", "Dropped"); 
         View view = (View) event.getLocalState(); 
         ViewGroup owner = (ViewGroup) view.getParent(); 
         owner.removeView(view); 
         LinearLayout container = (LinearLayout) dragView; 
         container.addView(view); 
         view.setVisibility(View.VISIBLE); 
         break; 
        case DragEvent.ACTION_DRAG_ENDED: 
         Log.d("Drag", "Drag ended"); 
         break; 
        default: 
         break; 
       } 
       return true; 
      } 


     }); 

    } 
}