0

J'ai une application Android avec deux barres de recherche, et je les ai configurées pour que l'application ne réponde pas à moins que les deux ne soient pressées. Mon problème est que quand ils sont tous les deux enfoncés, la méthode onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) commence à fonctionner en continu dans une boucle infinie. Cela se produit même si je maintiens mes doigts complètement immobiles sur les barres (ce qui signifie que la progression ne change pas sur l'une ou l'autre des barres, et par conséquent la méthode onProgressChanged ne devrait pas être appelée). Quelqu'un at-il des idées sur la raison pour laquelle cela pourrait se produire?onProgressChanged en cours d'exécution même en l'absence de changement de progression

Voici une partie pertinente:

void setupLRSpeedBars(final int UIID, final Bool bar1, final Bool bar2) { 
    SeekBar sb = (SeekBar) findViewById(UIID); 
    sb.setProgress(9); 
    sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 
     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 
      if (bar1.isTrue()) { 
       progress -= 9; 
       transmit((UIID == R.id.leftSpeedBar ? "L" : "R") + 
         (progress >= 0 ? "+" : "") + 
          Integer.toString(progress)); 
      } 
     } 

     public void onStartTrackingTouch(SeekBar seekBar) { 
      bar2.set(true); 
     } 

     public void onStopTrackingTouch(SeekBar seekBar) { 
      bar2.set(false); 
      seekBar.setProgress(9); 
      //transmit((UIID == R.id.leftSpeedBar ? "L" : "R") + "+0"); 
      transmit("s"); 
     } 
    }); 
} 

Notez également que je l'ai utilisé une coutume Bool classe au lieu d'un boolean, dans primitive ordre pour moi de contourner la restriction que toutes les variables en dehors du OnSeekBarChangeListener être marqué final. (J'ai besoin d'envoyer des informations entre les onSeekBarChangeListeners afin de déterminer si l'utilisateur est en train de maintenir ses doigts sur les deux barres de recherche en même temps) J'ai l'intuition que cela pourrait être la cause de mes problèmes, mais je ne sais pas regarde comment.

class Bool { 
    private boolean bool; 
    public Bool() {} 
    public Bool(boolean bool) { this.bool = bool; } 
    public void set (boolean bool) { this.bool = bool; } 
    public boolean get() { return bool; } 
    public boolean isTrue() { return bool; } 
} 

EDIT: Je vais aussi noter que j'utilise une coutume, seekbar verticale. Voici le code:

package android.widget; 

import android.content.Context; 
import android.graphics.Canvas; 
import android.util.AttributeSet; 
import android.view.MotionEvent; 

public class VerticalSeekBar extends SeekBar { 

    private OnSeekBarChangeListener myListener; 
    public VerticalSeekBar(Context context) { 
     super(context); 
    } 

    public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    public VerticalSeekBar(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
     super.onSizeChanged(h, w, oldh, oldw); 
    } 

    @Override 
    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     super.onMeasure(heightMeasureSpec, widthMeasureSpec); 
     setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth()); 
    } 

    @Override 
    public void setOnSeekBarChangeListener(OnSeekBarChangeListener mListener){ 
     this.myListener = mListener; 
    } 

    @Override 
    public synchronized void setProgress(int progress){ 
     super.setProgress(progress); 
     onSizeChanged(getWidth(), getHeight(), 0, 0); 
    } 

    protected void onDraw(Canvas c) { 
     c.rotate(-90); 
     c.translate(-getHeight(), 0); 

     super.onDraw(c); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     if (!isEnabled()) { 
      return false; 
     } 

     switch (event.getAction()) { 
      case MotionEvent.ACTION_DOWN: 
       if(myListener!=null) 
        myListener.onStartTrackingTouch(this); 
       break; 
      case MotionEvent.ACTION_MOVE: 
       setProgress(getMax() - (int) (getMax() * event.getY()/getHeight())); 
       onSizeChanged(getWidth(), getHeight(), 0, 0); 
       myListener.onProgressChanged(this, getMax() - (int) (getMax() * event.getY()/getHeight()), true); 
       break; 
      case MotionEvent.ACTION_UP: 
       myListener.onStopTrackingTouch(this); 
       break; 

      case MotionEvent.ACTION_CANCEL: 
       break; 
     } 
     return true; 
    } 
} 
+0

sb.setProgress (9); va se déclencher à onChangeListener –

+0

@SanketKachhela yep, mais cet appel se produit seulement une fois au début de l'application, pas 1000 fois dans une boucle infinie. En outre, cela se produit avant que j'ai défini le Custom OnSeekBarChangeListener – TheIronKnuckle

Répondre

2

Je pense que le problème est dans la mise en œuvre onTouchEvent de votre VerticalSeekBar parce que vous traitez tous les MotionEvent.ACTION_MOVE reçus.

De the documentation:

Une nouvelle onTouchEvent() est déclenchée par un événement de ACTION_MOVE chaque fois que la position de contact tactile de courant, de pression, ou des changements de taille. Comme décrit dans Detecting Common Gestures, tous ces événements sont enregistrés dans le paramètre MotionEvent de onTouchEvent(). Parce que le toucher au doigt n'est pas toujours la forme d'interaction la plus précise, la détection des événements tactiles est souvent basée davantage sur le mouvement que sur le simple contact. Pour aider les applications à distinguer les gestes basés sur les mouvements (tels qu'un glissement) des gestes sans mouvement (comme un simple clic), Android inclut la notion de «touche tactile». Le slop de toucher fait référence à la distance en pixels que le toucher d'un utilisateur peut parcourir avant que le geste soit interprété comme un geste basé sur le mouvement. Pour plus d'informations sur ce sujet, voir Gestion des événements tactiles dans un ViewGroup.

C'est, vous pensez que vos doigts sont complètement encore mais vos barres de recherche reçoivent ACTION_MOVE événements.

Dans votre cas, le rapprochement est maintenant une bonne idée « slops toucher », car la pente tactile calculée est énorme pour vos besoins, comme touch slop is defined as:

« Touch slops » fait référence à la distance en pixels une Le toucher de l'utilisateur peut errer avant que le geste soit interprété comme un défilement. Le slop tactile est généralement utilisé pour empêcher le défilement accidentel lorsque l'utilisateur effectue une autre opération tactile, par exemple toucher des éléments à l'écran.

Pour résoudre votre problème, vous pouvez calculer la distance entre la dernière position gérée et l'actuel pour déclencher votre onProgressChanged:

private static final float MOVE_PRECISION = 5; // You may want to tune this parameter 
private float lastY; 

// ... 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    if (!isEnabled()) { 
     return false; 
    } 

    switch (event.getAction()) { 
     case MotionEvent.ACTION_DOWN: 
      lastY = event.getY(); 

      if (myListener != null) 
       myListener.onStartTrackingTouch(this); 
      break; 
     case MotionEvent.ACTION_MOVE: 
      if (calculateDistanceY(event) > MOVE_PRECISION) { 
       setProgress(getMax() - (int) (getMax() * event.getY()/getHeight())); 
       onSizeChanged(getWidth(), getHeight(), 0, 0); 
       myListener.onProgressChanged(this, getMax() - (int) (getMax() * event.getY()/getHeight()), true); 

       lastY = event.getY(); 
      } 
      break; 
     case MotionEvent.ACTION_UP: 
      myListener.onStopTrackingTouch(this); 
      break; 

     case MotionEvent.ACTION_CANCEL: 
      break; 
    } 
    return true; 
} 

private float calculateDistanceY (MotionEvent event) { 
    return Math.abs(event.getY() - lastY); 
}