53 votes

Comment puis-je obtenir un SeekBar vertical sous Android?

J'ai mis en place le plus couramment signalé à VerticalSeekBar post ici. Comme il est, la SeekBar fonctionne un peu décalé. Voici mes légèrement adapté onTouchEvent() à partir de cet exemple:

public boolean onTouchEvent(MotionEvent event)
    {
            xPos = event.getX();
            yPos = event.getY();
            oOffset = this.getThumbOffset();
            oProgress = this.getProgress();

            //Code from example - Not working
            //this.setThumbOffset( progress * (this.getBottom()-this.getTop()) );

            this.setProgress((int)(29*yPos/this.getBottom()));
            return true;
    }

J'ai réussi à mettre en place un VerticalSeekBar dans la progression des mises à jour comme prévu, et est pleinement fonctionnelle, mais la manette de ne pas emboîter le pas. Ce n'est qu'un glitch graphique, donc je suis le domine pour l'instant. Mais, il serait agréable d'avoir ce travail. Cette SeekBar a max = 20.

Cependant, j'ai essayé de mettre en œuvre une autre VerticalSeekBar avec max = 1000. Évidemment, il utilise le même code, de sorte que vous pourriez supposer le même comportement. Je suis seulement en mesure d'atteindre une progression de 0~35, de même que mon doigt glisse au-delà de la SeekBar et éventuellement hors de l'écran. Si je viens de robinet près de la fin de la barre de progression (qui devrait être progress ~ 900), il renvoie une progression de près de 35 et le jaune de la barre de progression reflète que la valeur en restant près du sommet.

Ma question est: quelqu'un a un lien pour un travail vertical SeekBar, ou de savoir comment adapter cet exemple particulier?

150voto

Paul Tsupikoff Points 934

Voici une implémentation de travail de VerticalSeekBar:

 package android.widget;

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

public class VerticalSeekBar extends SeekBar {

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

    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:
            case MotionEvent.ACTION_MOVE:
            case MotionEvent.ACTION_UP:
                setProgress(getMax() - (int) (getMax() * event.getY() / getHeight()));
                onSizeChanged(getWidth(), getHeight(), 0, 0);
                break;

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

Pour l'implémenter, créez une nouvelle classe dans votre projet, en choisissant le bon package:

Là, collez le code et enregistrez-le. Maintenant, utilisez-le dans votre mise en page XML:

 <android.widget.VerticalSeekBar
  android:id="@+id/seekBar1"
  android:layout_width="wrap_content"
  android:layout_height="200dp"
  />
 

31voto

Fatal1ty2787 Points 263

Le code donné dans la réponse acceptée n'interceptait pas les événements onStartTrackingTouch et onStopTrackingTouch, je l'ai donc modifié pour mieux contrôler ces deux événements.

Voici mon code:

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

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

13voto

Michał M Points 91

J'ai eu des problèmes en utilisant ce code avec la méthode setProgress. Pour les résoudre, je suggère de remplacer setProgress par un ajout d'appel onSizeChanged.

11voto

Ramesh Points 3483

J'ai eu un problème pendant l'utilisation de ce code avec la méthode setProgress. Pour les résoudre, je suggère primordial setProgress et l'ajout de onSizeChanged de l'appel à elle.Ajout d'un code ici ..

   private int x,y,z,w;
   protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(h, w, oldh, oldw);
        this.x=w;
        this.y=h;
        this.z=oldw;
        this.w=oldh;
    }
        @Override
        public synchronized void setProgress(int progress) {

            super.setProgress(progress);

                onSizeChanged(x, y, z, w);

        }

sélectionné placez les actions sont réalisées en ajoutant le code suivant:

1.setPressed(true);setSelected(true);//Ajouter ce dans ACTION_DOWN

2.setPressed(false);setSelected(false);//Ajouter ce dans ACTION_UP

Et Écrivez le code sélectionné, passez options ur xml.

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true"
          android:state_window_focused="true"
          android:drawable="@drawable/thumb_h" />
    <item android:state_selected="true"
          android:state_window_focused="true"
          android:drawable="@drawable/thumb_h" />
    <item android:drawable="@drawable/thumb" />
</selector>

Ce travail est pour moi...

9voto

Adam Mackler Points 594

Merci à Paul Tsupikoff, Fatal1ty2787 et Ramesh pour ce super code.

Personnellement, je voulais une barre de défilement verticale qui est à l'envers par rapport au code donné. En d'autres termes, la valeur augmente, au lieu de diminuer, le bas de la manette. Changer quatre lignes semble avoir pris soin de cela.

Tout d'abord, j'ai changé l' onDraw() méthode de d'abord donné par Paul. L' rotate() et translate() des appels ont maintenant ces arguments:

c.rotate(90);
c.translate(0, -getWidth());

Ensuite, j'ai effectué deux modifications à l' ACTION_MOVE cas onTouchEvent() donnée par Fatal1ty2787. L'appel à l' setProgress() ressemble maintenant à ceci:

setProgress((int) (getMax() * event.getY() / getHeight()));

Enfin, l'appel à onProgressChanged() ressemble à ceci:

myListener.onProgressChanged(this, (int) (getMax() * event.getY() / getHeight()), true);

Maintenant, si seulement Google a partagé notre intérêt dans cette fonction....

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X