我想让飞的手势检测工作在我的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文档 计算器的代码

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


当前回答

在web(和本页)上有一些主张使用ViewConfiguration.getScaledTouchSlop()为SWIPE_MIN_DISTANCE设置一个设备缩放值。

getScaledTouchSlop()用于“滚动阈值”距离,而不是滑动距离。滚动阈值距离必须小于“页面之间的摆动”阈值距离。例如,这个函数在我的三星GS2上返回12个像素,而本页引用的示例大约是100个像素。

与API级别8 (Android 2.2, Froyo),你有getScaledPagingTouchSlop(),用于页面滑动。 在我的设备上,它返回24(像素)。所以如果你的API级别< 8,我认为“2 * getScaledTouchSlop()”应该是“标准”的滑动阈值。 但是我的小屏幕应用程序的用户告诉我,它太少了……在我的应用程序中,你可以垂直滚动,水平切换页面。有了建议的值,他们有时会改变页面,而不是滚动。

其他回答

这里有很多很好的信息。不幸的是,许多这种抛抛处理代码以不同的完成状态分散在不同的站点上,尽管人们会认为这对许多应用程序来说是必不可少的。

我已经花时间创建了一个fling侦听器,用于验证是否满足适当的条件。我添加了一个页抛监听器,它添加了更多检查,以确保页抛满足页抛的阈值。这两个侦听器都允许您轻松地将投掷限制在水平轴或垂直轴上。你可以看到它是如何在滑动图像的视图中使用的。我承认这里的人已经做了大部分的研究——我只是把它们放在一个可用的图书馆里。

这几天是我第一次尝试在Android上编写代码;期待更多。

我做的有点不同,并编写了一个额外的检测器类来实现View.onTouchListener

onCreateis简单地把它添加到最低的布局,就像这样:

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;
}

}

对我来说真的很好!

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

有一个内置的界面,你可以直接使用所有的手势: 下面是对基本级别用户的解释: 有两个进口品在选择时要小心,因为它们都是不同的