在网格布局上进行手势检测

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

我拥有的是一个包含9个ImageViewGridLayout 。 来源可以在这里找到:Romain Guys的网格布局。

我使用的文件来自Romain Guy的Photostream应用程序,并且只是稍作改动。

对于简单的点击情况我只需要设置onClickListener每个ImageView我添加是主要的activity ,它实现View.OnClickListener 。 实施能够识别fling东西似乎是无限复杂的。 我认为这是因为它可能会跨越views

  • 如果我的活动实现了OnGestureListener我不知道如何将它设置为我添加的GridImage视图的手势监听器。

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

    public class SelectFilterActivity extends Activity implements
        View.OnClickListener, OnTouchListener { ...
    
  • 如果我做一个自定义的View ,如GestureImageView扩展ImageView ,我不知道怎么跟一个活动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;
            }
        }
    });
    

    是否可以在屏幕顶部放置透明视图来捕捉fl光?

    如果我选择不inflate从XML我的孩子形象的意见我可以传递GestureDetector作为构造函数参数的一个新的子类ImageView ,我创造?

    这是我试图让fling检测工作的非常简单的活动:SelectFilterActivity(从照片流改编)。

    我一直在看这些来源:

  • 检测手势 - 教程

  • SDK文档

  • 计算器代码

  • 到目前为止,我没有任何工作,我希望得到一些指示。


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

    onFling观看重写的方法,即活动的onClick(View v)和手势监听器的onFling

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

    这个帖子'扔'舞是可选的,但鼓励。


    上面的答案之一提到处理不同的像素密度,但建议手动计算滑动参数。 值得注意的是,您实际上可以使用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)
    

    我注意到,使用这些值会导致应用程序和系统其余部分之间的投掷“感觉”更加一致。


    我做了一些改变,写了一个额外的检测器类来实现View.onTouchListener

    onCreate简单地将它添加到像这样的最低布局:

    ActivitySwipeDetector activitySwipeDetector = new ActivitySwipeDetector(this);
    lowestLayout = (RelativeLayout)this.findViewById(R.id.lowestLayout);
    lowestLayout.setOnTouchListener(activitySwipeDetector);
    

    其中id.lowestLayout是布局层次结构中视图最低的id.xxx,而lowestLayout则声明为RelativeLayout

    然后是实际活动滑动检测器类:

    public class ActivitySwipeDetector implements View.OnTouchListener {
    
    static final String logTag = "ActivitySwipeDetector";
    private Activity activity;
    static final int MIN_DISTANCE = 100;
    private float downX, downY, upX, upY;
    
    public ActivitySwipeDetector(Activity activity){
        this.activity = activity;
    }
    
    public void onRightSwipe(){
        Log.i(logTag, "RightToLeftSwipe!");
        activity.doSomething();
    }
    
    public void onLeftSwipe(){
        Log.i(logTag, "LeftToRightSwipe!");
        activity.doSomething();
    }
    
    public void onDownSwipe(){
        Log.i(logTag, "onTopToBottomSwipe!");
        activity.doSomething();
    }
    
    public void onUpSwipe(){
        Log.i(logTag, "onBottomToTopSwipe!");
        activity.doSomething();
    }
    
    public boolean onTouch(View v, MotionEvent event) {
        switch(event.getAction()){
            case MotionEvent.ACTION_DOWN: {
                downX = event.getX();
                downY = event.getY();
                return true;
            }
            case MotionEvent.ACTION_UP: {
                upX = event.getX();
                upY = event.getY();
    
                float deltaX = downX - upX;
                float deltaY = downY - upY;
    
           // swipe horizontal?
            if(Math.abs(deltaX) > Math.abs(deltaY))
            {
                if(Math.abs(deltaX) > MIN_DISTANCE){
                    // left or right
                    if(deltaX > 0) { this.onRightSwipe(); return true; }
                    if(deltaX < 0) { this.onLeftSwipe(); return true; }
                }
                else {
                        Log.i(logTag, "Horizontal Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
                        return false; // We don't consume the event
                }
            }
            // swipe vertical?
            else 
            {
                if(Math.abs(deltaY) > MIN_DISTANCE){
                    // top or down
                    if(deltaY < 0) { this.onDownSwipe(); return true; }
                    if(deltaY > 0) { this.onUpSwipe(); return true; }
                }
                else {
                        Log.i(logTag, "Vertical Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
                        return false; // We don't consume the event
                }
            }
    
                return true;
            }
        }
        return false;
    }
    
    }
    

    对我真的很好!

    链接地址: http://www.djcxy.com/p/24149.html

    上一篇: Fling gesture detection on grid layout

    下一篇: Set environment variables from file