我正在尝试实现一个可拖动的按钮,该按钮也应该是可滑动的。
不幸的是,系统在拖动开始后停止发送 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 有点直截了当,它有自己的默认方法来处理以下运动事件。
- 长按
- 放纵
- onDown
- onShowPress
- onSingleTapUp
- 滚动
你可以这样实现。
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/