11

更新:有关扩展问题,请参阅赏金。

GestureDetectorListView. 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 像素。但是当我遇到上述问题时,对于相同的1 厘米距离,它要低得多,可能是 50。所以窗口没有关闭,因为它不符合我的if条件。

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

4

5 回答 5

3

尝试这个,

    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

于 2013-06-14T13:19:09.423 回答
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;
}
于 2013-06-10T07:23:25.563 回答
1

第一的

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

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

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

第二

鉴于您最近的观察,也许关键是要考虑 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
}

这具有不使用e1or的优点e2,这使我们进入...

第三

正如您所注意到的,问题在于您与列表视图交互时。此时,可能会报告多个指针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
}
于 2013-06-16T21:03:34.847 回答
1

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

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

listView.setOnTouchListener(gestureListener); 
于 2013-06-12T19:56:00.500 回答
0

首先尝试OnTouchListener像这样:

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

然后 - 你总是回来falseonFling()return trueintry/catch子句。并尝试将相同的数据传递给onScrollelse 子句里面的方法onFling

于 2013-06-16T14:18:26.743 回答