android.widget.Switch - Ein / Aus-Ereignis-Listener?

229

Ich möchte eine Schaltfläche implementieren, android.widget.Switch (verfügbar ab API v.14).

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

Ich bin mir jedoch nicht sicher, wie ich einen Ereignis-Listener für die Schaltfläche hinzufügen soll. Sollte es ein "onClick" -Hörer sein? Und wie würde ich wissen, ob es "eingeschaltet" ist oder nicht?

Johan
quelle
6
OnClick via XML funktioniert tatsächlich - aber nur für "Klicks" auf die Schaltfläche, nicht für "Folien".
m02ph3u5

Antworten:

492

Switch erbt CompoundButtondie Attribute, daher würde ich den OnCheckedChangeListener empfehlen

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
    }
});
Sam
quelle
2
@ Joan Kein Problem. Ich weiß nicht , über Sie , aber ich wünschte , sie nannten es OnCheckChangedListener, ähnlich wie OnItemSelectedListener, da On- Nomen - Verb -Listener ein etabliertes Namensgebung convetion ist.
Sam
2
Wenn Sie beispielsweise das Fragment aktivieren, wird dieses Element immer ausgelöst, wenn Sie das Fragment erneut aufrufen, wenn Sie den Schalter auf Ein stellen.
Klutch
1
@Sam Was ist, wenn ich den Schalter mit der Methode setChcked () in den Status ON oder OFF ändern und die Methode onCheckedChanged nicht ausführen möchte? Aber wenn der Benutzer erneut auf die Schaltermethode onCheckedChanged tippt, wird sie ausgeführt ... Gibt es eine Möglichkeit, dies zu tun?
Deepak Kumar
2
Tasten haben OnCLick, Schalter haben nicht OnChange! Gut gestaltetes Google-Team!
Vassilis
1
@KZoNE Was ich hier getan habe, ist der Klick-Listener, um den Status zu ändern und den Wechsel zur Methode zu übergeben (in meinem Fall API-Aufruf) und dann die setChecked () -Methode, um den Status zu ändern (wie in onFailure / onError im API-Aufruf). . Hoffentlich hilft das.
Deepak Kumar
53

Verwenden Sie das folgende Snippet, um Ihrem Layout über XML einen Switch hinzuzufügen:

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

Rufen Sie dann in der onCreate-Methode Ihrer Aktivität einen Verweis auf Ihren Switch ab und legen Sie dessen OnCheckedChangeListener fest:

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

});
Shridutt Kothari
quelle
3
Dies ist eine klarere Antwort, die Ihnen das Layout und den Code gibt, die dahinter passen.
AshesToAshes
Wie verwalte ich mehrere Switchcompat in einem einzigen Listener? Bitte schlagen Sie eine Antwort darauf vor
Anand Savjani
22

Für Benutzer von Kotlin können Sie einen Listener für einen Switch (in diesem Fall mit der ID mySwitch) wie folgt festlegen :

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

isChecked ist wahr, wenn der Schalter gerade aktiviert ist (EIN), andernfalls falsch.

Faheel
quelle
19

Definieren Sie Ihr XML-Layout:

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

Erstellen Sie dann eine Aktivität

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

    ****
}

======== Für unten stehende API 14 verwenden Sie 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>

Aktivität

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
        }
    }
   *****
}
neferpitou
quelle
2
Vergessen Sie nicht, buttonView.isPressed ()
JacksOnF1re
5

Das Layout für das Switch-Widget ist ungefähr so.

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

In der Aktivitätsklasse können Sie auf zwei Arten codieren. Hängt von der Verwendung ab, die Sie codieren können.

Erster Weg

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

Zweiter Weg

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");
          }
       }       
     });
   }
}
Abish R.
quelle
2

Sie können DataBinding und ViewModel für das Ereignis Switch Checked Change verwenden

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

Ali Hasan
quelle
1
android.widget.Switch hat kein onCheckedChanged-Attirbute. Sie erhalten Fehler: AAPT: Fehler: Attribut android: onCheckedChanged nicht gefunden.
Ausverkauft
0

Meine Lösung mit a SwitchCompatund Kotlin. In meiner Situation musste ich nur dann auf eine Änderung reagieren, wenn der Benutzer sie über die Benutzeroberfläche auslöste. In der Tat, mein Schalter reagiert auf ein LiveData, und dies sowohl gemacht setOnClickListenerund setOnCheckedChangeListenerunbrauchbar. setOnClickListenerTatsächlich reagiert es korrekt auf Benutzerinteraktionen, wird jedoch nicht ausgelöst, wenn der Benutzer den Daumen über den Switch zieht.setOnCheckedChangeListeneram anderen Ende wird auch ausgelöst, wenn der Schalter programmgesteuert umgeschaltet wird (z. B. von einem Beobachter). In meinem Fall war der Schalter auf zwei Fragmenten vorhanden, und so löste onRestoreInstanceState in einigen Fällen den Schalter mit einem alten Wert aus, der den korrekten Wert überschrieb.

Also habe ich mir den Code von SwitchCompat angesehen und konnte sein Verhalten bei der Unterscheidung von Klicken und Ziehen erfolgreich nachahmen und daraus einen benutzerdefinierten Touchlistener erstellen, der ordnungsgemäß funktioniert. Auf geht's:

/**
 * 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)
    }
}

Wie man es benutzt:

Der eigentliche Touch-Listener, der ein Lambda mit dem auszuführenden Code akzeptiert:

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

Der Vollständigkeit halber sah der Beobachter des Staates switchstate(falls vorhanden) folgendermaßen aus:

switchstate.observe(this, Observer {
    myswitch.isChecked = it
})
AndrewBloom
quelle
Das Android-Team sollte das wirklich beheben ... Was ich installiert habe, ist in meinem LiveData-Beobachter. Ich hebe die Registrierung von onCheck auf, führe meine Aktion aus und setze sie dann zurück. Dies funktioniert nur, weil Änderungen an der Benutzeroberfläche in einem Thread (dem Hauptthread) vorgenommen werden.
Jeremy Jao
0

Es gibt zwei Möglichkeiten:

  1. Verwenden der XML-Onclick-Ansicht Add Switch in XML wie folgt:

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

In Ihrer Aktivitätsklasse (z. B. 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. Verwenden Sie den On-Click-Listener

Fügen Sie Switch in XML wie folgt hinzu:

In Ihrer Aktivitätsklasse (z. B. 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));
                }
            }

        }

    });
Mrudul Addipalli
quelle
0

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

        }
    }
Shadros
quelle