android.widget.Switch - écouteur d'événements on / off?


229

Je voudrais implémenter un bouton de commutation, android.widget.Switch (disponible à partir de l'API v.14).

<Switch
    android:id="@+id/switch1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Switch" />

Mais je ne sais pas comment ajouter un écouteur d'événements pour le bouton. Doit-il être un auditeur "onClick"? Et comment pourrais-je savoir s'il est activé ou non?


6
OnClick via XML fonctionne réellement - mais uniquement pour les "clics" sur le bouton, pas pour les "diapositives".
m02ph3u5

Réponses:


493

Le commutateur hérite CompoundButtondes attributs de, donc je recommanderais le OnCheckedChangeListener

mySwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        // do something, the isChecked will be
        // true if the switch is in the On position
    }
});

2
@Johan Aucun problème. Je ne sais pas pour vous mais j'aurais aimé qu'ils l'appellent OnCheckChangedListener, similaire à OnItemSelectedListener, car On- Noun - Verb -Listener est une convétion de nommage établie.
Sam

2
Mais lorsque vous mettez le sur un fragment par exemple, cette chose se déclenche toujours lorsque vous revisitez le fragment si vous positionnez le commutateur sur On.
klutch

1
@Sam Que se passe-t-il si je veux changer le commutateur à l'état ON ou OFF à l'aide de la méthode setChcked () et que je ne veux pas exécuter la méthode onCheckedChanged? Mais lorsque l'utilisateur tape à nouveau sur la méthode de commutation onCheckedChanged, s'exécute ... Y a-t-il un moyen de le faire?
deepak kumar

2
Les boutons ont OnCLick, les commutateurs n'ont pas OnChange! Équipe Google bien conçue!
Vassilis

1
@KZoNE Ce que j'ai fait ici, c'est utiliser l'écouteur de clics pour changer l'état et passer le commutateur à la méthode (dans mon cas, appel d'API) puis utiliser la méthode setChecked () pour changer l'état (comme dans onFailure / onError dans l'appel d'API) . J'espère que cela pourra aider.
deepak kumar

53

Utilisez l'extrait de code suivant pour ajouter un commutateur à votre mise en page via XML:

<Switch
     android:id="@+id/on_off_switch"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:textOff="OFF"
     android:textOn="ON"/>

Ensuite, dans la méthode onCreate de votre activité, obtenez une référence à votre commutateur et définissez son OnCheckedChangeListener:

Switch onOffSwitch = (Switch)  findViewById(R.id.on_off_switch); 
onOffSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    Log.v("Switch State=", ""+isChecked);
}       

});

3
Il s'agit d'une réponse plus claire vous donnant la mise en page et le code correspondant.
AshesToAshes

comment gérer plusieurs switchcompat dans le seul écouteur? Veuillez suggérer une réponse pour cela
Anand Savjani

22

Pour ceux qui utilisent Kotlin, vous pouvez définir un écouteur pour un commutateur (dans ce cas, avoir l'ID mySwitch) comme suit:

    mySwitch.setOnCheckedChangeListener { _, isChecked ->
         // do whatever you need to do when the switch is toggled here
    }

isChecked est vrai si le commutateur est actuellement coché (ON) et faux sinon.


19

Définissez votre disposition XML:

<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.neoecosystem.samplex.SwitchActivity">

    <Switch
        android:id="@+id/myswitch"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content" />

</RelativeLayout> 

Créez ensuite une activité

public class SwitchActivity extends ActionBarActivity implements CompoundButton.OnCheckedChangeListener {

    Switch mySwitch = null;


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


        mySwitch = (Switch) findViewById(R.id.myswitch);
        mySwitch.setOnCheckedChangeListener(this);
    }

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if (isChecked) {
            // do something when check is selected
        } else {
            //do something when unchecked
        }
    }

    ****
}

======== Pour l' API 14 ci-dessous, utilisez SwitchCompat =========

XML

<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.neoecosystem.samplex.SwitchActivity">

    <android.support.v7.widget.SwitchCompat
        android:id="@+id/myswitch"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content" />

</RelativeLayout>

Activité

public class SwitchActivity extends ActionBarActivity implements CompoundButton.OnCheckedChangeListener {

    SwitchCompat mySwitch = null;


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


        mySwitch = (SwitchCompat) findViewById(R.id.myswitch);
        mySwitch.setOnCheckedChangeListener(this);
    }

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if (isChecked) {
            // do something when checked is selected
        } else {
            //do something when unchecked
        }
    }
   *****
}

2
n'oubliez pas de vérifier buttonView.isPressed ()
JacksOnF1re

5

La disposition du widget Switch est quelque chose comme ça.

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <Switch
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="20dp"
        android:gravity="right"
        android:text="All"
        android:textStyle="bold"
        android:textColor="@color/black"
        android:textSize="20dp"
        android:id="@+id/list_toggle" />
</LinearLayout>

Dans la classe Activity, vous pouvez coder de deux manières. Dépend de l'utilisation que vous pouvez coder.

Première voie

public class ActivityClass extends Activity implements CompoundButton.OnCheckedChangeListener {
Switch list_toggle;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.return_vehicle);

    list_toggle=(Switch)findViewById(R.id.list_toggle);
    list_toggle.setOnCheckedChangeListener(this);
    }
}

public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
    if(isChecked) {
        list_toggle.setText("Only Today's");  //To change the text near to switch
        Log.d("You are :", "Checked");
    }
    else {
        list_toggle.setText("All List");   //To change the text near to switch
        Log.d("You are :", " Not Checked");
    }
}

Deuxième voie

public class ActivityClass extends Activity {
Switch list_toggle;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.return_vehicle);

    list_toggle=(Switch)findViewById(R.id.list_toggle);
    list_toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
       @Override
       public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
          if(isChecked) {
             list_toggle.setText("Only Today's");  //To change the text near to switch
             Log.d("You are :", "Checked");
          }
          else {
             list_toggle.setText("All List");  //To change the text near to switch
             Log.d("You are :", " Not Checked");
          }
       }       
     });
   }
}

2

Vous pouvez utiliser DataBinding et ViewModel pour l'événement Switch Checked Change

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
                name="viewModel"
                type="com.example.ui.ViewModel" />
    </data>
    <Switch
            android:id="@+id/on_off_switch"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onCheckedChanged="@{(button, on) -> viewModel.onCheckedChange(on)}"
     />


1
android.widget.Switch n'a pas onCheckedChanged attirbute. Vous obtiendrez l'erreur: AAPT: erreur: attribut android: onCheckedChanged introuvable.
Épuisé le

1

il y a deux façons,

  1. en utilisant xml onclick view Ajouter un commutateur en XML comme ci-dessous:

    <Switch
    android:id="@+id/switch1"
    android:onClick="toggle"/>

Dans votre classe d'activité (par exemple MainActivity.java)

    Switch toggle; //outside oncreate
    toggle =(Switch) findViewById(R.id.switch1); // inside oncreate

    public void toggle(View view) //outside oncreate
    {
        if( toggle.isChecked() ){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                start.setBackgroundColor(getColor(R.color.gold));
                stop.setBackgroundColor(getColor(R.color.white));
            }
        }
        else
        {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                stop.setBackgroundColor(getColor(R.color.gold));
                start.setBackgroundColor(getColor(R.color.white));
            }
        }
    }
  1. utilisation de l'écouteur de clic

Ajoutez Switch en XML comme ci-dessous:

Dans votre classe d'activité (par exemple MainActivity.java)

    Switch toggle; // outside oncreate
    toggle =(Switch) findViewById(R.id.switch1);  // inside oncreate


    toggle.setOnClickListener(new View.OnClickListener() {   // inside oncreate
        @Override
        public void onClick(View view) {

            if( toggle.isChecked() ){
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    start.setBackgroundColor(getColor(R.color.gold));
                }
            }
            else
            {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    stop.setBackgroundColor(getColor(R.color.gold));
                }
            }

        }

    });

0

Ma solution, en utilisant un SwitchCompatet Kotlin. Dans ma situation, je devais réagir à un changement uniquement si l'utilisateur l'avait déclenché via l'interface utilisateur. En fait, mon commutateur réagit à un LiveData, et ce fait à la fois setOnClickListeneret setOnCheckedChangeListenerinutilisable. setOnClickListeneren fait, il réagit correctement à l'interaction de l'utilisateur, mais il n'est pas déclenché si l'utilisateur fait glisser le pouce sur le commutateur.setOnCheckedChangeListenerà l'autre extrémité est également déclenchée si le commutateur est basculé par programme (par exemple par un observateur). Maintenant, dans mon cas, le commutateur était présent sur deux fragments, et ainsi onRestoreInstanceState déclencherait dans certains cas le commutateur avec une ancienne valeur écrasant la valeur correcte.

Donc, j'ai regardé le code de SwitchCompat, et j'ai réussi à imiter son comportement en distinguant le clic et le glisser et je l'ai utilisé pour créer un écouteur tactile personnalisé qui fonctionne comme il se doit. Et c'est parti:

/**
 * This function calls the lambda function passed with the right value of isChecked
 * when the switch is tapped with single click isChecked is relative to the current position so we pass !isChecked
 * when the switch is dragged instead, the position of the thumb centre where the user leaves the
 * thumb is compared to the middle of the switch, and we assume that left means false, right means true
 * (there is no rtl or vertical switch management)
 * The behaviour is extrapolated from the SwitchCompat source code
 */
class SwitchCompatTouchListener(private val v: SwitchCompat, private val lambda: (Boolean)->Unit) :  View.OnTouchListener {
    companion object {
        private const val TOUCH_MODE_IDLE = 0
        private const val TOUCH_MODE_DOWN = 1
        private const val TOUCH_MODE_DRAGGING = 2
    }

    private val vc = ViewConfiguration.get(v.context)
    private val mScaledTouchSlop = vc.scaledTouchSlop
    private var mTouchMode = 0
    private var mTouchX = 0f
    private var mTouchY = 0f

    /**
     * @return true if (x, y) is within the target area of the switch thumb
     * x,y and rect are in view coordinates, 0,0 is top left of the view
     */
    private fun hitThumb(x: Float, y: Float): Boolean {
        val rect = v.thumbDrawable.bounds
        return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom
    }

    override fun onTouch(view: View, event: MotionEvent): Boolean {
        if (view == v) {
            when (MotionEventCompat.getActionMasked(event)) {
                MotionEvent.ACTION_DOWN -> {
                    val x = event.x
                    val y = event.y
                    if (v.isEnabled && hitThumb(x, y)) {
                        mTouchMode = TOUCH_MODE_DOWN;
                        mTouchX = x;
                        mTouchY = y;
                    }
                }
                MotionEvent.ACTION_MOVE -> {
                    val x = event.x
                    val y = event.y
                    if (mTouchMode == TOUCH_MODE_DOWN &&
                        (abs(x - mTouchX) > mScaledTouchSlop || abs(y - mTouchY) > mScaledTouchSlop)
                    )
                        mTouchMode = TOUCH_MODE_DRAGGING;
                }
                MotionEvent.ACTION_UP,
                MotionEvent.ACTION_CANCEL -> {
                    if (mTouchMode == TOUCH_MODE_DRAGGING) {
                        val r = v.thumbDrawable.bounds
                        if (r.left + r.right < v.width) lambda(false)
                        else lambda(true)
                    } else lambda(!v.isChecked)
                    mTouchMode = TOUCH_MODE_IDLE;
                }
            }
        }
        return v.onTouchEvent(event)
    }
}

Comment l'utiliser:

l'écouteur tactile réel qui accepte un lambda avec le code à exécuter:

myswitch.setOnTouchListener(
    SwitchCompatTouchListener(myswitch) {
        // here goes all the code for your callback, in my case
        // i called a service which, when successful, in turn would 
        // update my liveData 
        viewModel.sendCommandToMyService(it) 
    }
)

Par souci d'exhaustivité, voici à quoi switchstateressemblait l'observateur de l'état (si vous l'avez):

switchstate.observe(this, Observer {
    myswitch.isChecked = it
})

L'équipe Android devrait vraiment résoudre ce problème ... Ce que j'ai fait est dans mon observateur LiveData, je désenregistre le onCheck, fais mon action, puis le remets en place. Cela ne fonctionne que parce que les changements d'interface utilisateur se produisent sur 1 thread (le thread principal).
Jeremy Jao

0

À Kotlin:

        switch_button.setOnCheckedChangeListener { buttonView, isChecked ->
        if (isChecked) {
            // The switch enabled
            text_view.text = "Switch on"

        } else {
            // The switch disabled
            text_view.text = "Switch off"

        }
    }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.