OnFling MotionEvent e1 null?

16

好的,这件事情差点把我逼疯了。

几天前,我实现了下面的代码,并成功地调用了toast,当我尝试向右或向左滑动时。

然而,现在它不能被调用,因为e1始终为空!

怎么会发生这种情况?我在模拟器上尝试了这个代码,但是有用户报告说,在真实设备上也无法使用。

public class SwipeGestureListener extends GestureDetector.SimpleOnGestureListener{

    private static final int SWIPE_MIN_DISTANCE = 150;
    private static final int SWIPE_MAX_OFF_PATH = 100;

    private static final int SWIPE_THRESHOLD_VELOCITY = 100;
    private final Activity activity;
    protected MotionEvent mLastOnDownEvent = null;

    public SwipeGestureListener(Activity activity) {
        this.activity = activity;
    }

    @Override
    public boolean onDown(MotionEvent e) {
        mLastOnDownEvent = e;
        System.out.println(e);
        return super.onDown(e);
    }

    @Override   
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        System.out.println(e1 + " " + e2);
        if (e1==null)
            e1 = mLastOnDownEvent;
        if (e1==null || e2==null)
            return false;

        float dX = e2.getX()-e1.getX();
        float dY = e2.getY()-e1.getY();

        if (Math.abs(dY)<SWIPE_MAX_OFF_PATH && Math.abs(velocityX)>=SWIPE_THRESHOLD_VELOCITY && Math.abs(dX)>=SWIPE_MIN_DISTANCE ) {

            if (dX>0) {
                Toast.makeText(activity.getApplicationContext(), "Right Swipe", Toast.LENGTH_SHORT).show();
                activity.fetchPrevious();
            } else {
                Toast.makeText(activity.getApplicationContext(), "Left Swipe", Toast.LENGTH_SHORT).show();
                activity.fetchNext();
            }

            return true;
        } 

        return false;
    }

}

实现手势的代码:

final GestureDetector gdt = new GestureDetector(this, new SwipeGestureListener(this));
listview.setOnTouchListener(new OnTouchListener(){

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        gdt.onTouchEvent(event);
        return false;
        }

});

1
有人能给出一个正确的解决方案吗?我也遇到了同样的问题。 - Jack
4个回答

1

我尝试了你的代码,确实没有起作用,然后我将GestureDetector更改为更新的API“GestureDetectorCompat”,并进行了一些进一步的更改: 使用GestureDetector.OnGestureListener而不是OnSimpleGestureListener, onDown()应该返回true,然后它就可以工作了。我无法向您解释确切的问题所在。但更改的行似乎有问题。也许有人可以解释潜在的问题。请查看正在运行的代码:

public class MainActivity extends Activity {
   ImageView imageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView= (ImageView) findViewById(R.id.imageView1);

        final GestureDetectorCompat gdt = new GestureDetectorCompat(this, new SwipeGestureListener(this));
        imageView.setOnTouchListener(new OnTouchListener(){

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return gdt.onTouchEvent(event);
                }

        });

    }




    public class SwipeGestureListener implements GestureDetector.OnGestureListener{

        private static final int SWIPE_MIN_DISTANCE = 150;
        private static final int SWIPE_MAX_OFF_PATH = 100;

        private static final int SWIPE_THRESHOLD_VELOCITY = 100;
        private final Activity activity;
        protected MotionEvent mLastOnDownEvent = null;

        public SwipeGestureListener(Activity activity) {
            this.activity = activity;
    }

        @Override
        public boolean onDown(MotionEvent e) {
            mLastOnDownEvent = e;
            System.err.println("ondown");
            //System.out.println(e);
            return true;
        }

        @Override   
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            System.err.println("onFling");
            System.out.println(e1 + " " + e2);
            if (e1==null)
                e1 = mLastOnDownEvent;
            if (e1==null || e2==null)
                return false;

            float dX = e2.getX()-e1.getX();
            float dY = e2.getY()-e1.getY();

            if (Math.abs(dY)<SWIPE_MAX_OFF_PATH && Math.abs(velocityX)>=SWIPE_THRESHOLD_VELOCITY && Math.abs(dX)>=SWIPE_MIN_DISTANCE ) {

                if (dX>0) {
                    Toast.makeText(activity.getApplicationContext(), "Right Swipe", Toast.LENGTH_SHORT).show();
                   // activity.fetchPrevious();
                } else {
                    Toast.makeText(activity.getApplicationContext(), "Left Swipe", Toast.LENGTH_SHORT).show();
                   // activity.fetchNext();
                }

                return true;
            } 

            return false;
        }

        @Override
        public void onLongPress(MotionEvent e) {
            // TODO Auto-generated method stub

    }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 
            // TODO Auto-generated method stub
            return false;
    }

        @Override
        public void onShowPress(MotionEvent e) {
            // TODO Auto-generated method stub

    }

       @Override
       public boolean onSingleTapUp(MotionEvent e) {
          // TODO Auto-generated method stub
           return false;
       }

       }

   }

请尝试一下!

抱歉 G_J,还是一样的问题。e1 仍然给我 null 值。 - Rendy
这真的很奇怪。你尝试过使用不同的View(而不是ListView)吗?当我将ImageView注册到OnTouchListener时,上面的代码绝对完美无瑕!你能展示一下你代码的其余部分吗? - G_J
是的,我同意。它可以在其他视图上工作,但不能在我的一个列表视图上工作。我会尝试调查一下 XML,谢谢 G_J 的帮助。 - Rendy
@G_J 你的想法很好,但在我的情况下,onDown()从未被调用,因此我无法拦截e1的空值。我们滑动时是否必须调用onDown() - mangusta

0

我曾经遇到过同样的问题。请确保所有视图都添加了相同的setOnTouchListener()方法。如果您的触摸位置在视图之外,则会在e1上得到null

我的例子:

private View.OnTouchListener onTouchListener = new OnSwipeTouchListener(mActivity) {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return super.onTouch(v, event);
        }

        @Override
        public void onSwipeLeft() {

        }

        @Override
        public void onSwipeRight() {
        }
    };


    @Override
    public View onCreateView(LayoutInflater inflater,
                      ViewGroup container, Bundle savedInstanceState) {

    //Inflate the layout for this fragment
    View v = inflater.inflate(R.layout.view, container, false);
    mListView = (ListView) v.findViewById(R.id.list);
    v.setFocusableInTouchMode(true);
    v.requestFocus();
    v.setOnTouchListener(onTouchListener);
    mListView.setOnTouchListener(onTouchListener);

    mAdapter = new OnlineAdapter(getActivity(), R.layout.row, onTouchListener);
    mListView.setAdapter(mAdapter);
    return v;

}

我的列表适配器:

@Override
    public View getView(final int position, View convertView, ViewGroup parent) {

        // something

            mImage = (ImageView) convertView.findViewById(R.id.image);
            mImage.setOnTouchListener(onTouchListener);
    }

0

我曾经遇到过类似的问题,我通过添加FrameLayout和所需的View(我使用了一个GridView,但认为它可以与ListView或其他视图一起使用)来解决它。

GestureListener与您的相同。布局如下:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:id="@+id/colors_grid_panel"
             xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:background="@color/white"
             android:paddingLeft="@dimen/create_side_padding"
             android:paddingRight="@dimen/create_side_padding"
             android:visibility="gone">

    <GridView
        android:id="@+id/colors_grid"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:numColumns="7"
        android:paddingBottom="10dp"
        android:paddingTop="10dp"
        android:stretchMode="columnWidth"
        android:verticalSpacing="10dp"/>

    <FrameLayout
        android:id="@+id/stub"
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</FrameLayout>

在程序中:
colorsGrid.setOnTouchListener(onSwipeTouchListener);
stub.setOnTouchListener(onSwipeTouchListener);

0
我遇到了同样的问题。如果有 onclicklistener 等在滑动项上,应该将其删除。然后它就会工作。谢谢。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接