【问题标题】:Gesture Listener onFling Not Acting Consistant手势监听器 onFling 不一致
【发布时间】:2013-06-06 20:42:13
【问题描述】:

更新:查看扩展问题的赏金。

我在ListView 上设置了GestureDetector。 ListView 是一个完整的片段,它来自窗口的一侧并部分覆盖另一个片段。我想让用户能够将其滑动关闭(即 Wunderlist 是右侧此功能的一个很好的示例)。

这是我的设置:

    gestureListener = new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {

            if (gestureDetector.onTouchEvent(event)) {
                return true;
            }

            return false;
        }
    };
    listView.setOnTouchListener(gestureListener); 

监听器本身:

public class GestureListener extends SimpleOnGestureListener {

        private static final int SWIPE_MIN_DISTANCE = 180;
        private static final int SWIPE_THRESHOLD_VELOCITY = 50;

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                float velocityY) {

            try {
                if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
                        && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {

                    FragmentManager fma = getActivity()
                            .getSupportFragmentManager();



                    FragmentManager fm = getFragmentManager();
                    FragmentTransaction t = fm.beginTransaction();

                    SherlockListFragment mFrag = new RateReviewFragment();

                    t.add(R.id.main_frag, mFrag);
                    t.setCustomAnimations(R.anim.animation_enter,
                            R.anim.animation_leave);
                    t.remove(mFrag);
                    t.commit();

                }
                return false;
            } catch (Exception e) {

            }
            return false;
        }





        @Override
        public void onLongPress(MotionEvent e) {

            // edited out; this opens up a context menu
        }

    }

有时,当ListView 滚动到底部(或列表滚动因单击列表行而中断)时,GestureListener 会停止……听。刷卡将不起作用。您必须滚动回顶部才能使其再次工作。

如果有人能帮我找出这些问题,我将不胜感激!

更新:只剩下一个问题,“听者停止听”

更新二:我可能已经弄清楚是什么原因造成的;只是不知道解决方法:

我在记录我的操作后发现了一些东西;我在列表中的位置越低(我与之交互的次数越多),测量值就不一致。例如,如果我将手指左右移动一厘米 - 在列表的最顶部,它会说我移动了,例如,200 像素。但是当我遇到上述问题时,对于 SAME 1 厘米的距离来说,它要低得多,可能是 50。所以窗口不会关闭,因为它不符合我的if 条件。

旁注:我不止一次说过,问题出在“与列表交互”时。这意味着:如果我从上到下快速滚动;没有任何问题;但是如果我慢慢地向下工作,也许点击屏幕,打开和关闭,点击listView上的按钮,其中一些打开一个新的活动(然后回到相同的位置),这就是“互动”与”。

【问题讨论】:

标签: android listview gestures


【解决方案1】:

试试这个,

    gestureDetector = new GestureDetector(getActivity(),
            new GestureListener());
    View.OnTouchListener gestureListener = new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
           listView.onTouchEvent(event);
           gestureDetector.onTouchEvent(event);

            return true;
        }
    };
    listView.setOnTouchListener(gestureListener);

并进行以下更改

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
                float distanceX, float distanceY) {
  return true;
}

编辑: 我看到了应用程序奇妙清单,如果您想模拟该功能,请尝试这种方法,

将 onInterceptTouch 用于根布局(listView 是其子布局),在此方法中,您必须检查用户是否像以下那样滑动,

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
  if (ev.getAction() == MotionEvent.ACTION_MOVE) {
    if(/* Check your condition here */) { 
      // User has swiped 
      return true;
    }
  }

  return false; // return false so that the event will be passed to child views.
}

更多信息Android onInterceptTouchEvent

【讨论】:

  • 嘿,谢谢你的建议;不幸的是,我仍然偶尔会失去滑动窗口的能力。
  • 根据我使用 Android 的经验,您不能期望设备始终为用户交互提供正确的(“预期”是一个更好的词)接触点。由我们(开发人员)来处理这种情况,所以为什么不玩一下 onFling() 内部的 if 条件来选择 8/10 倍可以工作的最佳条件。希望对你有帮助
  • 我同意。如果您看到我更新的问题,我会发现一个巨大的不一致之处。虽然我知道有办法做到这一点,但奇妙清单完美地执行了它。
  • 我正在了解更多有关此的信息;在您上面的答案中,您有/* Check your condition here */ - 我的情况需要特定的onFling() 属性,例如两个motionEvent 值(不是一个)和velocity。我如何在这里检查我的状况?
  • 有很多方法可以做到这一点,其中一种被指出是@neil 在他的回答中作为“第三”,但我建议在速度跟踪器的帮助下解决这个问题 (developer.android.com/reference/android/view/…)。
【解决方案2】:

以这种方式更改 onTouch:

@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
     boolean consumed = gestureDetector.onTouchEvent(event);
     if (event.getAction() == MotionEvent.ACTION_MOVE) {
                return false;
     }

    return consumed;
}

【讨论】:

  • 谢谢。将测试... 问题:我不认为 onTouch 是这个 SimpleOnGesture 方法的一部分?
  • 仍然是gestureDetector将触摸事件转发给它
  • 这似乎有相反的效果。它会杀死整个滑动关闭功能;然而以上三个问题仍然是个问题。
  • 所以你可以滚动 ListView 但没有触发?
  • 抱歉,fling 又回来了,但卷轴也有同样的问题....(就像 fling 一样)我非常感谢您的帮助,并期待提供这些积分。这是我正在开发的这个应用程序中的问题。
【解决方案3】:

不确定这是否会有所帮助,因为上帝知道所有这些碎片问题的幕后情况,但试试这个:

在调用 onTouch 之后,在返回 false 之前检查 gestureDetector 是否还活着(不是 null),(通过向 listview 类发送回调或其他东西)如果不是创建它的新实例并再次调用

listView.setOnTouchListener(gestureListener); 

【讨论】:

  • 好吧,我 Log.d gestureListener,我不相信它曾经为空。我将我的listView 放在我的onFling 不起作用的位置,并且侦听器仍在记录一些东西......如果它为空,那么日志似乎会显示这个?
  • 尽我所能尝试使用慢作为污垢调试系统并且很难判断它是否为空...我做了Log.d 以查看何时调用eventonFling .有好几次,即使我在刷卡,Fragment 也没有对 Fling 做出反应,它们都被调用了。这几乎表明我的 Fling 代码是错误的?但我相信所有滑动都符合长度和速度的标准。
【解决方案4】:

第一

我注意到,在您的手势监听器中,您在 onDown 中返回 true。如果我正确理解了您的问题,您将为ListView 留下点击和垂直滑动事件,因此您只对代码中的水平滑动事件感兴趣。

为什么不删除所有您不感兴趣的功能,从而将您不感兴趣的所有内容留给ListView?如果你必须拥有它们,至少返回false,这是默认设置(参见here)。

顺便说一句,AbsListViewListView 的父级)的 code 显示了一个非常复杂的状态系统,用于处理点击和滑动,因此在我看来,最好尽可能保持原样

其次

鉴于您最近的观察,也许关键是要考虑 X 和 Y 位移之间的比率,而不是滑动的绝对大小。虽然我无法解释报告的滑动大小的变化,但我们真正感兴趣的是主要是水平的运动,即:

(change in X) >> (change in Y)

这可以通过以下方式实现:

if ((velocityY == 0.0f) || (Math.abs(velocityX/velocityY) > 3.0f) {
    // The movement is predominantly horizontal
    // Put other checks here (like direction and so on)
    // Then do the stuff
}

这具有不使用e1e2 的优点,这将我们带到...

第三

正如您所注意到的,问题在于您何时与列表视图进行了交互。此时,Event 中可能报告了多个指针。不能保证它们返回的默认 X 和 Y 信息与任何特定的指针事件相关。如果您确实想要进行涉及 X 和 Y 的计算,则可能值得检查您是否正在比较来自同一指针事件的信息,使用类似:

int numPointers = e1.getPointerCount();
for (int pointerIndex1 = 0; pointerIndex1 < numPointers; pointerIndex1++) {
    int pointerId = e1.getPointerId(pointerIndex1);
    // find index for pointerId in e2.

    float deltaX = e2.getX(pointerIndex2) - e1.getX(pointerIndex1);
    // and so on
}

【讨论】:

  • 我在记录我的操作后发现了一些东西;我在列表中的位置越低(我与之交互的次数越多),测量值就不一致。例如,如果我将手指左右移动一厘米 - 在列表的最顶部,它会说我移动了,例如,200 像素。但是当我遇到上述问题时,对于相同的 1 厘米距离,它要低得多,可能是 50。所以窗口不会关闭,因为它不符合我的 if 条件。
  • 嘿,我再次感谢您的反馈。我会看看我的发现并及时通知你。
【解决方案5】:

首先尝试使OnTouchListener 像这样:

View.OnTouchListener gestureListener = new View.OnTouchListener() {
    public boolean onTouch(View v, MotionEvent event) {
    gestureDetector.onTouchEvent(event);
        return true;
    }
};

那么 - 你总是在 onFling() 中返回 false。在try/catch 子句中返回true。并尝试将相同的数据传递给 onFling 内 else 子句中的 onScroll 方法。

【讨论】:

  • 我一直对此有些困惑;与true 相比,返回false 有什么作用?同样将onFling() 中的FIRST false 更改为true 基本上会影响正常的listView 滚动。它会让你滚动列表,但它只会在你的手指触摸时移动......
  • 我认为您必须在 onFling 中检测水平翻转并自己进行列表滚动。关于真/假:当我在做文档时说我的gestureListener 没有工作(到目前为止我还没有写)。所以我只是建议你做我做过的事情。
猜你喜欢
  • 1970-01-01
  • 2013-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多