onCheckedChanged wird automatisch aufgerufen


75

Ich habe einen Schalter in einer Recyclingansicht und Daten werden in der Recyclingansicht angezeigt, nachdem Daten aus der Datenbank abgerufen wurden. Wenn die Recycling-Ansicht geöffnet wird, lese ich DB und wenn ein Feld in DB "Y" ist, aktiviere ich den Switch oder deaktiviere den Switch. Jetzt ist das Problem damit verbunden, dass auch der onCheckedchanged-Listener aufgerufen wird. Ich möchte, dass onCheckedChanged nur aufgerufen wird, wenn der Benutzer den Schalter manuell einstellt.

Beim Öffnen wird die folgende Recycling-Ansicht ausgeführt:

holder.enabledisable.setChecked(messengerRecord.get_is_valid().equalsIgnoreCase("Y"));

ViewHolder-Klasse:

public class viewHolder extends RecyclerView.ViewHolder implements CompoundButton.OnCheckedChangeListener{
public SwitchCompat enabledisable;
 public viewHolder(View v) {
            enabledisable = (SwitchCompat) v.findViewById(R.id.enabledisable);
            enabledisable.setOnCheckedChangeListener(this);
...................................
...................................

OncheckedChanged-Methode, die aufgerufen wird, wenn die recyclerView gerade geöffnet wird:

@Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            Log.v("ranjith","called oncheckedchanged");
            MessengerRecord rec;
            rec = dbHelper.getRecord(descview.getText().toString());
            switch (buttonView.getId()) {
                case R.id.enabledisable:
                    if (isChecked) {
                        rec.set_is_valid("Y");
                        dbHelper.updateRecord(rec);
                     }
}

In der Layoutdatei:

<android.support.v7.widget.SwitchCompat
    android:layout_marginRight="16dp"
    android:layout_marginEnd="16dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:focusable="false"
    android:id="@+id/enabledisable"
    android:layout_alignRight="@+id/textview_to"
    android:layout_alignEnd="@+id/textview_to"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"/>

Antworten:


251

Es ist seltsam, dass wir alle dieses Problem haben, aber keine offizielle Antwort von Google auf dieses einfache Problem.

Am einfachsten ist es zu überprüfen:

buttonView.isPressed()

Wenn true, bedeutet dies, dass der Benutzer auf die Ansicht geklickt hat.

Keine globalen Variablen erforderlich.

Hoffe das hilft.


4
Das funktioniert definitiv. Aber gibt es ein Ereignis, wenn der Benutzer den Schalter drückt? In diesem Fall funktioniert dies nicht, wenn der verwendete Schalter den Schalter verschiebt.
Dhun

Vielen Dank für diese einfache, aber großartige Lösung. Dies kann auch mit verwendet werden RadioButton. Denn RadioGroupich habe diese Antwort geschrieben .
Sufian

Vielen Dank an @Surfian für die Erwähnung :), ich bin froh, dass dies auch für RadioButton
Sulfkain

16
Die Lösung funktioniert nicht, wenn Sie den Switch sehr schnell durchziehen. Dummes Google
DàChún

Sie können manuell vorgehen, indem Sie OnClickListener implementieren und mit der isChecked () -Methode von SwitchCompat prüfen. Die Verwendung von onCheckedChangeListener war nicht erforderlich.
mr.boyfox

13

Ich habe diese Unterklasse von SwitchCompat verwendet, um dieses Problem zu vermeiden. Auf diese Weise benötige ich keinen Boilerplate-Code, in dem ich diese Klasse verwende. Wenn Sie das Häkchen ändern müssen, ohne den Listener auszulösen, verwenden Sie setCheckedSilentanstelle von setChecked:

import android.content.Context;
import android.os.Parcelable;
import android.support.v7.widget.SwitchCompat;
import android.util.AttributeSet;

/**
 * Created by emanuel on 30/5/16.
 */
public class Switch extends SwitchCompat {

    private OnCheckedChangeListener listener;

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

    @Override
    public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
        this.listener = listener;
        super.setOnCheckedChangeListener(listener);
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {
        super.setOnCheckedChangeListener(null);
        super.onRestoreInstanceState(state);
        super.setOnCheckedChangeListener(listener);
    }

    public void setCheckedSilent(boolean checked) {
        super.setOnCheckedChangeListener(null);
        super.setChecked(checked);
        super.setOnCheckedChangeListener(listener);
    }
}

onRestoreInstanceStatehat auch das Abhören ausgelöst, wenn in der onViewCreatedMethode festgelegt und Sie zu einem vorherigen Fragment zurückkehren. Hoffe es funktioniert bei dir!


11

Versuche dies

@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

        if (buttonView.isPressed()) {
          ... //returns true, if user clicks the switch button        
        }}

1
Dies funktioniert nicht, wenn das Wischen sehr schnell erfolgt.
Manuel

2

Das funktioniert bei mir:

 boolean selected = preferences.isChecked();
        yourCheckBox.setOnCheckedChangeListener(new 
            CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, 
            boolean isChecked) {
                    if (buttonView.isPressed()) {
               preferences.setChecked(isChecked);
                    } else {
                        yourCheckBox.setChecked(selected);
                    }
                }
            });

Dies funktioniert nicht, wenn das Wischen sehr schnell erfolgt.
Manuel

0

Verwenden Sie eine globale boolesche Variable. Wenn Sie Daten aus der Datenbank lesen, setzen Sie sie auf "true" und setzen Sie sie nach Prüfung (if) in onCheckChange erneut auf "false". Überprüfen Sie im ersten Teil der onCheckChange-Methode, ob diese Variable falsch ist. Führen Sie die Codes aus. Andernfalls wird zurückgegeben (der Standardwert dieser Variablen muss false sein.).

@Override
   public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
     if(!isSourceDB){ 

       Log.v("ranjith","called oncheckedchanged");
        MessengerRecord rec;
        rec = dbHelper.getRecord(descview.getText().toString());
        switch (buttonView.getId()) {
            case R.id.enabledisable:
                if (isChecked) {
                    rec.set_is_valid("Y");
                    dbHelper.updateRecord(rec);

          }
    }//end if
  isSourceDB = false; }// end oncheckedchange

Dies scheint eine Problemumgehung zu sein. Ich suchte nach einer Funktionalität in Android, die nur dann aktiviert wird, wenn der Benutzer darauf klickt (dh der Fokus wird empfangen). Aber es funktioniert. Stimmen Sie von mir ab.
Psypher

@Ranjith: Wenn der Schalter zuerst angeklickt wird, wird die toggle () -Methode aufgerufen und in der toggle-Methode die setchecked () -Methode aufgerufen. Daher sollten Sie die obigen Codes in die Umschaltmethode einfügen, die nicht geändert wurde. Übrigens, wenn Sie nur in onCheckChange () schreiben möchten, sollten Sie eine Methode schreiben, die nur den GUI-Status des Schalters ändert und ihn beim Lesen von Daten aus der Datenbank aufruft.
mk72

0

Ich hatte das gleiche Problem im ViewPager-Bildschirm für Fragmente. Wenn wir zwischen Fragmenten wechseln, wird onCheckedChanged Listener immer wieder aufgerufen.

Wenn noch jemand nach diesem Problem sucht, versuchen Sie es bitte.

@Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

            if (buttonView.isInTouchMode()) {
              ... //Your code will come here.         
            }
}

0

Kotlin Entwickler:

    checkboxXYZ.setOnCheckedChangeListener { btnView, isChecked ->
        if (btnView.isPressed) {

        }
    }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.