ฉันsetOnCheckedChangeListener
ใช้งานไปแล้วcheckbox
มีวิธีที่ฉันสามารถโทร
checkbox.setChecked(false);
โดยไม่ต้องเรียก onCheckedChanged
ฉันsetOnCheckedChangeListener
ใช้งานไปแล้วcheckbox
มีวิธีที่ฉันสามารถโทร
checkbox.setChecked(false);
โดยไม่ต้องเรียก onCheckedChanged
คำตอบ:
ไม่คุณไม่สามารถทำได้ วิธีการที่เรียกว่าโดยตรงจาก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;
}
}
mListener
อย่างไร Checkbox
ไม่มีทะเยอทะยานสำหรับมันOnCheckChangeListener
mListener
เป็นการใช้งานOnCheckChangedListener
ส่วนต่อประสานซึ่งถูกสร้างขึ้นโดยโปรแกรมเมอร์ คำตอบของฉันหมายความว่าโปรแกรมการบำรุงรักษาการอ้างอิงถึงการดำเนินงานของตัวเองmListener
-
CheckBox
วัตถุเท่านั้น ฉันจะไม่บอกว่ามันไม่มีประสิทธิภาพ
เพิ่มรหัสนี้ภายใน OnCheckedChangeListener:
if(!compoundButton.isPressed()) {
return;
}
สิ่งนี้จะช่วยให้เราทราบว่าสถานะช่องทำเครื่องหมายสภาพอากาศเปลี่ยนแปลงไปโดยทางโปรแกรมหรือจากการกระทำของผู้ใช้
วิธีที่เป็นไปได้อีกวิธีหนึ่งในการบรรลุเป้าหมายนี้คือการใช้กล่องกาเครื่องหมายที่กำหนดเองซึ่งจะช่วยให้คุณเลือกหากคุณต้องการให้ผู้ฟังเรียกหรือไม่:
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();
}
}
รุ่น Kotlin หากคุณต้องการ:
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);
ใช้ส่วนขยายของ Kotlin กับคำตอบ @Shade:
fun CompoundButton.setCustomChecked(value: Boolean,listener: CompoundButton.OnCheckedChangeListener) {
setOnCheckedChangeListener(null)
isChecked = value
setOnCheckedChangeListener(listener)
}
สำหรับทุกคนที่สะดุดสิ่งนี้วิธีที่ง่ายกว่าวิธีหนึ่งคือการใช้แท็กในช่องทำเครื่องหมายจากนั้นตรวจสอบแท็กนั้นบนผู้ฟัง (รหัสคือ Kotlin):
checkBox.tag = false
checkBox.setOnCheckedChangeListener{ buttonView, isChecked ->
if(checkBox.tag != true) {
//Do some stuff
} else {
checkBox.tag = false
}
จากนั้นเมื่อเข้าถึงเพียงตั้งค่าแท็กเป็นจริงก่อนที่คุณจะตั้งค่า isChecked เป็นจริงเมื่อคุณต้องการละเว้นการเปลี่ยนแปลงค่า:
checkBox.tag = true
checkBox.isChecked = true
คุณสามารถแมปแท็กกับคีย์โดยใช้เมธอด setTag ทางเลือกที่ต้องใช้คีย์หากคุณกังวลเกี่ยวกับความสามารถในการทำความเข้าใจ แต่ถ้ามันมีอยู่ในคลาสเดียวสตริงความคิดเห็นไม่กี่จะเกินพอที่จะอธิบายสิ่งที่เกิดขึ้น
คุณสามารถใช้คลาส 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
ตั้งค่าเป็น null เพื่อเปลี่ยนฟังก่อนตรวจสอบปุ่มตัวเลือก คุณสามารถตั้งค่าผู้ฟังอีกครั้งหลังจากตรวจสอบปุ่มตัวเลือก
radioGroup.setOnCheckedChangeListener(null);
radioGroup.check(R.id.radioButton);
radioGroup.setOnCheckedChangeListener(new
RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, @IdRes int i) {
}
});
การตีความของฉันซึ่งฉันคิดว่าเป็นวิธีที่ง่ายที่สุด
อาจเป็นประโยชน์)
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)
}
}
นี่เป็นวิธีง่ายๆที่ฉันใช้:
กำหนดฟังแบบกำหนดเอง:
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();
เกี่ยวกับเรื่องนี้ ลองใช้แท็กในมุมมอง
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
}
}
});
ฉันใช้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
}
}
ฉันพบคำตอบทั้งหมดข้างต้นวิธีที่ซับซ้อนเกินไป ทำไมไม่เพียงแค่สร้างธงของคุณเองด้วยบูลีนที่เรียบง่าย?
เพียงใช้ระบบการตั้งค่าสถานะแบบง่าย ๆ ด้วยบูลีน 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
อีกครั้งเพื่อให้รหัสของเรายังคงทำงาน หวังว่านี่จะช่วยได้!
ลองอันนี้น่าจะเหมาะกับคุณ! คุณสามารถใช้กับ firebase ได้ด้วย!
รับข้อมูล firebase! ใช้สิ่งนี้!
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
}
}
}
});
ฉันไม่ต้องการที่จะต้องส่งผู้ฟังในแต่ละครั้งที่เราตั้งค่าการตรวจสอบการเปลี่ยนแปลงหรือการใช้ enabled
เป็นวิธีการพิจารณาว่าเราควรตั้งค่าหรือไม่ (เกิดอะไรขึ้นในกรณีที่เราปิดสวิตช์ไว้เมื่อตั้งค่า ?)
แต่ฉันใช้ประโยชน์จากแท็กที่มี ID และวิธีการขยายสองสามอย่างที่คุณสามารถโทรได้
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)
ผู้ฟังหากคุณต้องการ
ฉันเดาว่าการใช้การสะท้อนนั้นเป็นวิธีเดียว บางสิ่งเช่นนี้
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();
}
if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN){ /* do reflection */}
โซลูชันของฉันเขียนด้วยภาษาจาวาตามคำตอบ @Chris:
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 ช่องทำเครื่องหมายและจะมีการตรวจสอบหนึ่งช่องเสมอ (จะต้องตรวจสอบตั้งแต่แรก) การตั้งค่าแท็กเป็นบล็อกจริงบนฟังตรวจสอบการเปลี่ยนแปลง
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();
}