2017-09-20 11 views
0

Mon activité contient un ensemble TextView dans un ScrollView couvrant l'intégralité de l'écran. Le contenu de TextView est généralement composé de plusieurs pages.Problème avec le balayage et le défilement normal

J'essaie d'activer les commandes tactiles comprenant un seul robinet, double tap, balayez vers la gauche, balayez vers la droite et pincer et cela fonctionne bien. Le problème est cependant la difficulté pour l'utilisateur de glisser à gauche ou à droite avec le défilement accidentellement ScrollView vers le haut ou vers le bas (et l'annulation d'où la détection swipe)

Voici mon habitude OnTouchListener qui est utilisé sur mon TextView

public class OnSwipeTouchListener implements OnTouchListener { 

private final GestureDetector gestureDetector; 
private boolean mTapConsumed = false; 
private int mTapsDetected = 0; 
private boolean mEnableTap = true; 

public OnSwipeTouchListener (Context ctx){ 
    gestureDetector = new GestureDetector(ctx, new GestureListener()); 
} 

private double mPinchOriginalDistance = 0; 
private float mPinchLastScale = 1.0f;    //scale change for current pinch action 
private ScrollView mScrollView; 

@Override 
public boolean onTouch(View v, MotionEvent event) { 

    mScrollView = (ScrollView) v.getParent(); 
    if(event.getPointerCount() == 2) { 
     mScrollView.requestDisallowInterceptTouchEvent(true); 
     mTapConsumed = true; 
     mTapsDetected = 0; 
     switch(event.getAction() & MotionEvent.ACTION_MASK){ 

      case MotionEvent.ACTION_POINTER_DOWN: 
       //pinch mode 
       float distx, disty; 
       //Get the current distance 
       distx = event.getX(0) - event.getX(1); 
       disty = event.getY(0) - event.getY(1); 
       mPinchOriginalDistance = Math.sqrt(distx * distx + disty * disty); 
       break; 

      case MotionEvent.ACTION_MOVE: 
       //Get the current distance 
       distx = event.getX(0) - event.getX(1); 
       disty = event.getY(0) - event.getY(1); 
       double distance = Math.sqrt(distx * distx + disty * disty); 
       if(mPinchOriginalDistance == 0) 
        break; 
       float scale = (float)(distance/mPinchOriginalDistance); 
       mPinchLastScale = scale; 
       onPinchScaleChange(scale); 
       break; 

      case MotionEvent.ACTION_POINTER_UP: 
       onPinchFinal(mPinchLastScale); 
       mPinchOriginalDistance = 0; 
       mPinchLastScale = 1.0f; 
       break; 

      default: 
       break; 
     } 
     return true; 
    } 
    else 
     return gestureDetector.onTouchEvent(event); 

} 

private final class GestureListener extends SimpleOnGestureListener { 

    private static final int SWIPE_THRESHOLD = 80; 
    private static final int SWIPE_VELOCITY_THRESHOLD = 60; 
    private final static int GESTURE_TAP_DELAY = 300; 
    private final static int GESTURE_FLING_DELAY = 1000; 


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

    @Override 
    public boolean onSingleTapUp(MotionEvent e) { 
     if(!mEnableTap) 
      return true; 
     mTapConsumed = false; 
     mTapsDetected++; 
     if(mTapsDetected == 1) 
      handler.postDelayed(checkTap, GESTURE_TAP_DELAY); 
     return true; 
    } 

    @Override 
    public boolean onDoubleTap(MotionEvent e) { 
     if(!mEnableTap) 
      return true; 
     mTapConsumed = false; 
     mTapsDetected++; 
     return true; 
    } 

    @Override 
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 
     mEnableTap = false; 
     mTapConsumed = true; 
     mTapsDetected = 0; 
     handler.removeCallbacks(postFling); 
     handler.postDelayed(postFling, GESTURE_FLING_DELAY); //dont allow a tap to be registered for a certain time 
     boolean result = false; 
     try { 
      float diffY = e2.getY() - e1.getY(); 
      float diffX = e2.getX() - e1.getX(); 
      flingData(diffX, diffY); 
      if (Math.abs(diffX) > Math.abs(diffY)) { 

       if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) { 
        if (diffX > 0) { 
         onSwipeRight(); 
        } else { 
         onSwipeLeft(); 
        } 
        result = true; 
       } 
      } 

     } catch (Exception exception) { 
      exception.printStackTrace(); 
     } 
     return result; 
    } 
} 

//Prevents a single tap being detected as well as a double tap  
private Handler handler = new Handler(); 
private Runnable checkTap = new Runnable() { 

    public void run() { 
     try { 
      if(!mTapConsumed && mTapsDetected >= 1) { 
       if(mTapsDetected > 1) 
        onTapDouble(); 
       else 
        onTapSingle(); 
       mTapsDetected = 0; 
      } 
     } 
     catch(Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 

}; 

//Prevents a tap from being detected for a short duration after a fling has occurred 
private Runnable postFling = new Runnable() { 

    public void run() { 
     try { 
      mEnableTap = true; 
     } 
     catch(Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 
}; 



public void onSwipeRight() { 
} 

public void onSwipeLeft() { 
} 

public void onPinchScaleChange(float scale) { 
} 

public void onPinchFinal(float scale) { 
} 

public void onTapSingle() { 
} 

public void onTapDouble() { 
} 

public void flingData(float diffX, float diffY) 
{ 

} 

}

Pour être clair. Le code ci-dessus fonctionne mais il est difficile pour l'utilisateur d'activer une touche gauche ou droite car le ScrollView veut faire défiler vers le haut ou vers le bas. J'ai besoin d'un moyen de faire glisser à gauche et à droite plus facile pour l'utilisateur. Des idées?

Répondre

0

Il s'avère que parfois la réponse la plus simple est la meilleure. J'ai appliqué le onTouchListener à la scrollview plutôt qu'à la textview et tout est bon dans le monde. :)