1

之間,我想創建一個動畫:Android的衝突OnTouchListener SimpleOnGestureListener和setOnClickListener

使用案例: 1.用戶刷卡/拖動物品到右(水平),項目被添加進籃。如果他再次滑動,則會在籃筐中再添加一個相同的物品。 2.用戶向左(水平)滑動/拖拽項目,項目從籃筐中移除,如果之前添加,如果籃筐中沒有項目,我們將其保留原樣。

拖動效果:當用戶拖動時,項目隨手指一起移動。只要他離開它,物品就會回到原來的位置。

縮放效果:當用戶點擊該項目時,項目會縮放,讓用戶知道該項目已添加到購物籃中。 (右拖的複製方法)。

我想專門使用OnSwipeTouchListener類用於此目的:

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如上代碼,這兩種方法不會被觸發

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

關於Click事件的縮放效果。

在我的片段中,我縮放這樣的圖像。

offerimg1.setOnClickListener(新View.OnClickListener(){

 @Override 
     public void onClick(View v) { 
      // TODO Auto-generated method stub 
      zoomAnimation(v, offerimg1); 
     } 
    }); 

而且我zoomAnimation方法是:

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

我變焦的工作,除非我沒有在我的零散實現:

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

     }); 

我不確定這些事件之間有什麼碰撞,我需要實現在我的上面的用例中,每個事件都應該在每個圖像上工作。因爲我的圖像處於片段的滾動視圖中。

如果你想我可以在這裏分享更多的代碼。如果我無法澄清我的問題,請讓我知道。

我真的很感謝你的幫助。

問候, 沙善普拉塔普

+0

是否有任何人誰可以提供幫助。我試圖解決這個問題幾個小時,但無法取得成功。如果有任何可以指出的錯誤,沒有給出任何代碼示例。我會接受這個答案。 – shank2111

+0

好吧,我能夠解決onClick事件的問題,使用建議由http://stackoverflow.com/questions/9965695/how-to-distinguish-between-move-and-click-in-ontouchevent/29933115# 29933115但我仍然堅持onSwipeLeft()和onSwipeRight()..觸發事件後觸發,它應傳播到這兩種方法。 – shank2111

+0

是的,我發現onSwipeLeft()和onSwipeRight()這個問題..因爲我的圖像與我的手指一起移動,這就是distanceX顯示爲零的原因,它總是小於靜態SWIPE_DISTANCE_THRESHOLD。在代碼中,我們說如果distanceX是負數,它的swipeLeft()else swipeRight()。任何評論請.. – shank2111

回答

0

最後,我已經解決了這個問題,

實測值問題與上面的代碼:

onSwipeLeft()和onSwipeRight()..因爲我的圖像與我的手指 一起移動,這就是distanceX正在變爲零的原因, 它總是小於靜態SWIPE_DISTANCE_THRESHOLD。而在 代碼,我們說如果distanceX爲負其swipeLeft(否則 )swipeRight()

解決方案: 我們需要好歹陷阱哪種方式用戶移動他/她的手指,因此我在MotionEvent.ACTION_MOVE:事件中決定,找出mv.x是否定的或mv.x是正的。一旦找到它,就很容易做出決定,並且在此基礎上,我們可以決定在GestureListener中運行哪種方法。

這是我的OnSwipeTouchListener,我仍然不確定這是否是這種情況的最佳解決方案,但是我發現它在AVD和Android設備上工作。

我仍然開放給找到這樣做的一個很好的和明確的方法(最佳實踐):

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

最好的問候, 沙善普拉塔普