2015-12-23 17 views
6

Sto provando a implementare un pulsante trascinabile che dovrebbe essere anche flingable.Drag and Drop + Rilevatore fiammifero non funzionante

Sfortunatamente il sistema interrompe l'invio di MotionEvents dopo l'avvio del trascinamento. Pertanto, il metodo GestureDetector.OnGestureListener.onFling() non viene mai chiamato.

C'è un modo per intercettare quegli eventi prima che vengano consumati dal sistema di trascinamento?

Ho anche cercato di creare il mio FlingDetector, ma non è affidabile su dispositivi diversi e densità dello schermo:

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

Ho implementato qualcosa di simile in una libreria. Vedere "GestureDetectorCompat" [qui] (https://github.com/ericbhatti/floaties/blob/master/FloatiesLibrary/floaties/src/main/java/com/bezyapps/floatieslibrary/Floaty.java). Spero che sia d'aiuto. –

+0

@timoschloesser tenta di accedere alla posizione mentre viene trascinato .... e se la posizione è cambiata molto velocemente. è lanciato. prova a utilizzare getAction() e ACTION_DRAG_LOCATION. non so come puoi misurare la velocità. –

risposta

0

si può ottenere sia scappatella e trascinare con un pulsante tramite GestureDetector. GestureDetector è un po 'semplice, ha il suo metodo predefinito per la gestione del seguente evento di movimento.

  1. longpress
  2. Fling
  3. onDown
  4. onShowPress
  5. onSingleTapUp
  6. onscroll

è possibile implementare Ti piace questa.

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


     }); 

    } 
}