android.widget.Switch - включить / выключить прослушиватель событий?
Я хотел бы реализовать кнопку переключения, android.widget.Switch (доступно из API v.14).
<Switch
android:id="@+id/switch1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Switch" />
Но я не уверен, как добавить прослушиватель событий для кнопки. Должен ли он быть слушателем "onClick"? И как бы я узнал, включен он или нет?
5 ответов
Переключатель наследует CompoundButton
атрибуты, поэтому я бы порекомендовал OnCheckedChangeListener
mySwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// do something, the isChecked will be
// true if the switch is in the On position
}
});
Используйте следующий фрагмент, чтобы добавить Switch к вашему макету через XML:
<Switch
android:id="@+id/on_off_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textOff="OFF"
android:textOn="ON"/>
Затем в методе Activity вашего onCreate получите ссылку на ваш Switch и установите его OnCheckedChangeListener:
Switch onOffSwitch = (Switch) findViewById(R.id.on_off_switch);
onOffSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Log.v("Switch State=", ""+isChecked);
}
});
Для тех, кто использует Kotlin, вы можете установить слушателя для коммутатора (в этом случае, имея идентификатор mySwitch
) следующее:
mySwitch.setOnCheckedChangeListener { _, isChecked -> run {
// do whatever you need to do when the switch is toggled here
}
}
isChecked
Значение true, если в данный момент переключатель включен (ON), и false в противном случае.
Определите ваш XML-макет:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.neoecosystem.samplex.SwitchActivity">
<Switch
android:id="@+id/myswitch"
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
</RelativeLayout>
Затем создайте активность
public class SwitchActivity extends ActionBarActivity implements CompoundButton.OnCheckedChangeListener {
Switch mySwitch = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_switch);
mySwitch = (Switch) findViewById(R.id.myswitch);
mySwitch.setOnCheckedChangeListener(this);
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
// do something when check is selected
} else {
//do something when unchecked
}
}
****
}
======== Для API ниже 14 используйте SwitchCompat =========
XML
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.neoecosystem.samplex.SwitchActivity">
<android.support.v7.widget.SwitchCompat
android:id="@+id/myswitch"
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
</RelativeLayout>
Деятельность
public class SwitchActivity extends ActionBarActivity implements CompoundButton.OnCheckedChangeListener {
SwitchCompat mySwitch = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_switch);
mySwitch = (SwitchCompat) findViewById(R.id.myswitch);
mySwitch.setOnCheckedChangeListener(this);
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
// do something when checked is selected
} else {
//do something when unchecked
}
}
*****
}
В Котлине:
switch_button.setOnCheckedChangeListener { buttonView, isChecked ->
if (isChecked) {
// The switch enabled
text_view.text = "Switch on"
} else {
// The switch disabled
text_view.text = "Switch off"
}
}
Раскладка для виджета Switch выглядит примерно так.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Switch
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="20dp"
android:gravity="right"
android:text="All"
android:textStyle="bold"
android:textColor="@color/black"
android:textSize="20dp"
android:id="@+id/list_toggle" />
</LinearLayout>
В классе Activity вы можете кодировать двумя способами. Зависит от использования вы можете кодировать.
Первый путь
public class ActivityClass extends Activity implements CompoundButton.OnCheckedChangeListener {
Switch list_toggle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.return_vehicle);
list_toggle=(Switch)findViewById(R.id.list_toggle);
list_toggle.setOnCheckedChangeListener(this);
}
}
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
if(isChecked) {
list_toggle.setText("Only Today's"); //To change the text near to switch
Log.d("You are :", "Checked");
}
else {
list_toggle.setText("All List"); //To change the text near to switch
Log.d("You are :", " Not Checked");
}
}
Второй способ
public class ActivityClass extends Activity {
Switch list_toggle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.return_vehicle);
list_toggle=(Switch)findViewById(R.id.list_toggle);
list_toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked) {
list_toggle.setText("Only Today's"); //To change the text near to switch
Log.d("You are :", "Checked");
}
else {
list_toggle.setText("All List"); //To change the text near to switch
Log.d("You are :", " Not Checked");
}
}
});
}
}
Сентябрь 2020 - Программный ответ
Вы можете сделать это программно для Switch Widget и Material Design:
Switch yourSwitchButton = findViewById(R.id.switch_id);
yourSwitchButton.setChecked(true); // true is open, false is close.
yourSwitchButton.setOnCheckedChangeListener((compoundButton, b) -> {
if (b){
//open job.
}
else {
//close job.
}
});
@canerkaseler
Вы можете использовать DataBinding и ViewModel для события Switch Checked Change
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.example.ui.ViewModel" />
</data>
<Switch
android:id="@+id/on_off_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onCheckedChanged="@{(button, on) -> viewModel.onCheckedChange(on)}"
/>
Мое решение, используя SwitchCompat
и Котлин. В моей ситуации мне нужно было реагировать на изменение только в том случае, если пользователь запускал его через пользовательский интерфейс. Фактически, мой переключатель реагирует наLiveData
, и это сделало оба setOnClickListener
а также setOnCheckedChangeListener
непригодный для использования. setOnClickListener
на самом деле правильно реагирует на взаимодействие с пользователем, но не срабатывает, если пользователь перемещает большой палец через переключатель. setOnCheckedChangeListener
на другом конце срабатывает также, если переключатель переключается программно (например, наблюдателем). Теперь в моем случае переключатель присутствовал на двух фрагментах, и поэтому onRestoreInstanceState в некоторых случаях запускал переключатель со старым значением, перезаписывающим правильное значение.
Итак, я посмотрел на код SwitchCompat и смог успешно имитировать его поведение, различая щелчок и перетаскивание, и использовал это для создания настраиваемого сенсорного прослушивателя, который работает так, как должен. Вот так:
/**
* This function calls the lambda function passed with the right value of isChecked
* when the switch is tapped with single click isChecked is relative to the current position so we pass !isChecked
* when the switch is dragged instead, the position of the thumb centre where the user leaves the
* thumb is compared to the middle of the switch, and we assume that left means false, right means true
* (there is no rtl or vertical switch management)
* The behaviour is extrapolated from the SwitchCompat source code
*/
class SwitchCompatTouchListener(private val v: SwitchCompat, private val lambda: (Boolean)->Unit) : View.OnTouchListener {
companion object {
private const val TOUCH_MODE_IDLE = 0
private const val TOUCH_MODE_DOWN = 1
private const val TOUCH_MODE_DRAGGING = 2
}
private val vc = ViewConfiguration.get(v.context)
private val mScaledTouchSlop = vc.scaledTouchSlop
private var mTouchMode = 0
private var mTouchX = 0f
private var mTouchY = 0f
/**
* @return true if (x, y) is within the target area of the switch thumb
* x,y and rect are in view coordinates, 0,0 is top left of the view
*/
private fun hitThumb(x: Float, y: Float): Boolean {
val rect = v.thumbDrawable.bounds
return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom
}
override fun onTouch(view: View, event: MotionEvent): Boolean {
if (view == v) {
when (MotionEventCompat.getActionMasked(event)) {
MotionEvent.ACTION_DOWN -> {
val x = event.x
val y = event.y
if (v.isEnabled && hitThumb(x, y)) {
mTouchMode = TOUCH_MODE_DOWN;
mTouchX = x;
mTouchY = y;
}
}
MotionEvent.ACTION_MOVE -> {
val x = event.x
val y = event.y
if (mTouchMode == TOUCH_MODE_DOWN &&
(abs(x - mTouchX) > mScaledTouchSlop || abs(y - mTouchY) > mScaledTouchSlop)
)
mTouchMode = TOUCH_MODE_DRAGGING;
}
MotionEvent.ACTION_UP,
MotionEvent.ACTION_CANCEL -> {
if (mTouchMode == TOUCH_MODE_DRAGGING) {
val r = v.thumbDrawable.bounds
if (r.left + r.right < v.width) lambda(false)
else lambda(true)
} else lambda(!v.isChecked)
mTouchMode = TOUCH_MODE_IDLE;
}
}
}
return v.onTouchEvent(event)
}
}
Как это использовать:
фактический слушатель касания, который принимает лямбду с кодом для выполнения:
myswitch.setOnTouchListener(
SwitchCompatTouchListener(myswitch) {
// here goes all the code for your callback, in my case
// i called a service which, when successful, in turn would
// update my liveData
viewModel.sendCommandToMyService(it)
}
)
Для полноты картины так обозреватель состояния switchstate
(если он у вас есть) выглядел так:
switchstate.observe(this, Observer {
myswitch.isChecked = it
})
Есть два пути,
используя xml onclick view Добавить переключатель в XML, как показано ниже:
<Switch android:id="@+id/switch1" android:onClick="toggle"/>
В классе YourActivity (например, MainActivity.java)
Switch toggle; //outside oncreate
toggle =(Switch) findViewById(R.id.switch1); // inside oncreate
public void toggle(View view) //outside oncreate
{
if( toggle.isChecked() ){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
start.setBackgroundColor(getColor(R.color.gold));
stop.setBackgroundColor(getColor(R.color.white));
}
}
else
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
stop.setBackgroundColor(getColor(R.color.gold));
start.setBackgroundColor(getColor(R.color.white));
}
}
}
- использование прослушивателя кликов
Добавьте переключатель в XML, как показано ниже:
В классе YourActivity (например, MainActivity.java)
Switch toggle; // outside oncreate
toggle =(Switch) findViewById(R.id.switch1); // inside oncreate
toggle.setOnClickListener(new View.OnClickListener() { // inside oncreate
@Override
public void onClick(View view) {
if( toggle.isChecked() ){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
start.setBackgroundColor(getColor(R.color.gold));
}
}
else
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
stop.setBackgroundColor(getColor(R.color.gold));
}
}
}
});
В классе Activity
switch.setOnCheckedChangeListener((CompoundButton.OnCheckedChangeListener) (buttonView, isChecked) -> {
if (isChecked){
// your code
} else {
// your code
}
});
макет для виджета Switch
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:checked="true"
android:layoutDirection="ltr"/>