Tôi đã setOnCheckedChangeListener
thực hiện chocheckbox
Có cách nào tôi có thể gọi
checkbox.setChecked(false);
mà không kích hoạt onCheckedChanged
Tôi đã setOnCheckedChangeListener
thực hiện chocheckbox
Có cách nào tôi có thể gọi
checkbox.setChecked(false);
mà không kích hoạt onCheckedChanged
Câu trả lời:
Không, bạn không thể làm điều đó. Các onCheckedChanged
phương pháp được gọi là trực tiếp từ setChecked
. Những gì bạn có thể làm là như sau:
mCheck.setOnCheckedChangeListener (null);
mCheck.setChecked (false);
mCheck.setOnCheckedChangeListener (mListener);
Xem nguồn của CheckBox và cách triển khai 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
không có một getter cho nóOnCheckChangeListener
mListener
là một triển khai của OnCheckChangedListener
giao diện, được tạo ra bởi các lập trình viên. Câu trả lời của tôi ngụ ý rằng lập trình viên duy trì một tham chiếu đến việc thực hiện của riêng họ - mListener
.
CheckBox
đối tượng. Tôi sẽ không nói rằng đó là không hiệu quả.
Thêm mã này vào OnCheckedChangeListener:
if(!compoundButton.isPressed()) {
return;
}
Điều này sẽ giúp chúng tôi tìm ra trạng thái kiểm tra thời tiết đã được thay đổi theo chương trình hoặc do hành động của người dùng.
Một cách khác có thể để đạt được điều này là bằng cách sử dụng một CheckBox tùy chỉnh, nó sẽ cho phép bạn chọn nếu bạn muốn người nghe được gọi hay không:
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();
}
}
Phiên bản Kotlin, nếu bạn thích:
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()
}
}
sử dụng mẫu:
checkBox.setChecked(true,false);
bạn sử dụng đơn giản là setonclickListener, nó sẽ hoạt động tốt và đây là phương pháp rất đơn giản, cảm ơn :)
Sử dụng các tiện ích mở rộng của Kotlin với câu trả lời @Shade:
fun CompoundButton.setCustomChecked(value: Boolean,listener: CompoundButton.OnCheckedChangeListener) {
setOnCheckedChangeListener(null)
isChecked = value
setOnCheckedChangeListener(listener)
}
Đối với bất kỳ ai tình cờ phát hiện ra điều này, một cách đơn giản hơn để làm điều này là chỉ sử dụng một thẻ trên hộp kiểm và sau đó kiểm tra thẻ đó trên trình nghe của nó (mã nằm trong Kotlin):
checkBox.tag = false
checkBox.setOnCheckedChangeListener{ buttonView, isChecked ->
if(checkBox.tag != true) {
//Do some stuff
} else {
checkBox.tag = false
}
Sau đó, khi truy cập, chỉ cần đặt thẻ thành true trước khi bạn đặt isChecked thành true khi bạn muốn bỏ qua thay đổi giá trị:
checkBox.tag = true
checkBox.isChecked = true
Bạn cũng có thể ánh xạ thẻ tới một khóa bằng cách sử dụng phương thức setTag thay thế yêu cầu khóa nếu bạn lo lắng về tính dễ hiểu. Nhưng nếu tất cả chỉ chứa trong một lớp duy nhất, một vài chuỗi nhận xét sẽ là quá đủ để giải thích những gì đang xảy ra.
Bạn có thể sử dụng lớp SafeCheckBox này làm hộp kiểm của mình:
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);
}
}
Sau đó, bạn có thể gọi: -
setSafeCheck(true,ListenerMode.IGNORE);// OnCheckedChange listener will not be notified
Đặt null thành changeListener trước khi kiểm tra nút radio. Bạn có thể thiết lập lại trình nghe sau khi kiểm tra nút radio.
radioGroup.setOnCheckedChangeListener(null);
radioGroup.check(R.id.radioButton);
radioGroup.setOnCheckedChangeListener(new
RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, @IdRes int i) {
}
});
Giải thích của tôi mà tôi nghĩ là dễ nhất
có thể hữu ích)
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);
}
}
sử dụng nó
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean on) {
if (((ProgrammableSwitchCompat) compoundButton).isCheckedProgrammatically) {
return;
}
//...
((ProgrammableSwitchCompat) compoundButton).setCheckedProgrammatically(true);
//...
((ProgrammableSwitchCompat) compoundButton).setCheckedProgrammatically(false);
//...
}
sử dụng sẽ kích hoạt setChecked(boolean)
chức năng
đó là tất cả
KOTLINE
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)
}
}
Đây là một giải pháp đơn giản tôi đã sử dụng:
Xác định trình nghe tùy chỉnh:
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;
}
}
Khởi tạo:
CompoundButtonListener checkBoxListener = new CompoundButtonListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
if (isEnabled()) {
// Your code goes here
}
}
};
myCheckBox.setOnCheckedChangeListener(checkBoxListener);
Sử dụng:
checkBoxListener.disable();
// Some logic based on which you will modify CheckBox state
// Example: myCheckBox.setChecked(true)
checkBoxListener.enable();
Còn cái này thì sao. Hãy thử sử dụng Thẻ trong Chế độ xem
mCheck.setTag("ignore");
mCheck.setChecked(true);
mCheck.setTag(null);
và
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
}
}
});
Tôi đã sử dụng ReentrantLock
và khóa nó bất cứ khi nào tôi cài đặt 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
}
}
Tôi thấy tất cả các câu trả lời trên quá phức tạp. Tại sao không chỉ tạo cờ của riêng bạn với một boolean đơn giản?
Chỉ cần sử dụng một hệ thống cờ đơn giản với một boolean. Tạo boolean noListener
. Bất cứ khi nào bạn muốn bật / tắt công tắc mà không chạy bất kỳ mã nào (trong ví dụ này, được biểu thị là runListenerCode()
, chỉ cần đặt noListener=true
trước khi gọiswitch.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;
}
});
Giải pháp rất đơn giản sử dụng cờ đơn giản. Cuối cùng, chúng tôi thiết lập noListener=false
một lần nữa để mã của chúng tôi tiếp tục hoạt động. Hi vọng điêu nay co ich!
Hãy thử cái này sẽ làm việc cho bạn! Bạn có thể sử dụng điều này với firebase cũng!
Để có được dữ liệu căn cứ hỏa lực! Dùng cái này!
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());
// ...
}
});
Sau đó khi người dùng làm một cái gì đó!
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
}
}
}
});
Tôi thực sự không muốn phải vượt qua người nghe trong mỗi lần chúng tôi đặt kiểm tra thay đổi, cũng không sử dụng enabled
như một cách xác định liệu chúng tôi có nên đặt giá trị hay không (điều gì xảy ra trong trường hợp chúng tôi đã tắt công tắc khi đặt giá trị ?)
Thay vào đó, tôi đang sử dụng các thẻ có id và một vài phương thức mở rộng mà bạn có thể gọi:
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)
}
Bây giờ bạn có thể gọi setCheckedWithoutCallingListener(bool)
và nó sẽ thực thi việc sử dụng người nghe chính xác.
Bạn vẫn có thể gọi setChecked(bool)
để kích hoạt người nghe nếu bạn vẫn cần nó
Tôi đoán sử dụng sự phản chiếu là cách duy nhất. Một cái gì đó như thế này:
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 */}
Giải pháp của tôi được viết bằng java dựa trên câu trả lời @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 hộp kiểm và luôn luôn sẽ được kiểm tra (một phải được kiểm tra ban đầu). Cài đặt thẻ thành các khối thực sự trên trình ngheCheckedChanged.
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();
}