onCheckedChanged викликається автоматично


76

У мене є перемикач у перегляді переглядача, і дані відображаються в перегляді переглядача після отримання даних з БД. Коли відкривається перегляд recicler, я читаю БД, і якщо поле в БД має значення "Y", я вмикаю перемикач, інакше я вимикаю перемикач. Тепер проблема полягає в тому, що також викликається слухач onCheckedchanged, я хочу, щоб onCheckedChanged викликався лише тоді, коли користувач встановлює комутатор вручну.

При відкритті переглядача виконується подане нижче:

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

Клас ViewHolder:

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

Метод OnConCedChanged, який викликається при відкритті програми reciclerView:

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

У файлі макета:

<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"/>

Відповіді:


255

Це дивно, що у всіх нас є ця проблема, але не офіційна відповідь Google на цю просту проблему.

НАЙНОВІШЕ - це перевірити:

buttonView.isPressed()

Якщо true, це означає, що користувач натиснув подання.

Не потрібні глобальні змінні.

Сподіваюся, це допомагає.


4
Це точно працює. Але чи є якась подія, якщо користувач пересуває перемикач? У цьому випадку, якщо використовується рухомий перемикач, це не працює.
dhun

Дякуємо за це просте, але чудове рішення. Це можна використовувати RadioButtonтакож. Бо RadioGroupя написав цю відповідь .
Суфіян

Дякую @Surfian за згадку :), я радий, що це працює і для RadioButton
Sulfkain

16
рішення не спрацює, якщо дуже швидко прокрутити перемикач. Дурний Google
DàChún

Ви можете обробляти вручну, реалізуючи OnClickListener і перевіряючи метод isChecked () SwitchCompat, не вимагаючи використання onCheckedChangeListener.
mr.boyfox

13

Я використав цей підклас SwitchCompat, щоб уникнути цієї проблеми. Таким чином, мені не потрібен шаблонний код там, де я використовую цей клас. Всякий раз, коли вам потрібно змінити перевірене, не запускаючи слухача, використовуйте setCheckedSilentзамість 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);
    }
}

onRestoreInstanceStateтакож ініціював прослуховування, коли встановлено в onViewCreatedметоді, і ви повертаєтесь до попереднього фрагмента. Сподіваюся, це працює для вас!


11

Спробуйте це

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

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

1
Це не працює, якщо проведіть пальцем дуже швидко.
Мануель

2

Це працює для мене:

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

Це не працює, якщо проведіть пальцем дуже швидко.
Мануель

0

використовувати глобальну булеву змінну і при зчитуванні даних з БД встановити її "true", а після перевірки (якщо) у onCheckChange встановити "false" знову. у першому методі onCheckChange перевірити, чи є ця змінна хибною, виконувати коди, інакше повернути (значення цієї змінної за замовчуванням має бути хибним);

@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

Здається, це обхід. Я шукав функціональність в android, яка дзвонить перевіренозмінено лише при натисканні користувачем (тобто фокус отримується). Але це працює. Голосуйте за мене.
Psypher

@Ranjith: при першому виклику методу Switch натискається метод toggle (), а в методі toggle - set selected (). тому вам слід вставити вищевказані коди в метод перемикання, а не при проведенні зміни. до речі, якщо ви хочете просто написати в onCheckChange (), вам слід написати метод, який лише змінює стан графічного інтерфейсу комутатора і викликає його при читанні даних з БД.
mk72

0

Я зіткнувся з тією ж проблемою на екрані ViewPager щодо фрагментів. Коли ми перемикаємося між фрагментами, слухач onCheckedChanged викликається знову і знову.

Якщо хтось все ще шукає цю проблему, спробуйте.

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

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.