我试图实现一个可拖动的可拖动按钮。
不幸的是,系统在拖动开始后停止发送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);
}
}
答案 0 :(得分:0)
使用GestureDetector,您可以使用按钮实现拖动和拖动。 GestureDetector有点直接,它有自己的Default方法来处理下面的动作事件。
你可以像这样实施。
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;
}
});
}
}