2013-03-20 6 views

Antwort

193

Nein nennen kann, können Sie es nicht tun . Die onCheckedChanged Methode wird direkt von setChecked aufgerufen. Was Sie tun können, ist die folgende:

mCheck.setOnCheckedChangeListener (null); 
mCheck.setChecked (false); 
mCheck.setOnCheckedChangeListener (mListener); 

die source of CheckBox Siehe, und die Umsetzung von setChecked:

public void setChecked(boolean checked) { 
    if (mChecked != checked) { 
     mChecked = checked; 
     refreshDrawableState(); 

     // Avoid infinite recursions if setChecked() is called from a listener 
     if (mBroadcasting) { 
      return; 
     } 

     mBroadcasting = true; 
     if (mOnCheckedChangeListener != null) { 
      mOnCheckedChangeListener.onCheckedChanged(this, mChecked); 
     } 

     if (mOnCheckedChangeWidgetListener != null) { 
      mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked); 
     } 

     mBroadcasting = false;    
    } 
} 
+4

Wie wollen Sie 'mListener' zu bekommen? 'Checkbox' hat keinen Getter für seinen' OnCheckChangeListener' – tir38

+10

Nun, es ist nicht nötig, einfach zu downvoten, weil Sie die Lösung nicht verstehen. 'mlistener' ist eine Implementierung der 'OnCheckChangedListener'-Schnittstelle, die vom Programmierer erstellt wurde. Meine Antwort bedeutet, dass der Programmierer einen Verweis auf ** ihre eigene Implementierung ** - "mlistener" beibehalten hat. – Shade

+0

Wäre es ineffizient, den Listener zu ändern, wenn Sie die setChecked() -Methode wiederholt verwenden möchten? – Ren

0

Ich denke, die die Reflexion ist der einzige Weg. Etwas wie folgt aus:

CheckBox cb = (CheckBox) findViewById(R.id.checkBox1); 
try { 
    Field field = CompoundButton.class.getDeclaredField("mChecked"); 
    field.setAccessible(true); 
    field.set(cb, cb.isChecked()); 
    cb.refreshDrawableState(); 
    cb.invalidate(); 
} catch (Exception e) { 
    e.printStackTrace(); 
} 
+0

Kann arbeiten, bis die Devs den Feldnamen ändern oder zB die "isChecked" -Methode in der Hierarchie hochziehen ... oder ein anderes Refactoring machen ... Mindestens etwas hinzufügen wie 'if (Build.VERSION.SDK_INT <= Build.VERSION_CODES .JELLY_BEAN) {/ * do reflection * /} ' – aeracode

+0

Es ist eine falsche Idee zu ermutigen, die API zu knacken und sich in Interna zu vertiefen. Jede Änderung an der Implementierung führt zum Fehlschlagen von Apps. – mspanc

8

Sie einfach setonclickListener verwenden, wird es funktioniert gut, und das ist sehr einfache Methode, Dank :)

+26

onClick() wird nicht aufgerufen, wenn der Benutzer den Schalter verschiebt. – James

+1

In der Tat haben Sie damit keinen Handler, wenn der Benutzer den Schalter zieht. –

+0

dann, wie erhalten Sie isChecked Wert, also wahr oder falsch? – Abhi

10

Eine andere Möglichkeit, dies zu erreichen, ist durch eine benutzerdefinierte CheckBox mit:

public class CheckBox extends AppCompatCheckBox { 
    private OnCheckedChangeListener mListener; 

    public CheckBox(final Context context) { 
     super(context); 
    } 

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

    public CheckBox(final Context context, final AttributeSet attrs, final int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
    } 

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

    public void setChecked(final boolean checked, final boolean alsoNotify) { 
     if (!alsoNotify) { 
      super.setOnCheckedChangeListener(null); 
      super.setChecked(checked); 
      super.setOnCheckedChangeListener(mListener); 
      return; 
     } 
     super.setChecked(checked); 
    } 

    public void toggle(boolean alsoNotify) { 
     if (!alsoNotify) { 
      super.setOnCheckedChangeListener(null); 
      super.toggle(); 
      super.setOnCheckedChangeListener(mListener); 
     } 
     super.toggle(); 
    } 
} 

Probe Nutzung:

checkBox.setChecked(true,false); 
3

Sie könnten diese SafeCheckBox-Klasse verwenden als Checkbox:

public class SafeCheckBox extends AppCompatCheckBox implements CompoundButton.OnCheckedChangeListener { 

    private OnSafeCheckedListener onSafeCheckedListener; 

    private int mIgnoreListener = CALL_LISTENER; 

    public static final int IGNORE = 0; 
    public static final int CALL_LISTENER = 1; 

    @Retention(RetentionPolicy.SOURCE) 
    @IntDef({IGNORE, CALL_LISTENER}) 
    public @interface ListenerMode { 
    } 

    public SafeCheckBox(Context context) { 
     super(context); 
     init(context); 
    } 

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

    public SafeCheckBox(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
     init(context); 
    } 

    /** 
    * @param checkState  change state of the checkbox to 
    * @param mIgnoreListener true to ignore the listener else listener will be notified 
    */ 
    public void setSafeCheck(boolean checkState, @ListenerMode int mIgnoreListener) { 
     if (isChecked() == checkState) return; //already in the same state no need to fire listener. 

     if (onSafeCheckedListener != null) { // this to avoid a bug if the user listens for the event after using this method and in that case he will miss first check 
      this.mIgnoreListener = mIgnoreListener; 
     } else { 
      this.mIgnoreListener = CALL_LISTENER; 
     } 
     setChecked(checkState); 
    } 

    private void init(Context context) { 
     setOnCheckedChangeListener(this); 
    } 


    public OnSafeCheckedListener getOnSafeCheckedListener() { 
     return onSafeCheckedListener; 
    } 

    public void setOnSafeCheckedListener(OnSafeCheckedListener onSafeCheckedListener) { 
     this.onSafeCheckedListener = onSafeCheckedListener; 
    } 

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

     if (onSafeCheckedListener != null) 
      onSafeCheckedListener.onAlwaysCalledListener(buttonView, isChecked);// this has to be called before onCheckedChange 
     if (onSafeCheckedListener != null && (mIgnoreListener == CALL_LISTENER)) { 
      onSafeCheckedListener.onCheckedChanged(buttonView, isChecked); 
     } 
     mIgnoreListener = CALL_LISTENER; 
    } 

    /** 
    * Listener that will be called when you want it to be called. 
    * On checked change listeners are called even when the setElementChecked is called from code. :(
    */ 
    public interface OnSafeCheckedListener extends OnCheckedChangeListener { 
     void onAlwaysCalledListener(CompoundButton buttonView, boolean isChecked); 
    } 
} 
  • Dann könnte man nennen: -

    setSafeCheck(true,ListenerMode.IGNORE);// OnCheckedChange listener will not be notified

2

mit @Shade Antwort Kotlin die Erweiterungen verwenden:

1

für jeden, stolpert darüber, ein einfacher Weg, dies zu tun ist, um nur einen Tag auf dem Kontrollkästchen zu verwenden, und überprüft dann den Tag auf seinen Zuhörern (Code ist in Kotlin):

checkBox.tag = false 
checkBox.setOnCheckedChangeListener{ buttonView, isChecked -> 
    if(checkBox.tag != true) { 
     //Do some stuff 
    } else { 
     checkBox.tag = false 
    } 

Dann, wenn den Tag auf true nur gesetzt Zugreifen, bevor Sie die Set isChecked auf true, wenn Sie die Wertänderung ignoriert werden sollen:

checkBox.tag = true 
checkBox.isChecked = true 

Sie auch den Tag zu einem Schlüssel unter Verwendung des alternativen setTag Verfahren abbilden könnte, die einen Schlüssel benötigt, wenn Sie über Verständlichkeits besorgt waren. Aber wenn alles in einer einzigen Klasse enthalten ist, werden ein paar Kommentar-Strings mehr als genug sein, um zu erklären, was passiert.

0

Null auf den Optionsschalter changeListener vor dem Überprüfen setzen. Sie können den Listener nach Auswahl des Optionsfelds erneut einstellen.

radioGroup.setOnCheckedChangeListener(null); 
radioGroup.check(R.id.radioButton); 
radioGroup.setOnCheckedChangeListener(new 

RadioGroup.OnCheckedChangeListener() { 
    @Override 
    public void onCheckedChanged(RadioGroup radioGroup, @IdRes int i) { 

    } 
}); 
0

Meine Lösung in Java geschrieben, basierend auf @ Chris Antwort:

chkParent.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
      @Override 
      public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
       if(buttonView.getTag() != null){ 
        buttonView.setTag(null); 
        return; 
       } 
       if(isChecked){ 
        chkChild.setTag(true); 
        chkChild.setChecked(false); 
       } 
       else{ 
        chkParent.setChecked(true); 
       } 
      } 
}); 

chkChild.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
      @Override 
      public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
       if(buttonView.getTag() != null){ 
        buttonView.setTag(null); 
        return; 
       } 
       if(isChecked){ 
        chkParent.setTag(true); 
        chkParent.setChecked(false); 
       } 
       else{ 
        chkChild.setChecked(true); 
       } 
      } 
}); 

2 Checkbox und immer wird man überprüft werden (ein zunächst überprüft, obwohl sein muss). Setzen Sie den Tag auf True Blocks onCheckedChanged Listener.

0

Meine Interpretation, die ich denke, ist die einfachste
hilfreich sein können)

public class ProgrammableSwitchCompat extends SwitchCompat { 

    public boolean isCheckedProgrammatically = false; 

    public ProgrammableSwitchCompat(final Context context) { 
     super(context); 
    } 

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

    public ProgrammableSwitchCompat(final Context context, final AttributeSet attrs, final int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
    } 

    @Override 
    public void setChecked(boolean checked) { 
     isCheckedProgrammatically = false; 
     super.setChecked(checked); 
    } 

    public void setCheckedProgrammatically(boolean checked) { 
     isCheckedProgrammatically = true; 
     super.setChecked(checked); 
    } 
} 

es wird setChecked(boolean) Funktion
auslösen, die

@Override 
public void onCheckedChanged(CompoundButton compoundButton, boolean on) { 
    if (((ProgrammableSwitchCompat) compoundButton).isCheckedProgrammatically) { 
     return; 
    } 
    //... 
    ((ProgrammableSwitchCompat) compoundButton).setCheckedProgrammatically(true); 
    //... 
    ((ProgrammableSwitchCompat) compoundButton).setCheckedProgrammatically(false); 
    //... 
} 

Gebrauch verwenden alle diese

0

ist eine einfache Lösung, die ich verwendet habe:
definieren einen benutzerdefinierten Zuhörer:

class CompoundButtonListener implements CompoundButton.OnCheckedChangeListener { 

    boolean enabled = false; 

    @Override 
    public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { 

    } 

    void enable() { 
     enabled = true; 
    } 

    void disable() { 
     enabled = false; 
    } 

    boolean isEnabled() { 
     return enabled; 
    } 
} 

Initialisierung:

CompoundButtonListener checkBoxListener = new CompoundButtonListener() { 
    @Override 
    public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { 
     if (isEnabled()) { 
      // Your code goes here 
     } 
    } 
}; 
myCheckBox.setOnCheckedChangeListener(checkBoxListener); 

Verbrauch:

checkBoxListener.disable(); 

// Some logic based on which you will modify CheckBox state 
// Example: myCheckBox.setChecked(true) 

checkBoxListener.enable();