简体   繁体   English

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

[英]Drag and Drop + Fling Detector not working

I'm trying to implement a draggable button that should also be flingable. 我正在尝试实现一个可拖动的可拖动按钮。

Unfortunately the system stops sending MotionEvents after the drag is started. 不幸的是,系统在拖动开始后停止发送MotionEvents。 Therefore the GestureDetector.OnGestureListener.onFling() method is never called. 因此,永远不会调用GestureDetector.OnGestureListener.onFling()方法。

Is there a way to intercept those events before they are consumed by the drag system? 有没有办法在拖拽系统消耗之前拦截这些事件?

I also tried to create my own FlingDetector, but it's not reliable across different devices and screen densities: 我也尝试创建自己的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);
}

}

You can achieve both fling and drag with a button using GestureDetector. 您可以使用GestureDetector通过按钮实现拖动和拖动。 GestureDetector is a little straight forward,its has it's own Default method for handling the following motion event. GestureDetector有点直接,它有自己的Default方法来处理下面的动作事件。

  1. LongPress 长按
  2. Fling 一扔
  3. onDown onDown
  4. onShowPress onShowPress
  5. onSingleTapUp onSingleTapUp
  6. onScroll onScroll

You can Implement Like this. 你可以像这样实施。

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


        });

    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM