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

我有一个GridLayout,包含9个ImageViews。来源可以在这里找到:罗曼家伙的网格布局。

我从Romain Guy的Photostream应用程序中获取的文件只做了轻微的修改。

对于简单的点击情况,我只需要为每个ImageView设置onClickListener,我添加为实现View.OnClickListener的主要活动。实现能够识别投掷的东西似乎要复杂得多。我猜这是因为它可能跨越不同的观点?

If my activity implements OnGestureListener I don't know how to set that as the gesture listener for the Grid or the Image views that I add. public class SelectFilterActivity extends Activity implements View.OnClickListener, OnGestureListener { ... If my activity implements OnTouchListener then I have no onFling method to override (it has two events as parameters allowing me to determine if the fling was noteworthy). public class SelectFilterActivity extends Activity implements View.OnClickListener, OnTouchListener { ... If I make a custom View, like GestureImageView that extends ImageView I don't know how to tell the activity that a fling has occurred from the view. In any case, I tried this and the methods weren't called when I touched the screen.

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

// 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膨胀我的子图像视图,我可以通过手势检测器作为构造函数参数到我创建的ImageView的新子类吗?

这是一个非常简单的活动,我试图让飞动检测工作:SelectFilterActivity(改编自photostream)。

我一直在看这些资料:

检测手势-教程 SDK文档 计算器的代码

到目前为止,什么都没用,我希望能得到一些指导。


当前回答

如果你不喜欢创建一个单独的类或者让代码变得复杂, 你可以在OnTouchListener中创建一个GestureDetector变量,让你的代码更简单

namVyuVar可以是你需要设置监听器的视图的任何名称

namVyuVar.setOnTouchListener(new View.OnTouchListener()
{
    @Override
    public boolean onTouch(View view, MotionEvent MsnEvtPsgVal)
    {
        flingActionVar.onTouchEvent(MsnEvtPsgVal);
        return true;
    }

    GestureDetector flingActionVar = new GestureDetector(getApplicationContext(), new GestureDetector.SimpleOnGestureListener()
    {
        private static final int flingActionMinDstVac = 120;
        private static final int flingActionMinSpdVac = 200;

        @Override
        public boolean onFling(MotionEvent fstMsnEvtPsgVal, MotionEvent lstMsnEvtPsgVal, float flingActionXcoSpdPsgVal, float flingActionYcoSpdPsgVal)
        {
            if(fstMsnEvtPsgVal.getX() - lstMsnEvtPsgVal.getX() > flingActionMinDstVac && Math.abs(flingActionXcoSpdPsgVal) > flingActionMinSpdVac)
            {
                // TskTdo :=> On Right to Left fling

                return false;
            }
            else if (lstMsnEvtPsgVal.getX() - fstMsnEvtPsgVal.getX() > flingActionMinDstVac && Math.abs(flingActionXcoSpdPsgVal) > flingActionMinSpdVac)
            {
                // TskTdo :=> On Left to Right fling

                return false;
            }

            if(fstMsnEvtPsgVal.getY() - lstMsnEvtPsgVal.getY() > flingActionMinDstVac && Math.abs(flingActionYcoSpdPsgVal) > flingActionMinSpdVac)
            {
                // TskTdo :=> On Bottom to Top fling

                return false;
            }
            else if (lstMsnEvtPsgVal.getY() - fstMsnEvtPsgVal.getY() > flingActionMinDstVac && Math.abs(flingActionYcoSpdPsgVal) > flingActionMinSpdVac)
            {
                // TskTdo :=> On Top to Bottom fling

                return false;
            }
            return false;
        }
    });
});

其他回答

如果你不喜欢创建一个单独的类或者让代码变得复杂, 你可以在OnTouchListener中创建一个GestureDetector变量,让你的代码更简单

namVyuVar可以是你需要设置监听器的视图的任何名称

namVyuVar.setOnTouchListener(new View.OnTouchListener()
{
    @Override
    public boolean onTouch(View view, MotionEvent MsnEvtPsgVal)
    {
        flingActionVar.onTouchEvent(MsnEvtPsgVal);
        return true;
    }

    GestureDetector flingActionVar = new GestureDetector(getApplicationContext(), new GestureDetector.SimpleOnGestureListener()
    {
        private static final int flingActionMinDstVac = 120;
        private static final int flingActionMinSpdVac = 200;

        @Override
        public boolean onFling(MotionEvent fstMsnEvtPsgVal, MotionEvent lstMsnEvtPsgVal, float flingActionXcoSpdPsgVal, float flingActionYcoSpdPsgVal)
        {
            if(fstMsnEvtPsgVal.getX() - lstMsnEvtPsgVal.getX() > flingActionMinDstVac && Math.abs(flingActionXcoSpdPsgVal) > flingActionMinSpdVac)
            {
                // TskTdo :=> On Right to Left fling

                return false;
            }
            else if (lstMsnEvtPsgVal.getX() - fstMsnEvtPsgVal.getX() > flingActionMinDstVac && Math.abs(flingActionXcoSpdPsgVal) > flingActionMinSpdVac)
            {
                // TskTdo :=> On Left to Right fling

                return false;
            }

            if(fstMsnEvtPsgVal.getY() - lstMsnEvtPsgVal.getY() > flingActionMinDstVac && Math.abs(flingActionYcoSpdPsgVal) > flingActionMinSpdVac)
            {
                // TskTdo :=> On Bottom to Top fling

                return false;
            }
            else if (lstMsnEvtPsgVal.getY() - fstMsnEvtPsgVal.getY() > flingActionMinDstVac && Math.abs(flingActionYcoSpdPsgVal) > flingActionMinSpdVac)
            {
                // TskTdo :=> On Top to Bottom fling

                return false;
            }
            return false;
        }
    });
});

上面的滑动手势检测代码非常有用!但是,您可能希望通过使用以下相对值(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);

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

我注意到,使用这些值可以使应用程序和系统其他部分之间的“感觉”更加一致。

也作为一个小的改进。

使用try/catch块的主要原因是e1在初始移动时可能为空。除了try/catch之外,还包括一个null和return测试。 类似如下

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

所有人:不要忘记case MotionEvent。ACTION_CANCEL:

它调用30%的滑动没有ACTION_UP

在这里它等于ACTION_UP