OnCheckChanged को ट्रिगर किए बिना चेकबॉक्स मान बदलें


147

मेरे पास है setOnCheckedChangeListener अपने लिए लागू किया हैcheckbox

क्या कोई रास्ता है जिससे मैं फोन कर सकता हूं

checkbox.setChecked(false);

ट्रिगर किए बिना onCheckedChanged


सिर्फ एक साधारण सच्चे / झूठे झंडे का उपयोग क्यों नहीं किया जाता? यह इस समस्या के बारे में जाने का सबसे सरल तरीका है और यह केवल अतिरिक्त कोड की तीन पंक्तियों की तरह है। नीचे मेरा जवाब देखें।
रुचिर बरोनिया

जवाबों:


279

नहीं, आप ऐसा नहीं कर सकते। onCheckedChangedविधि से सीधे कहा जाता है setChecked। आप निम्न कार्य कर सकते हैं:

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

चेकबॉक्स का स्रोत और उसका कार्यान्वयन देखें 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;            
    }
}

6
आप कैसे प्राप्त करने का प्रस्ताव करते हैं mListener? Checkboxइसके लिए एक OnCheckChangeListener
गटर

20
ठीक है, क्योंकि आप समाधान समझ में नहीं आता है बस को कम करने की जरूरत नहीं है। इंटरफ़ेस mListenerका एक कार्यान्वयन है OnCheckChangedListener, जो प्रोग्रामर द्वारा बनाया गया था। मेरे उत्तर का तात्पर्य है कि प्रोग्रामर ने अपने स्वयं के कार्यान्वयन के संदर्भ को बनाए रखा - mListener
शेड

क्या आप श्रोता को बदलने के लिए अक्षम होंगे यदि आप सेटकिटेड () विधि का दोहराव से उपयोग करना चाहते हैं?
रेन

4
@, श्रोता को बदलने से CheckBoxऑब्जेक्ट में केवल एक संपत्ति की स्थापना शामिल है । मैं यह नहीं कहूंगा कि यह अक्षम है।
शेड

डॉक्टर पढ़ता है "चेक किए गए रेडियो बटन को बदलने पर कॉल किया जाता है। जब चयन साफ़ हो जाता है, checkId -1 है"। यह वास्तव में भ्रामक है, यह या तो isChecked के माध्यम से पारित किया जाना चाहिए।
AA_PV

69

इस कोड को OnCheckedChangeListener के अंदर जोड़ें:

if(!compoundButton.isPressed()) {
            return;
}

यह हमें मौसम चेकबॉक्स स्थिति का पता लगाने में मदद करेगा जो प्रोग्रामेटिक रूप से या उपयोगकर्ता कार्रवाई द्वारा बदल दिया गया था।


11
यह एक समाधान के रूप में चिह्नित किया जाना चाहिए, एक आकर्षण की तरह काम करता है!
अश्विन बलानी

5
जागरूक रहें! यह एक्सेसिबिलिटी मोड को तोड़ देता है! isPressed () सत्य नहीं है जब इसे वॉयस असिस्टेंट मोड से डबल टैप द्वारा ट्रिगर किया जाता है।
A1M

21

इसे प्राप्त करने का एक और संभावित तरीका एक कस्टम चेकबॉक्स का उपयोग करके है, जो आपको यह चुनने देगा कि आप श्रोता को बुलाना चाहते हैं या नहीं:

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

कोटलिन संस्करण, यदि आप पसंद करते हैं:

class CheckBox @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : AppCompatCheckBox(context, attrs, defStyleAttr) {
    private var listener: CompoundButton.OnCheckedChangeListener? = null

    override fun setOnCheckedChangeListener(listener: CompoundButton.OnCheckedChangeListener?) {
        this.listener = listener
        super.setOnCheckedChangeListener(listener)
    }

    fun setChecked(checked: Boolean, alsoNotify: Boolean) {
        if (!alsoNotify) {
            super.setOnCheckedChangeListener(null)
            super.setChecked(checked)
            super.setOnCheckedChangeListener(listener)
            return
        }
        super.setChecked(checked)
    }

    fun toggle(alsoNotify: Boolean) {
        if (!alsoNotify) {
            super.setOnCheckedChangeListener(null)
            super.toggle()
            super.setOnCheckedChangeListener(listener)
        }
        super.toggle()
    }
}

नमूना उपयोग:

checkBox.setChecked(true,false);

11

आप बस setonclickListener का उपयोग करते हैं, यह ठीक काम करेगा और यह बहुत सरल विधि है, धन्यवाद :)


35
जब उपयोगकर्ता स्विच को स्लाइड करता है तो onClick () को नहीं बुलाया जाता है।
जेम्स

2
दरअसल, ऐसा करने से आप बिना हैंडलर छोड़ देते हैं, जब उपयोगकर्ता टॉगल करता है।
विक्टर जी

तो फिर आप कैसे प्राप्त करेंगे चेक किया गया मूल्य अर्थात सही या गलत?
अभि

6

@ जवाब के साथ कोटलिन के एक्सटेंशन का उपयोग करना:

fun CompoundButton.setCustomChecked(value: Boolean,listener: CompoundButton.OnCheckedChangeListener) {
     setOnCheckedChangeListener(null)
     isChecked = value
     setOnCheckedChangeListener(listener)
}

6

किसी के लिए भी जो इस तरह से ठोकर खाता है, ऐसा करने का एक सरल तरीका सिर्फ चेकबॉक्स पर टैग का उपयोग करना है और फिर उस टैग को उसके श्रोता (कोड कोटलीन में है) पर जांचना है:

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

तब जब आप मूल्य को अनदेखा करना चाहते हैं तो एक्सेस करने से पहले टैग को सही पर सेट करें

checkBox.tag = true
checkBox.isChecked = true

आप वैकल्पिक सेटटैग पद्धति का उपयोग करके टैग को एक कुंजी पर मैप कर सकते हैं, जिसे समझने के लिए यदि आप चिंतित थे, तो एक कुंजी की आवश्यकता होती है। लेकिन अगर यह सब एक ही वर्ग के लिए होता है तो कुछ कमेंट स्ट्रिंग्स, व्हाट्सएप को समझने के लिए पर्याप्त होंगे।


4

आप अपने चेकबॉक्स के रूप में इस SafeCheckBox वर्ग का उपयोग कर सकते हैं:

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);
    }
}
  • तब आप कॉल कर सकते हैं: -

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


3

चेक रेडियो बटन से पहले चेंजलिस्ट को नल सेट करें। चेक रेडियो बटन के बाद आप श्रोता को फिर से सेट कर सकते हैं।

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

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

   }
});

1
क्या काम करता है और यह अन्य समाधानों की तुलना में यहां तेज और सरल है।
PayToPwn

3

मेरी व्याख्या जो मुझे लगता है कि सबसे आसान
हो सकता है सहायक हो)

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

इसका इस्तेमाल करें

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

उपयोग ट्रिगर हो जाएगा setChecked(boolean) फ़ंक्शन
जो सभी है

KOTLIN

class MyCheckBox @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = R.attr.switchStyle
) : AppCompatCheckBox(context, attrs, defStyleAttr) {

    var programmatically = false

    override fun setChecked(checked: Boolean) {
        programmatically = false
        super.setChecked(checked)
    }

    fun setCheckedProgrammatically(checked: Boolean) {
        programmatically = true
        super.setChecked(checked)
    }
}

2

यह एक सरल समाधान है जिसका मैंने उपयोग किया:
एक कस्टम श्रोता को परिभाषित करें:

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

प्रारंभ:

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

उपयोग:

checkBoxListener.disable();

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

checkBoxListener.enable();

2

इस बारे में कैसा है। देखें में टैग का उपयोग करने का प्रयास करें

mCheck.setTag("ignore");
mCheck.setChecked(true);
mCheck.setTag(null);

तथा

switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean selected) {

            //If switch has a tag, ignore below
            if(compoundButton.getTag() != null)
                return; 

            if (selected) {
                // do something
            } else {
                // do something else
            }

        }
    });

2

ReentrantLockजब भी मैं सेटिंग कर रहा हूं, मैंने उसका उपयोग किया , और उसे लॉक किया isChecked:

// lock when isChecked is being set programmatically
val isBeingProgrammaticallySet = ReentrantLock()

// set isChecked programmatically
isBeingProgrammaticallySet.withLock()
{
    checkbox.isChecked = true
}

// do something only when preference is modified by user
checkbox.setOnCheckedChangeListener()
{
    _,isChecked ->
    if (isBeingProgrammaticallySet.isHeldByCurrentThread.not())
    {
        // do it
    }
}

1

मुझे उपरोक्त सभी उत्तर रास्ते बहुत जटिल लगे। सिर्फ एक साधारण बूलियन के साथ अपना झंडा क्यों नहीं बनाया?

बस बूलियन के साथ एक सरल ध्वज प्रणाली का उपयोग करें। बनाएँ boolean noListener। जब भी आप किसी भी कोड को चलाए बिना अपना स्विच ऑन / ऑफ करना चाहते हैं (इस उदाहरण में, जैसा कि दर्शाया गया है runListenerCode(), बस noListener=trueकॉल करने से पहले सेट करेंswitch.setChecked(false/true)

switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
           @Override
           public void onCheckedChanged(CompoundButton compoundButton, boolean selected) {
               if (!noListener) { //If we want to run our code like usual
                   runListenerCode();
               } else { //If we simply want the switch to turn off
                   noListener = false;
               }
           });

सरल झंडे का उपयोग करते हुए बहुत सरल समाधान। अंत में, हम noListener=falseएक बार फिर सेट करते हैं ताकि हमारा कोड काम करना जारी रखे। उम्मीद है की यह मदद करेगा!


1

यह एक आप के लिए काम करना चाहिए कोशिश करो! आप इसे फायरबेस के साथ भी उपयोग कर सकते हैं!

फायरबेस डाटा पाने के लिए! इसे इस्तेमाल करो!

databaseReference.child(user.getPhoneNumber()).child("Reqs").addValueEventListener(new ValueEventListener() {

        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            SharedPreferences prefs = mContext.getSharedPreferences("uinfo", MODE_PRIVATE);
            String pno = prefs.getString("username", "No name defined");

            if(dataSnapshot.child(pno).getValue(String.class).equals("acc")){
                holder.acc.setChecked(true);
            }else{
                holder.acc.setChecked(false);
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            // Getting Post failed, log a message
            Log.w("dfs", "loadPost:onCancelled", databaseError.toException());
            // ...
        }
    });

उसके बाद जब यूजर कुछ करेगा!

holder.acc.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if(isChecked) {
                    if(buttonView.isPressed()) {
                        //your code
                    }
                }
                else {
                    if(buttonView.isPressed()) {
                       //your code
                    }
                }
            }
        });

1

मैं वास्तव में श्रोता को पारित करने के लिए नहीं होना चाहता था, हर बार जब हम सेट चेक करते हैं, और न ही उपयोग करते हुए enabled यह निर्धारित करने के तरीके के रूप में रहे हैं कि क्या हमें मूल्य सेट करना चाहिए (उस स्थिति में क्या होता है जब हमारे पास मूल्य सेट करते समय स्विच पहले से ही अक्षम है ?)

इसके बजाय मैं एक आईडी और आपके द्वारा कॉल की जा सकने वाली एक्सटेंशन विधियों के साथ टैग का उपयोग कर रहा हूं:

fun CompoundButton.setOnCheckedWithoutCallingChangeListener(
    listener: (view: CompoundButton, checked: Boolean) -> Unit
) {
    setOnCheckedChangeListener { view, checked ->
        if (view.getTag(R.id.compound_button_checked_changed_listener_disabled) != true) {
            listener(view, checked)
        }
    }
    this.setTag(R.id.compound_button_enabled_checked_change_supported, true)
}

fun CompoundButton.setCheckedWithoutCallingListener(checked: Boolean) {
    check(this.getTag(R.id.compound_button_enabled_checked_change_supported) == true) {
        "Must set listener using `setOnCheckedWithoutCallingChangeListener` to call this method" 
    }

    setTag(R.id.compound_button_checked_changed_listener_disabled, true)
    isChecked = checked
    setTag(R.id.compound_button_checked_changed_listener_disabled, false)
}

अब आप कॉल कर सकते हैं setCheckedWithoutCallingListener(bool)और यह सही श्रोता उपयोग को लागू करेगा।

setChecked(bool)यदि आपको अभी भी ज़रूरत है तो आप श्रोता को आग लगाने के लिए कॉल कर सकते हैं


0

मुझे लगता है कि प्रतिबिंब का उपयोग करना एकमात्र तरीका है। कुछ इस तरह:

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

देव कार्य को तब तक बदल सकते हैं जब तक कि क्षेत्र का नाम या उदाहरण के लिए, पदानुक्रम में ".Checked" पद्धति को न बदल दें ... या कोई अन्य if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN){ /* do reflection */}
पुन

एपीआई को तोड़ने और इंटर्नल में खुदाई करने के लिए प्रोत्साहित करना एक गलत विचार है। कार्यान्वयन में किसी भी परिवर्तन के कारण एप्लिकेशन विफल हो जाएंगे।
mspanc

0

@ समाधान पर आधारित जावा में लिखा गया मेरा समाधान:

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 चेकबॉक्स और हमेशा एक चेक किया जाएगा (हालांकि शुरू में चेक किया जाना चाहिए)। टैग को सच्चे ब्लॉक पर सेट करना


0
public void setCheckedChangeListenerSwitch() {

    switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean selected) {

            if (selected) {
                // do something
            } else {
                // do something else
            }

        }
    });

}

// Update state & reset listener (so onCheckedNot called)
public void updateSwitchState(boolean state){

    switch.setOnCheckedChangeListener(null);
    switch.setChecked(state);
    setCheckedChangeListenerSwitch();

}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.