web-dev-qa-db-fra.com

Comment faire une barre de recherche verticale dans Android?

Est-ce qu'une seekbar peut être verticale? Je ne suis pas très bon en design d’interface utilisateur, alors comment faire une recherche plus belle, donnez-moi quelques modèles et exemples.

60
Chris

Voici une très bonne implémentation de seekbar vertical . Regardez. 

http://560b.sakura.ne.jp/Android/VerticalSlidebarExample.Zip

Et voici ma propre implémentation pour Seekbar vertical et inversé basé sur this

https://github.com/AndroSelva/Vertical-SeekBar-Android

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:
            int i=0;
            i=getMax() - (int) (getMax() * event.getY() / getHeight());
            setProgress(i);
            Log.i("Progress",getProgress()+"");
            onSizeChanged(getWidth(), getHeight(), 0, 0);
            break;

        case MotionEvent.ACTION_CANCEL:
            break;
    }
    return true;
}
48
Andro Selva
  1. Pour les API 11 et ultérieures, vous pouvez utiliser les attributs XML de seekbar (Android: rotation = "270") pour un effet vertical.

    <SeekBar
    Android:id="@+id/seekBar1"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:rotation="270"/>
    
  2. Pour les anciens niveaux API (ex API10), utilisez uniquement la réponse de Selva: 
    https://github.com/AndroSelva/Vertical-SeekBar-Android

58
Saturn

Exemple de travail

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
   public synchronized void setProgress(int progress)  // it is necessary for calling setProgress on click of a button
   {
    super.setProgress(progress);
    onSizeChanged(getWidth(), getHeight(), 0, 0); 
   }
    @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;
    }
}

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"
  />

Assurez-vous de créer un package Android.widget et de créer VerticalSeekBar.Java sous ce package

22
Xar E Ahmer

Essayer:

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"  
xmlns:tools="http://schemas.Android.com/tools" 
Android:layout_width="match_parent" 
Android:layout_height="match_parent" > 

<SeekBar 
    Android:id="@+id/seekBar1" 
    Android:layout_width="match_parent" 
    Android:layout_height="wrap_content" 
    Android:rotation="270" 
    /> 

</RelativeLayout> 
13
Balaji Gunasekar

Nous avons créé une barre de recherche verticale en utilisant Android:rotation="270":

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:orientation="horizontal"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <SurfaceView
        Android:id="@+id/camera_sv_preview"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"/>

    <LinearLayout
        Android:id="@+id/camera_lv_expose"  
        Android:layout_width="32dp"
        Android:layout_height="200dp"
        Android:layout_centerVertical="true"
        Android:layout_alignParentRight="true"
        Android:layout_marginRight="15dp"
        Android:orientation="vertical">

        <TextView
            Android:id="@+id/camera_tv_expose"
            Android:layout_width="32dp"
            Android:layout_height="20dp"
            Android:textColor="#FFFFFF"
            Android:textSize="15sp"
            Android:gravity="center"/>

        <FrameLayout
            Android:layout_width="32dp"
            Android:layout_height="180dp"
            Android:orientation="vertical">

            <SeekBar
                Android:id="@+id/camera_sb_expose"
                Android:layout_width="180dp"
                Android:layout_height="32dp" 
                Android:layout_gravity="center"
                Android:rotation="270"/>

        </FrameLayout>

    </LinearLayout>

    <TextView
        Android:id="@+id/camera_tv_help"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_centerHorizontal="true"
        Android:layout_alignParentBottom="true"
        Android:layout_marginBottom="20dp"
        Android:text="@string/camera_tv"
        Android:textColor="#FFFFFF" />

</RelativeLayout>

Capture d'écran pour la compensation d'exposition de l'appareil photo:

 enter image description here

9
Maxim Mikhisor

J'ai utilisé la solution de Selva mais j'avais deux types de problèmes:

  • OnSeekbarChangeListener n'a pas fonctionné correctement
  • La définition des progrès par programme ne fonctionnait pas correctement.

J'ai corrigé ces deux problèmes. Vous pouvez trouver la solution (dans mon propre package de projet) à

https://github.com/jeisfeld/Augendiagnose/blob/master/AugendiagnoseIdea/augendiagnoseLib/src/main/Java/de/jeisfeld/augendiagnoselib/components/VerticalSeekBar.Java

9
Jörg Eisfeld

Notez, il me semble que si vous modifiez la largeur, la largeur du pouce ne change pas correctement ..__ Je n'ai pas pris le temps de la corriger, je l'ai juste corrigée pour mon cas. Voici ce que j’ai fait ... Je ne savais pas comment contacter le créateur original.

public void setThumb(Drawable thumb) {
    if (thumb != null) {
        thumb.setCallback(this);

        // Assuming the thumb drawable is symmetric, set the thumb offset
        // such that the thumb will hang halfway off either Edge of the
        // progress bar.
        //This was orginally divided by 2, seems you have to adjust here when you adjust width.
        mThumbOffset = (int)thumb.getIntrinsicHeight();
    }
6
user602622

Cela a fonctionné pour moi, il suffit de le mettre dans n'importe quelle mise en page que vous voulez.

<FrameLayout
    Android:layout_width="32dp"
    Android:layout_height="192dp">

    <SeekBar
        Android:layout_width="192dp"
        Android:layout_height="32dp"
        Android:layout_gravity="center"
        Android:rotation="270" />

</FrameLayout>
5
Nick

Lorsque vous déplacez le thumb avec un EditText, la barre de recherche verticale setProgress peut ne pas fonctionner. Le code suivant peut aider:

    @Override
public synchronized void setProgress(int progress) {
    super.setProgress(progress);
    updateThumb();
}

private void updateThumb() {
    onSizeChanged(getWidth(), getHeight(), 0, 0);
}

Ce code d'extrait se trouve ici: https://stackoverflow.com/a/33064140/2447726

2
Guy West

Essaye ça 

import Android.content.Context;
import Android.graphics.Canvas;
import Android.support.annotation.NonNull;
import Android.util.AttributeSet;
import Android.view.MotionEvent;
import Android.widget.SeekBar;

/**
 * Implementation of an easy vertical SeekBar, based on the normal SeekBar.
 */
public class VerticalSeekBar extends SeekBar {
    /**
     * The angle by which the SeekBar view should be rotated.
     */
    private static final int ROTATION_ANGLE = -90;

    /**
     * A change listener registrating start and stop of tracking. Need an own listener because the listener in SeekBar
     * is private.
     */
    private OnSeekBarChangeListener mOnSeekBarChangeListener;

    /**
     * Standard constructor to be implemented for all views.
     *
     * @param context The Context the view is running in, through which it can access the current theme, resources, etc.
     * @see Android.view.View#View(Context)
     */
    public VerticalSeekBar(final Context context) {
        super(context);
    }

    /**
     * Standard constructor to be implemented for all views.
     *
     * @param context The Context the view is running in, through which it can access the current theme, resources, etc.
     * @param attrs   The attributes of the XML tag that is inflating the view.
     * @see Android.view.View#View(Context, AttributeSet)
     */
    public VerticalSeekBar(final Context context, final AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * Standard constructor to be implemented for all views.
     *
     * @param context  The Context the view is running in, through which it can access the current theme, resources, etc.
     * @param attrs    The attributes of the XML tag that is inflating the view.
     * @param defStyle An attribute in the current theme that contains a reference to a style resource that supplies default
     *                 values for the view. Can be 0 to not look for defaults.
     * @see Android.view.View#View(Context, AttributeSet, int)
     */
    public VerticalSeekBar(final Context context, final AttributeSet attrs, final int defStyle) {
        super(context, attrs, defStyle);
    }

    /*
     * (non-Javadoc) ${see_to_overridden}
     */
    @Override
    protected final void onSizeChanged(final int width, final int height, final int oldWidth, final int oldHeight) {
        super.onSizeChanged(height, width, oldHeight, oldWidth);
    }

    /*
     * (non-Javadoc) ${see_to_overridden}
     */
    @Override
    protected final synchronized void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
        super.onMeasure(heightMeasureSpec, widthMeasureSpec);
        setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
    }

    /*
     * (non-Javadoc) ${see_to_overridden}
     */
    @Override
    protected final void onDraw(@NonNull final Canvas c) {
        c.rotate(ROTATION_ANGLE);
        c.translate(-getHeight(), 0);

        super.onDraw(c);
    }

    /*
     * (non-Javadoc) ${see_to_overridden}
     */
    @Override
    public final void setOnSeekBarChangeListener(final OnSeekBarChangeListener listener) {
        // Do not use super for the listener, as this would not set the fromUser flag properly
        mOnSeekBarChangeListener = listener;
    }

    /*
     * (non-Javadoc) ${see_to_overridden}
     */
    @Override
    public final boolean onTouchEvent(@NonNull final MotionEvent event) {
        if (!isEnabled()) {
            return false;
        }

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            setProgressInternally(getMax() - (int) (getMax() * event.getY() / getHeight()), true);
            if (mOnSeekBarChangeListener != null) {
                mOnSeekBarChangeListener.onStartTrackingTouch(this);
            }
            break;

        case MotionEvent.ACTION_MOVE:
            setProgressInternally(getMax() - (int) (getMax() * event.getY() / getHeight()), true);
            break;

        case MotionEvent.ACTION_UP:
            setProgressInternally(getMax() - (int) (getMax() * event.getY() / getHeight()), true);
            if (mOnSeekBarChangeListener != null) {
                mOnSeekBarChangeListener.onStopTrackingTouch(this);
            }
            break;

        case MotionEvent.ACTION_CANCEL:
            if (mOnSeekBarChangeListener != null) {
                mOnSeekBarChangeListener.onStopTrackingTouch(this);
            }
            break;

        default:
            break;
        }

        return true;
    }

    /**
     * Set the progress by the user. (Unfortunately, Seekbar.setProgressInternally(int, boolean) is not accessible.)
     *
     * @param progress the progress.
     * @param fromUser flag indicating if the change was done by the user.
     */
    public final void setProgressInternally(final int progress, final boolean fromUser) {
        if (progress != getProgress()) {
            super.setProgress(progress);
            if (mOnSeekBarChangeListener != null) {
                mOnSeekBarChangeListener.onProgressChanged(this, progress, fromUser);
            }
        }
        onSizeChanged(getWidth(), getHeight(), 0, 0);
    }

    /*
     * (non-Javadoc) ${see_to_overridden}
     */
    @Override
    public final void setProgress(final int progress) {
        setProgressInternally(progress, false);
    }
}
1
Saef Myth

Commencer

Ajoutez ces lignes à build.gradle.

dependencies {
    compile 'com.h6ah4i.Android.widget.verticalseekbar:verticalseekbar:0.7.2'
}

Utilisation

Code Java

public class TestVerticalSeekbar extends AppCompatActivity {
    private SeekBar volumeControl = null;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_vertical_seekbar);

        volumeControl = (SeekBar) findViewById(R.id.mySeekBar);

        volumeControl.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            int progressChanged = 0;

            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                progressChanged = progress;
            }

            public void onStartTrackingTouch(SeekBar seekBar) {
                // TODO Auto-generated method stub
            }

            public void onStopTrackingTouch(SeekBar seekBar) {
                Toast.makeText(getApplicationContext(), "seek bar progress:" + progressChanged,
                        Toast.LENGTH_SHORT).show();
            }
        });
    }

}

Mise en page XML

<!-- This library requires pair of the VerticalSeekBar and VerticalSeekBarWrapper classes -->
<com.h6ah4i.Android.widget.verticalseekbar.VerticalSeekBarWrapper
    Android:layout_width="wrap_content"
    Android:layout_height="150dp">
    <com.h6ah4i.Android.widget.verticalseekbar.VerticalSeekBar
        Android:id="@+id/mySeekBar"
        Android:layout_width="0dp"
        Android:layout_height="0dp"
        Android:max="100"
        Android:progress="0"
        Android:splitTrack="false"
        app:seekBarRotation="CW90" /> <!-- Rotation: CW90 or CW270 -->
</com.h6ah4i.Android.widget.verticalseekbar.VerticalSeekBarWrapper>

REMARQUE: Android:splitTrack="false" est requis pour Android N +.

1
Phadadev

J'ai essayé de différentes manières, mais celle qui a fonctionné pour moi a été. Utiliser Seekbar dans FrameLayout

<FrameLayout
    Android:id="@+id/VolumeLayout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:layout_above="@id/MuteButton"
    Android:layout_below="@id/volumeText"
    Android:layout_centerInParent="true">
        <SeekBar
        Android:id="@+id/volume"
        Android:layout_width="500dp"
        Android:layout_height="60dp"
        Android:layout_gravity="center"
        Android:progress="50"
        Android:secondaryProgress="40"
        Android:progressDrawable="@drawable/seekbar_volume"
        Android:secondaryProgressTint="@color/tint_neutral"
        Android:thumbTint="@color/tint_neutral"
    />

Et dans le code.

Setup Pre Draw callback sur la barre de recherche, où vous pouvez modifier la largeur et la hauteur de la barre de recherche. J'ai fait cette partie en c #, donc le code i utilisé était

            var volumeSlider = view.FindViewById<SeekBar>(Resource.Id.home_link_volume);

            var volumeFrameLayout = view.FindViewById<FrameLayout>(Resource.Id.linkVolumeFrameLayout);

            void OnPreDrawVolume(object sender, ViewTreeObserver.PreDrawEventArgs e)
            {
                volumeSlider.ViewTreeObserver.PreDraw -= OnPreDrawVolume;
                var h = volumeFrameLayout.Height;
                volumeSlider.Rotation = 270.0f;
                volumeSlider.LayoutParameters.Width = h;
                volumeSlider.RequestLayout();
            }

            volumeSlider.ViewTreeObserver.PreDraw += OnPreDrawVolume;

Ici, j’ajoute le programme d’écoute à l’événement PreDraw et lorsqu’il est déclenché, j’élimine le PreDraw afin qu’il ne passe pas en boucle infinie.

Ainsi, lorsque Pre Draw est exécuté, je récupère la hauteur de FrameLayout et l'assigne à Seekbar. Et définissez la rotation de seekbar sur 270. Comme ma seekbar se trouve dans la mise en page du cadre et que sa gravité est définie sur Centre. Je n'ai pas besoin de m'inquiéter de la traduction. En tant que Seekbar, restez toujours au milieu de la disposition du cadre.

La raison pour laquelle je supprime EventHandler est parce que seekbar.RequestLayout (); Fera en sorte que cet événement soit exécuté à nouveau.

0
soan saini

Enveloppez-le dans un FrameLayout afin d'éviter tout problème de taille.

  <FrameLayout
                Android:layout_width="@dimen/_20dp"
                Android:layout_marginStart="@dimen/_15dp"
                Android:layout_marginEnd="@dimen/_15dp"
                Android:layout_height="match_parent"
                Android:orientation="vertical">

                <SeekBar
                    Android:layout_width="150dp"
                    Android:layout_height="30dp"
                    Android:layout_gravity="center"
                    Android:rotation="270" />
  </FrameLayout>
0
Abhishek Sengupta

Dans mon cas, j'ai utilisé un seekBar ordinaire et ai simplement inversé la mise en page.

seekbark_layout.xml - ma mise en page qui contient la barre de recherche que nous devons rendre verticale.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/rootView"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

<SeekBar
    Android:id="@+id/seekBar"
    Android:layout_width="match_parent"
    Android:layout_height="50dp"
    Android:layout_alignParentBottom="true"/>

</RelativeLayout>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    tools:context="com.vgfit.seekbarexample.MainActivity">

<View
    Android:id="@+id/headerView"
    Android:layout_width="match_parent"
    Android:layout_height="100dp"
    Android:background="@color/colorAccent"/>

<View
    Android:id="@+id/bottomView"
    Android:layout_width="match_parent"
    Android:layout_height="100dp"
    Android:layout_alignParentBottom="true"
    Android:background="@color/colorAccent"/>

<include
    layout="@layout/seekbar_layout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:layout_above="@id/bottomView"
    Android:layout_below="@id/headerView"/>

 </RelativeLayout>

Et dans MainActivity, je fais pivoter seekbar_layout:

import Android.os.Bundle
import Android.support.v7.app.AppCompatActivity
import Android.widget.RelativeLayout
import kotlinx.Android.synthetic.main.seekbar_layout.*


class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    rootView.post {
        val w = rootView.width
        val h = rootView.height

        rootView.rotation = 270.0f
        rootView.translationX = ((w - h) / 2).toFloat()
        rootView.translationY = ((h - w) / 2).toFloat()

        val lp = rootView.layoutParams as RelativeLayout.LayoutParams
        lp.height = w
        lp.width = h
        rootView.requestLayout()
    }
}
}

En conséquence, nous avons la barre de recherche verticale nécessaire:  enter image description here

0
Vdovin