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.
- Implementación de Fling en lienzo android
- Android Cómo llamar a OnFling cuando Swiping en cualquier lugar de la actividad no sólo en el ViewFlipper
- Detectar el fin del fling en ScrollView
- Mostrando un botón de eliminación en el desplazamiento de un listview para Android
- Android - Detección de gestos (deslizar hacia arriba / hacia abajo) en una vista determinada
¿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); } }
- Android: desplazamiento ViewPager basado en la velocidad
- Adición de Fling Gesture a una vista de imagen - Android
- Onfling () no se llama por alguna razón
- Android de izquierda a derecha solamente
- Stop scrollView en el centro del rollo
- Uso de onFling y ViewPager
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.
- Pulsación larga
- Arrojar
- Hacía abajo
- OnShowPress
- OnSingleTapUp
- 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; } }); } }