网格布局上的Fling手势检测

我想让 "fling "手势检测在我的Android应用程序中工作。

我有一个GridLayout,其中包含9个`ImageView'。来源可以在这里找到。[Romain Guys's Grid Layout][4]。

这个文件来自Romain Guy的Photostream应用程序,只是稍作了修改。

对于简单的点击情况,我只需要为我添加的每个ImageView设置onClickListener,作为实现View.OnClickListener的主要活动'。要实现识别 "fling "的东西似乎要复杂得多。我猜想这是因为它可能跨越视图`?

  • 如果我的活动实现了 OnGestureListener,我不知道如何将其设置为 将其设置为手势监听器,用于 栅格 "或 "图像 "视图的手势监听器。 添加。

     public class SelectFilterActivity extends Activity implements
        View.OnClickListener, OnGestureListener { ...
  • 如果我的活动实现了 OnTouchListener那么我就没有 覆盖 "onFling "方法(它有 它有两个事件作为参数,允许我 来确定是否有飞来的东西是 值得注意的)。

     public class SelectFilterActivity extends Activity implements
         View.OnClickListener, OnTouchListener { ...
  • 如果我做一个自定义的 "视图",比如 "GestureImageView",它扩展了 "ImageView",我不知道如何告诉活动,从视图中发生了 "fling"。无论如何,我试过这样做,当我触摸屏幕时,这些方法没有被调用。

我真的需要一个跨视图工作的具体例子。我应该在什么时候以及如何附加这个 "监听器"?我还需要能够检测到单次点击。

// 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中 "膨胀 "我的子图像视图,我能否将 "手势检测器 "作为构造参数传递给我创建的 "图像视图 "的新子类?

这是一个非常简单的活动,我试图让 "fling "检测发挥作用。SelectFilterActivity (Adapted from photostream).

我一直在看这些资料。

到目前为止,没有任何东西对我有用,我希望得到一些指点。

[4]: https://github.com/selmanon/apps-for-android/blob/master/Photostream/src/com/google/android/photostream/GridLayout.java

解决办法

感谢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);

敬畏地看着你的重载方法被击中,包括活动的onClick(View v)和手势监听器的onFling

public void onClick(View v) {
  Filter f = (Filter) v.getTag();
  FilterFullscreenActivity.show(this, input, f);
}

后面的'fling'舞蹈是可有可无的,但鼓励使用。

评论(23)

上面的刷卡手势检测器代码非常有用!然而,你可能希望通过使用以下相对值(REL_SWIPE)而不是绝对值(SWIPE_)使这个解决方案与密度无关。

DisplayMetrics dm = getResources().getDisplayMetrics();

int REL_SWIPE_MIN_DISTANCE = (int)(SWIPE_MIN_DISTANCE * dm.densityDpi / 160.0f);
int REL_SWIPE_MAX_OFF_PATH = (int)(SWIPE_MAX_OFF_PATH * dm.densityDpi / 160.0f);
int REL_SWIPE_THRESHOLD_VELOCITY = (int)(SWIPE_THRESHOLD_VELOCITY * dm.densityDpi / 160.0f);
评论(7)

也作为一个小的改进。

使用try/catch块的主要原因是e1在最初的运动中可能是空的。除了try/catch之外,还包括对空的测试和返回。 类似于以下内容

if (e1 == null || e2 == null) return false;
try {
...
} catch (Exception e) {}
return false;
评论(0)