android.widget.Switch - увімкнення / вимкнення слухача подій?


229

Я хотів би реалізувати кнопку перемикання 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"? І як я можу знати, увімкнено "увімкнено" чи ні?


6
OnClick через XML насправді працює - але лише для "натискань" на кнопку, а не для "слайдів".
m02ph3u5

Відповіді:


492

Switch наслідує 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
    }
});

2
@Johan Не біда. Я не знаю про вас, але я б хотів, щоб вони назвали його OnCheckChangedListener, схожий на OnItemSelectedListener, оскільки On- Noun - Verb -Listener є усталеною конвеєцією іменування.
Сем

2
Але, наприклад, коли ви кладете на фрагмент, ця річ завжди спрацьовує кожного разу, коли ви переглядаєте фрагмент, якщо ви встановите перемикач на Увімкнено.
клатч

1
@Sam Що робити, якщо я хочу змінити перемикач на стан ON або OFF за допомогою методу setChcked () і не хочу виконувати метод onCheckedChanged? Але коли користувач знову натискає на метод перемикання onCheckedChanged виконується ... Чи є спосіб це зробити?
деепак кумар

2
Кнопки є OnCLick, перемикачів немає OnChange! Добре розроблена команда Google!
Василіс

1
@KZoNE Що я тут робив, використовував слухач кліків, щоб змінити стан і передав перемикач на метод (в моєму випадку виклик API), а потім застосував метод setChecked () для зміни стану (наприклад, в onFailure / onError в API виклику) . Сподіваюся, що це допомагає.
деепак кумар

53

Використовуйте такий фрагмент, щоб додати комутатор до вашого макета через XML:

<Switch
     android:id="@+id/on_off_switch"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:textOff="OFF"
     android:textOn="ON"/>

Потім у методі onCreate вашої діяльності знайдіть посилання на свій комутатор та встановіть його 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);
}       

});

3
Це більш чітка відповідь, яка дає вам макет і код, які відповідають.
AshesToAshes

як керувати декількома комутаторами в одному слухачі? Просимо запропонувати відповідь на це
Ананд Савяні

22

Для тих, хто використовує Kotlin, ви можете встановити слухача для комутатора (у цьому випадку з ідентифікатором mySwitch) наступним чином:

    mySwitch.setOnCheckedChangeListener { _, isChecked ->
         // do whatever you need to do when the switch is toggled here
    }

isChecked вірно, якщо перемикач поточно встановлено (УВІМКНЕНО), а помилково - інакше.


19

Визначте свій 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
        }
    }
   *****
}

2
не забудьте перевірити buttonView.isPress ()
JacksOnF1re

5

Макет віджета 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>

У класі діяльності ви можете кодувати двома способами. Залежить від використання, яке ви можете кодувати.

Перший шлях

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

2

Ви можете використовувати 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)}"
     />


1
android.widget.Switch не має функцію onCheckedChanged attirbute. Ви отримаєте помилку: AAPT: error: атрибут android: onCheckedChanged не знайдено.
Продається

1

є два способи,

  1. за допомогою перегляду xml onclick Add Add Switch in 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));
            }
        }
    }
  1. за допомогою слухача кліків

Додати перемикач у 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));
                }
            }

        }

    });

0

Моє рішення, використовуючи a SwitchCompatі Kotlin. У моїй ситуації мені потрібно було реагувати на зміну, лише якщо користувач викликав її через інтерфейс користувача. Насправді мій перемикач реагує на a LiveData, і це зробило setOnClickListenerі setOnCheckedChangeListenerнепридатним. setOnClickListenerнасправді правильно реагує на взаємодію користувачів, але це не спрацьовує, якщо користувач перетягує великий палець через комутатор. setOnCheckedChangeListenerз іншого боку спрацьовує також, якщо перемикач перемикається програмно (наприклад, спостерігачем). Тепер у моєму випадку перемикач був присутній на двох фрагментах, і так ReRerereInstanceState в деяких випадках викликав би перемикач зі старим значенням, що замінює правильне значення.

Отже, я переглянув код 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
})

Команда Android дійсно повинна це виправити ... Те, що я встановив, - це в моєму спостерігачі LiveData, я відміняю реєстрацію onCheck, виконую свої дії, а потім повертаю її назад. Це працює лише тому, що зміни інтерфейсу користувача відбуваються на 1 потоці (основний потік).
Джеремі Джао

0

У Котліні:

        switch_button.setOnCheckedChangeListener { buttonView, isChecked ->
        if (isChecked) {
            // The switch enabled
            text_view.text = "Switch on"

        } else {
            // The switch disabled
            text_view.text = "Switch off"

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