android.widget.Switch - on / off pendengar acara?

229

Saya ingin menerapkan tombol sakelar, android.widget.Switch (tersedia dari API v.14).

<Switch
    android:id="@+id/switch1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Switch" />

Tapi saya tidak yakin bagaimana cara menambahkan pendengar acara untuk tombol tersebut. Haruskah itu menjadi pendengar "onClick"? Dan bagaimana saya tahu jika itu diaktifkan "on" atau tidak?

Johan
sumber
6
OnClick via XML benar-benar berfungsi - tetapi hanya untuk "klik" pada tombol, bukan untuk "slide".
m02ph3u5

Jawaban:

492

Alihkan CompoundButtonatribut bawaan , jadi saya akan merekomendasikan 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
    }
});
Sam
sumber
2
@ Johan Tidak masalah. Saya tidak tahu tentang Anda tetapi saya berharap mereka menamainya OnCheckChangedListener, mirip dengan OnItemSelectedListener, karena On- Noun - Verb -Listener adalah konvensi penamaan yang mapan.
Sam
2
Tetapi ketika Anda meletakkan fragmen pada contohnya, benda itu selalu menyala setiap kali Anda mengunjungi fragmen tersebut jika Anda mengatur sakelar ke Nyala.
klutch
1
@ Sam Bagaimana jika saya ingin mengubah sakelar ke status AKTIF atau MATI menggunakan metode setChcked () dan tidak ingin menjalankan metode onCheckedChanged? Tetapi ketika pengguna kembali mengetuk metode sakelar onCheckedChanged dieksekusi ... Apakah ada cara untuk melakukan ini?
deepak kumar
2
Tombol ada OnCLick, switch tidak punya OnChange! Tim Google yang dirancang dengan baik!
Vassilis
1
@ KZoNE Apa yang saya lakukan di sini adalah menggunakan pendengar klik untuk mengubah keadaan & meneruskan beralih ke metode (dalam kasus API panggilan saya) & kemudian menggunakan metode setChecked () untuk mengubah keadaan (seperti pada onFailure / onError dalam panggilan API) . Semoga itu bisa membantu.
deepak kumar
53

Gunakan cuplikan berikut untuk menambahkan Alihkan ke tata letak Anda melalui XML:

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

Kemudian dalam metode onCreate Aktivitas Anda, dapatkan referensi ke Switch Anda dan atur 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);
}       

});
shridutt kothari
sumber
3
Ini adalah jawaban yang lebih jelas memberi Anda tata letak dan kode di belakang yang cocok.
AshesToAshes
bagaimana cara mengatur beberapa switchcompat di satu pendengar? Tolong sarankan jawaban untuk itu
Anand Savjani
22

Bagi mereka yang menggunakan Kotlin, Anda dapat mengatur pendengar untuk beralih (dalam hal ini memiliki ID mySwitch) sebagai berikut:

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

isChecked benar jika saklar saat ini dicentang (ON), dan false jika tidak.

Faheel
sumber
19

Tentukan tata letak XML Anda:

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

Kemudian buat sebuah Aktivitas

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

    ****
}

======== Untuk di bawah API 14 gunakan 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>

Aktivitas

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
        }
    }
   *****
}
neferpitou
sumber
2
jangan lupa untuk memeriksa buttonView.isPressed ()
JacksOnF1re
5

Tata letak untuk beralih widget adalah sesuatu seperti ini.

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

Di kelas Activity, Anda bisa membuat kode dengan dua cara. Tergantung pada penggunaan Anda dapat kode.

Jalan Pertama

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

Cara kedua

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");
          }
       }       
     });
   }
}
Abish R
sumber
2

Anda bisa menggunakan DataBinding dan ViewModel untuk acara Change 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)}"
     />

Ali hasan
sumber
1
android.widget.Switch tidak memiliki attirbuteCheckedChanged. Anda akan mendapatkan kesalahan: AAPT: error: atribut android: onCheckedChanged tidak ditemukan.
Habis Terjual
1

ada dua cara,

  1. menggunakan xml onclick view Tambahkan Switch dalam XML seperti di bawah ini:

    <Switch
    android:id="@+id/switch1"
    android:onClick="toggle"/>

Di Kelas YourActivity (Misalnya 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. gunakan pada pendengar klik

Tambahkan Switch in XML seperti di bawah ini:

Di Kelas YourActivity (Misalnya 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));
                }
            }

        }

    });
Mrudul Addipalli
sumber
0

Solusi saya, menggunakan a SwitchCompatdan Kotlin. Dalam situasi saya, saya perlu bereaksi terhadap perubahan hanya jika pengguna memicu melalui UI. Bahkan, saklar saya bereaksi terhadap LiveData, dan ini membuat keduanya setOnClickListenerdan setOnCheckedChangeListenertidak dapat digunakan. setOnClickListenersebenarnya bereaksi dengan benar terhadap interaksi pengguna, tetapi itu tidak dipicu jika pengguna menyeret ibu jari melintasi sakelar.setOnCheckedChangeListenerdi ujung yang lain dipicu juga jika sakelar dimatikan secara terprogram (misalnya oleh pengamat). Sekarang dalam kasus saya saklar hadir pada dua fragmen, dan onRestoreInstanceState akan memicu dalam beberapa kasus saklar dengan nilai lama menimpa nilai yang benar.

Jadi, saya melihat kode SwitchCompat, dan mampu meniru perilakunya dengan sukses dalam membedakan klik dan seret dan menggunakannya untuk membangun daftar sentuh kustom yang berfungsi sebagaimana mestinya. Kita mulai:

/**
 * 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)
    }
}

Bagaimana cara menggunakannya:

pendengar sentuh aktual yang menerima lambda dengan kode untuk dieksekusi:

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

Demi kelengkapan, beginilah tampilan pengamat untuk negara switchstate(jika Anda memilikinya):

switchstate.observe(this, Observer {
    myswitch.isChecked = it
})
AndrewBloom
sumber
Tim Android benar-benar harus memperbaiki ini ... Apa yang saya lakukan ada di pengamat LiveData saya, saya membatalkan registrasi onCheck, melakukan tindakan saya, lalu mengaturnya kembali. Ini hanya berfungsi karena perubahan UI terjadi pada 1 utas (utas utama).
Jeremy Jao
0

Di Kotlin:

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

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

        }
    }
Shadros
sumber