Drag and Drop + Fling Detector no funciona

Estoy tratando de implementar un botón arrastrable que también debe ser flingable.

Desafortunadamente, el sistema deja de enviar MotionEvents después de arrancar el arrastre. Por lo tanto, el método GestureDetector.OnGestureListener.onFling () nunca se llama.

¿Hay una manera de interceptar esos eventos antes de que sean consumidos por el sistema de arrastre?

También traté de crear mi propio FlingDetector, pero no es fiable a través de diferentes dispositivos y densidades de pantalla:

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); } } 

Puede lograr arrastrar y arrastrar con un botón usando GestureDetector. GestureDetector es un poco sencillo, tiene su propio método por defecto para manejar el siguiente evento de movimiento.

  1. Pulsación larga
  2. Arrojar
  3. Hacía abajo
  4. OnShowPress
  5. OnSingleTapUp
  6. OnScroll

Usted puede implementar de esta manera.

 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; } }); } } 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.