Drag and Drop + Fling Detector无法正常工作

时间:2015-12-23 11:04:15

标签: android drag-and-drop onfling

我试图实现一个可拖动的可拖动按钮。

不幸的是,系统在拖动开始后停止发送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);
}

}

1 个答案:

答案 0 :(得分:0)

使用GestureDetector,您可以使用按钮实现拖动和拖动。 GestureDetector有点直接,它有自己的Default方法来处理下面的动作事件。

  1. 长按
  2. 弗林
  3. onDown
  4. onShowPress
  5. onSingleTapUp
  6. onScroll
  7. 你可以像这样实施。

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