在网格布局上检测拖动手势
在网格布局上检测拖动手势
我想在我的Android应用程序中实现fling
手势检测。
我有一个包含9个ImageView
的GridLayout
,可以在此处找到源代码:Romain Guys的Grid布局。
我使用的文件来自Romain Guy的Photostream应用程序,只进行了轻微的调整。
对于简单的点击情况,我只需要将我添加的每个ImageView
的onClickListener
设置为实现View.OnClickListener
的主要activity
即可。似乎更复杂的是实现识别fling
的功能。我认为这是因为它可能跨越多个views
。
- 如果我的
activity
实现了OnGestureListener
,我不知道如何将其设置为Grid
或Image
视图的手势监听器。public class SelectFilterActivity extends Activity implements View.OnClickListener, OnGestureListener { ...
- 如果我的
activity
实现了OnTouchListener
,那么我就没有onFling
方法可以重写(它有两个事件作为参数,允许我确定这个fling
是否值得注意)。public class SelectFilterActivity extends Activity implements View.OnClickListener, OnTouchListener { ...
- 如果我创建一个自定义的
View
,比如GestureImageView
,它扩展了ImageView
,我不知道如何告诉activity
从视图中检测到一个fling
。无论如何,我尝试过这个,但是当我触摸屏幕时,方法没有被调用。
我真的只需要一个跨视图工作的具体示例。我应该在什么时候以及如何附加这个listener
?我需要能够检测单击。
// Gesture detection mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() { public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { int dx = (int) (e2.getX() - e1.getX()); // don't accept the fling if it's too short // as it may conflict with a button push if (Math.abs(dx) > MAJOR_MOVE && Math.abs(velocityX) > Math.absvelocityY)) { if (velocityX > 0) { moveRight(); } else { moveLeft(); } return true; } else { return false; } } });
是否有可能在屏幕顶部放置一个透明视图来捕捉滑动手势?
如果不从XML中inflate
我的子图像视图,我可以将GestureDetector
作为构造函数参数传递给我创建的新ImageView
子类吗?
这是我正试图使fling
检测起作用的非常简单的活动:SelectFilterActivity (Adapted from photostream)。
我一直在看这些资源:
到目前为止都没有起作用,我希望能得到一些指点。
以上的一个答案提到了处理不同像素密度,但建议手动计算刷卡参数。值得注意的是,您实际上可以使用ViewConfiguration
类从系统获取缩放的合理值:
final ViewConfiguration vc = ViewConfiguration.get(getContext()); final int swipeMinDistance = vc.getScaledPagingTouchSlop(); final int swipeThresholdVelocity = vc.getScaledMinimumFlingVelocity(); final int swipeMaxOffPath = vc.getScaledTouchSlop(); // (there is also vc.getScaledMaximumFlingVelocity() one could check against)
我注意到使用这些值会导致滑动的“感觉”在应用和系统的其余部分之间更加一致。
感谢Code Shogun,我在其中的代码中作出了适应性的调整。
让你的活动像往常一样实现OnClickListener
:
public class SelectFilterActivity extends Activity implements OnClickListener { private static final int SWIPE_MIN_DISTANCE = 120; private static final int SWIPE_MAX_OFF_PATH = 250; private static final int SWIPE_THRESHOLD_VELOCITY = 200; private GestureDetector gestureDetector; View.OnTouchListener gestureListener; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /* ... */ // Gesture detection gestureDetector = new GestureDetector(this, new MyGestureDetector()); gestureListener = new View.OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { return gestureDetector.onTouchEvent(event); } }; } class MyGestureDetector extends SimpleOnGestureListener { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { try { if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) return false; // right to left swipe if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { Toast.makeText(SelectFilterActivity.this, "Left Swipe", Toast.LENGTH_SHORT).show(); } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { Toast.makeText(SelectFilterActivity.this, "Right Swipe", Toast.LENGTH_SHORT).show(); } } catch (Exception e) { // nothing } return false; } @Override public boolean onDown(MotionEvent e) { return true; } } }
将手势监听器附加到添加到主布局的所有视图;
// Do this for each view added to the grid imageView.setOnClickListener(SelectFilterActivity.this); imageView.setOnTouchListener(gestureListener);
当你的重写方法被调用时感到惊奇,包括activity的onClick(View v)
和手势监听器的onFling
。
public void onClick(View v) { Filter f = (Filter) v.getTag(); FilterFullscreenActivity.show(this, input, f); }
后续的“fling”舞蹈是可选的,但值得鼓励。