关于 java:Android 之间的冲突,OnTouchListener SimpleOnGestureListener 和 setOnClickListener

Android conflict between, OnTouchListener SimpleOnGestureListener and setOnClickListener

我正在尝试创建动画:

用例:
1. 用户向右(水平)滑动/拖动项目,项目被添加到购物篮中。如果他再次刷卡,它会在篮子中再添加一件相同的物品。
2. 用户向左(水平)滑动/拖动项目,项目从购物篮中移除,如果之前添加,如果购物篮中没有项目,我们保持原样。

拖动效果:当用户拖动时,项目会随着手指一起移动。他一离开,物品就会回到原来的位置。

缩放效果:当用户点击商品时,商品会被放大,让用户知道商品已添加到购物篮中。 (复制右键拖拽的方法)。

我尝试专门为此目的使用 OnSwipeTouchListener 类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import android.content.Context;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

import PointF;

public class OnSwipeTouchListener implements OnTouchListener {

    private final GestureDetector gestureDetector;
    PointF DownPT = null;
    PointF StartPT = null;
    float startX;
    float startY;

    public OnSwipeTouchListener(Context context , float x, float y) {
        gestureDetector = new GestureDetector(context, new GestureListener());
        DownPT = new PointF();
        StartPT = new PointF();
        this.startX = x;
        this.startY = y;
    }

    public void onSwipeLeft() {
    }

    public void onSwipeRight() {
    }

    public boolean onTouch(View v, MotionEvent event) {

        int eid = event.getAction();

        switch (eid) {
            case MotionEvent.ACTION_MOVE:

                PointF mv = new PointF(event.getX() - DownPT.x, event.getY() - DownPT.y);

                v.setX((int) (StartPT.x + mv.x));
                v.setY(this.startY);
                StartPT = new PointF(v.getX(), v.getY());
                break;
            case MotionEvent.ACTION_DOWN:
                DownPT.x = event.getX();
                DownPT.y = event.getY();
                StartPT = new PointF(v.getX(), v.getY());

                break;
            case MotionEvent.ACTION_UP:
                // Move image back to its original position.
                v.setX(this.startX);
                v.setY(this.startY);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            

                break;
            default:
                v.setX(this.startX);
                v.setY(this.startY);

                break;
        }

        return gestureDetector.onTouchEvent(event);
    }

    private final class GestureListener extends SimpleOnGestureListener {

        private static final int SWIPE_DISTANCE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            float distanceX = e2.getX() - e1.getX();
            float distanceY = e2.getY() - e1.getY();
            if (Math.abs(distanceX) > Math.abs(distanceY) && Math.abs(distanceX) > SWIPE_DISTANCE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                if (distanceX > 0)
                    onSwipeRight();
                else
                    onSwipeLeft();
                return true;
            }
            return false;
        }
    }
}

当我的方法 OnTouch 如下所示时,我的 onSwipeRight() 和 onSwipeLeft() 被触发,但是当我在代码中实现了上面的 onTouch 时,这两个方法不会被触发。

1
2
3
public boolean onTouch(View v, MotionEvent event) {
  return gestureDetector.onTouchEvent(event);
}

关于点击事件的缩放效果。

在我的 Fragment 中,我正在像这样缩放图像。

offerimg1.setOnClickListener(new View.OnClickListener() {

1
2
3
4
5
6
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            zoomAnimation(v, offerimg1);
        }
    });

而我的 zoomAnimation 方法是:

1
2
3
4
private void zoomAnimation(View view,ImageView image) {
        Animation animation = AnimationUtils.loadAnimation(getActivity().getApplicationContext(), R.anim.zoom);
        image.startAnimation(animation);
    }

除非我没有在我的碎片中实现,否则我的 Zoom 正在工作:

1
2
3
4
5
6
7
8
9
10
11
12
 offerimg1.setOnTouchListener(new OnSwipeTouchListener(getActivity().getApplicationContext(),offerimg1.getX(),offerimg1.getY()) {
            @Override
            public void onSwipeLeft() {
                Log.d("onTouch"," swipe left");
            }

            @Override
            public void onSwipeRight() {
                Log.d("onTouch"," swipe right");
            }

        });

我不确定这些事件之间的冲突是什么。我需要实现我上面的用例,每个事件都应该在每个图像上工作。由于我的图像在片段中的滚动视图中。

如果你愿意,我可以在这里分享更多代码。如果我无法澄清我的问题,请告诉我。

非常感谢您的帮助。

问候,
沙香克·普拉塔普


终于把问题解决了,

发现上述代码有问题:

onSwipeLeft() and onSwipeRight().. since my image is moving along with
my finger, this is the reason distanceX is turing out to be zero,
which is always less than static SWIPE_DISTANCE_THRESHOLD. and in the
code we are saying that if distanceX is negative its swipeLeft() else
swipeRight()

解决方案:
我们需要某种方式来捕捉用户移动手指的方式,因此我决定在 MotionEvent.ACTION_MOVE: 事件中,找出 mv.x 是负数还是 mv.x 是正数。一旦我找到它,就很容易做出决定,在此基础上我们可以决定在 GestureListener.

中运行哪个方法

这是我的 OnSwipeTouchListener,我仍然不确定这是否是这种情况的最佳解决方案,但我发现它适用于 AVD 和 Android 设备。

我仍然愿意找到一种很好且清晰的方法(最佳实践)来执行此操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
import android.content.Context;
import android.content.res.Resources;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewConfiguration;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.Toast;

import R;

import StartingPoints;
import PointF;

public class OnSwipeTouchListener implements OnTouchListener {

    private static final String APP = OnSwipeTouchListener.class.getName() ;
    private final GestureDetector gestureDetector;
    PointF DownPT = null;
    PointF StartPT = null;

    Context _context;
    static  boolean isLeftMoved = false;
    static  boolean isRightMoved = false;

    /**
     * Max allowed duration for a"click", in milliseconds.
     */

    private static final int MAX_CLICK_DURATION = 1000;

    /**
     * Max allowed distance to move during a"click", in DP.
     */

    private static final int MAX_CLICK_DISTANCE = 15;
    private static final float PIXELS_PER_SECOND = 5;

    private long pressStartTime;
    private float pressedX;
    private float pressedY;
    private boolean stayedWithinClickDistance;
    Resources resources;
    private float startX = 0f;
    private float startY = 0f;
    private boolean isNewImage = true;




    public OnSwipeTouchListener(Context context, Resources resources) {
        this._context = context;
        gestureDetector = new GestureDetector(context, new GestureListener());
        DownPT = new PointF();
        StartPT = new PointF();
        this.resources = resources;

    }

    public void onSwipeLeft() {
    }

    public void onSwipeRight() {
    }

    public boolean onTouch(View v, MotionEvent e) {
        if(isNewImage){
            isNewImage = false;
            startX = v.getX();
            startY = v.getY();
        }
        switch (e.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //animation code
                DownPT.x = e.getX();
                DownPT.y = e.getY();
                StartPT = new PointF(v.getX(), v.getY());


                //calculation code
                pressStartTime = System.currentTimeMillis();
                pressedX = e.getX();
                pressedY = e.getY();
                stayedWithinClickDistance = true;
                break;

            case MotionEvent.ACTION_MOVE:
                // animation code
                PointF mv = new PointF(e.getX() - DownPT.x, e.getY() - DownPT.y);
                v.setX((int) (StartPT.x + mv.x));
                v.setY(startY);

                StartPT = new PointF(v.getX(), v.getY());
                if(mv.x < 0 ){
                    isLeftMoved = true;
                }
                if(mv.x > 0 ){
                    isRightMoved = true;
                }

                //calculation code
                if (stayedWithinClickDistance && distance(pressedX, pressedY, e.getX(), e.getY()) > MAX_CLICK_DISTANCE) {
                    stayedWithinClickDistance = false;
                }

                Log.d("Moved","Item moved");
                break;
            case MotionEvent.ACTION_UP:
                if(!stayedWithinClickDistance){
                    v.setX(startX);
                    v.setY(startY);
                    isNewImage = true;
                }


                long pressDuration = System.currentTimeMillis() - pressStartTime;
                if (pressDuration < MAX_CLICK_DURATION && stayedWithinClickDistance) {
                    // Click event has occurred
                    Log.d("Stayed"," With Click event");
                    zoomAnimation(v);
                    isNewImage = true;
                }


                break;
            default:
                // Move image back to its original position, by default
                Log.d("default","This is default");
                v.setX(startX);
                v.setY(startY);
                isNewImage = true;
                break;

        }

        return gestureDetector.onTouchEvent(e);
    }


    private  float distance(float x1, float y1, float x2, float y2) {
        float dx = x1 - x2;
        float dy = y1 - y2;
        float distanceInPx = (float) Math.sqrt(dx * dx + dy * dy);
        return pxToDp(distanceInPx);
    }

    private  float pxToDp(float px) {
        return px / resources.getDisplayMetrics().density;
    }

    private void zoomAnimation(View view) {
        Animation animation = AnimationUtils.loadAnimation(_context, R.anim.zoom);
        view.startAnimation(animation);
    }





    private final class GestureListener extends SimpleOnGestureListener {

        private static final int SWIPE_DISTANCE_THRESHOLD = 20;
        private static final int SWIPE_VELOCITY_THRESHOLD = 50;



        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

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

            float maxFlingVelocity    = ViewConfiguration.get(_context).getScaledMaximumFlingVelocity();
            float velocityPercentX    = velocityX / maxFlingVelocity;          // the percent is a value in the range of (0, 1]
            float normalizedVelocityX = velocityPercentX * PIXELS_PER_SECOND;  // where PIXELS_PER_SECOND is a device-independent measurement

            float distanceX = e2.getX() - e1.getX();
            float distanceY = e2.getY() - e1.getY();

            if (isLeftMoved || isRightMoved) {
                if(isRightMoved) {
                    isLeftMoved = false;
                    isRightMoved = false;
                    onSwipeRight();
                }
                else {
                    isLeftMoved = false;
                    isRightMoved = false;
                    onSwipeLeft();
                }
            }

            return false;
        }

        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            return true;
        }
    }
}

最好的问候,
沙香克·普拉塔普