Как узнать, изменил ли пользователь состояние кнопки переключения?

У меня есть десять кнопок-переключателей. Я хочу сохранить состояние пяти из этих кнопок при нажатии кнопки «Домой». Но я хочу сохранить его только в том случае, если пользователь внес изменения в состояние любой из кнопок. Есть ли способ узнать изменение состояний без использования setOnClickListener()?


person nila    schedule 25.08.2011    source источник


Ответы (8)


Я сделал следующее, это не очень красиво, но работает:

ttsButton = (ToggleButton) findViewById(R.id.solution_ttsbutton);
ttsButton.setOnCheckedChangeListener(toggleButtonChangeListener);
...
// gets called, if the button state changes
final CompoundButton.OnCheckedChangeListener toggleButtonChangeListener = new CompoundButton.OnCheckedChangeListener() {
    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        // The user changed the button, do something
    }
};

и я делаю следующее, если я хочу изменить кнопку программно, не выполняя прослушиватель изменений:

ttsButton.setOnCheckedChangeListener(null);
ttsButton.setChecked(false);
ttsButton.setOnCheckedChangeListener(toggleButtonChangeListener);
person Community    schedule 03.01.2013
comment
Более понятный пример и описание здесь: developer.android.com/guide/topics/ интерфейс/управление/ - person ban-geoengineering; 22.02.2016

Существует простой способ узнать, нажимает ли пользователь CompoundButton (CheckBox, Switch, RadioButton, ToggleButton), используйте следующее:

 new CompoundButton.OnCheckedChangeListener() {
        public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
            if (compoundButton.isPressed()) {
                // do something related to user click/tap
            } else {
                // do something related to programmatically state changes (checked/unchecked)
            }
        }
    }
person ultraon    schedule 10.01.2017
comment
Это должен быть принятый ответ, если кто-то не сможет доказать, что .isPressed() не переключается на другие устройства ввода, такие как стилус (но я в этом сомневаюсь) - person Daniel F; 20.02.2017
comment
Этот ответ правильный! Я проверил несколько тестовых случаев, и это сработало! - person MD. Shafiul Alam Biplob; 05.01.2020

Используйте CompoundButton.OnCheckedChangeListener класс.

ToggleButton button = /* ... */;
button.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        // Save the state here
    }
});

EDIT: если вы хотите использовать один прослушиватель:

CompoundButton.OnCheckedChangeListener listener =
        new CompoundButton.OnCheckedChangeListener() {
    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        String key = null;
        switch(buttonView.getId()) {
            case R.id.button1:
                key = "key1";
                break;
            case R.id.button2:
                key = "key2";
                break;
            default:
                return;
        }
        // Save the state here using key
    }
});

ToggleButton button1 = /* ... */;    
button1.setOnCheckedChangeListener(listener);

ToggleButton button2 = /* ... */;
button2.setOnCheckedChangeListener(listener);

Но есть много способов реализовать это на самом деле. Таким образом, вы можете придумать другой метод, который лучше подходит для ваших нужд, чем этот.

person Michael    schedule 25.08.2011
comment
Как я могу использовать один список для всех кнопок переключения? - person nila; 25.08.2011
comment
Как я вижу, это не отвечает на вопрос. Более точная формулировка была бы такой: как отличить button.setChecked(); и клик пользователя? onCheckedChanged вызывается в обоих случаях. - person sydd; 04.01.2013
comment
И, как я вижу из вопроса, автор не заинтересован в разграничении действия пользователя и вызова метода, а просто хочет знать, когда меняются состояния кнопок. - person Michael; 04.01.2013
comment
Я получаю другой id от проверенной кнопки!, .getId() не возвращает ожидаемый id! - person Francisco Corrales Morales; 25.11.2014

Использовать настраиваемое представление

import android.content.Context;
import android.util.AttributeSet;
import android.widget.Switch;

public class CustomSwitch extends Switch {


    private OnCheckedChangeListener mListener;

    public CustomSwitch(Context context) {
        super(context);
    }

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

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

    public CustomSwitch(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
        // Do not call supper method
        mListener = listener;
    }

    @Override
    public void setChecked(boolean checked) {
        super.setChecked(checked);

        if (mListener != null) {
            mListener.onCheckedChanged(this, checked);
        }
    }

    public void setCheckedProgrammatically(boolean checked) {
        // You can call super method, it doesn't have a listener... he he :)
        super.setChecked(checked);
    }

}

Пример использования XML

<com.your.package.CustomSwitch
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

Теперь идея состоит в том, чтобы вызвать метод setCheckedProgrammatically в коде. setChecked вызывается Android, когда пользователи изменяют состояние кнопки соединения.

Обратите внимание, что я использую переключатель, который расширяет кнопку соединения, вы можете использовать в основном тот же код для любого другого (флажок, ...)

person Bojan Kseneman    schedule 15.04.2015

Для котлина используйте это расширение:


fun CompoundButton.setOnUserCheckedChangeListener(callback: (isChecked: Boolean) -> Unit) {
    setOnCheckedChangeListener { buttonView, isChecked ->
        if (buttonView.isPressed) {
            callback.invoke(isChecked)
        }
    }
}
person Morteza Rastgoo    schedule 12.09.2020

Сначала проверьте эту ссылку http://developer.android.com/resources/tutorials/views/hello-formstuff.html#ToggleButton

Простой onChangeListener сделает:

         public class TestProjectActivity extends Activity {

      ToggleButton one; 
     ToggleButton two;
    ToggleButton three;
     ToggleButton four;

    /** Called when the activity is first created. */
      @Override
      public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
        setContentView(R.layout.main);


one = (ToggleButton) findViewById(R.id.toggleButton1);
two = (ToggleButton) findViewById(R.id.toggleButton2);
three = (ToggleButton) findViewById(R.id.toggleButton3);
four = (ToggleButton) findViewById(R.id.toggleButton4);

one.setOnCheckedChangeListener(changeChecker);
two.setOnCheckedChangeListener(changeChecker);
three.setOnCheckedChangeListener(changeChecker);
four.setOnCheckedChangeListener(changeChecker);
      }

      OnCheckedChangeListener changeChecker = new OnCheckedChangeListener() {

@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    if (isChecked){
        if (buttonView == one) {
            two.setChecked(false);
            three.setChecked(false);
            four.setChecked(false);
        }
        if (buttonView == two) {
            one.setChecked(false);
            three.setChecked(false);
            four.setChecked(false);
        }
        if (buttonView == three) {
            two.setChecked(false);
            one.setChecked(false);
            four.setChecked(false);
        }
        if (buttonView == four) {
            two.setChecked(false);
            three.setChecked(false);
            one.setChecked(false);
        }
    }
}
};

}
person Randroid    schedule 25.08.2011

Используйте View.OnTouchListener для прослушивания и обнаружения взаимодействия с пользователем. Я реализовал это в своем классе адаптера.

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<ViewHolder>
implements AccountUtils.OnAccountStateChange ,View.OnTouchListener{

// variable to store whether screen id pressed or not
public static boolean pressed=false;


//If User touches the screen 
//MotionEvent.ACTION_DOWN is triggred
//and when user lifts his hand (takes away from screen)
//MotionEvent.ACTION_UP is triggred
// Here you should the change the value of pressed accordingly
@Override
public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()){
        case MotionEvent.ACTION_DOWN:
        pressed = true;// Screen Touched
        break;
        case MotionEvent.ACTION_UP:
        pressed = false;// Screen 
        break;
    }
    return false;
}

static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    final SwitchCompat btnToggle;

    public ViewHolder(final View itemView) {
        super(itemView);

        btnToggle = (SwitchCompat) itemView.findViewById(R.id.btn_toggle);
        btnToggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                // IF the value in Var pressed is true 
                // only then trigger this event
                if (pressed) {

                    // YOUR METHOD GOES HERE
                    Toast.makeText(context, "Checked Changed",   Toast.LENGTH_SHORT).show();

                }
            }
        });

    }

}

}

person harsh_v    schedule 26.11.2015

Я бы рекомендовал это решение: https://stackoverflow.com/a/9130007/2708288

Вкратце, используйте «boolean CheckBox#isShown()», чтобы определить, в каком случае он возвращает false, даже если вы изменяете состояние проверки в onStart() или onResume() действия. (Я не тестировал сценарий Fragment.)

person Alan Zhiliang Feng    schedule 17.07.2016