android - 拖放 + Fling 检测器不起作用

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

}

最佳答案

您可以使用 GestureDetector 通过按钮实现滑动和拖动。 GestureDetector 有点直截了当,它有自己的默认方法来处理以下运动事件。

  1. 长按
  2. 放纵
  3. onDown
  4. onShowPress
  5. onSingleTapUp
  6. 滚动

你可以这样实现。

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


        });

    }
}

关于android - 拖放 + Fling 检测器不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34434241/

相关文章:

android - ListView中的OnFling,获取滑动的Item信息

Android OnGestureListener Fling 未检测到

android - 如何加密我的密码 - Android Studio

Android - 劫持点击

android - 简单的 kivy 选项卡示例

java - 仅此网站无法拖放 Selenium

c# - 像 Winspector Spy 一样拖放

java - 对象静态实例内的数组被销毁

javascript - 在页面上拖放文件——缺乏一致的解决方案

android - 如何更改 Android Gallery 中的最小滑动距离?