android.widget.Switch - người nghe sự kiện bật / tắt?


229

Tôi muốn triển khai nút chuyển đổi, android.widget.Switch (có sẵn từ API v.14).

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

Nhưng tôi không chắc làm thế nào để thêm một trình lắng nghe sự kiện cho nút. Nó có nên là một trình nghe "onClick" không? Và làm thế nào để tôi biết nếu nó được bật "bật" hay không?


6
OnClick qua XML thực sự hoạt động - nhưng chỉ với "lần nhấp" trên nút, không phải cho "trang trình bày".
m02ph3u5

Câu trả lời:


492

Chuyển đổi CompoundButtoncác thuộc tính kế thừa , vì vậy tôi muốn giới thiệu 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 Không có rắc rối. Tôi không biết về bạn nhưng tôi ước họ đặt tên cho nó là OnCheckChangedListener, tương tự như OnItemSelectedListener, vì On- Noun - Verb -Listener là một cách đặt tên được thiết lập.
Sam

2
Nhưng khi bạn đặt một đoạn chẳng hạn, thứ đó sẽ luôn kích hoạt bất cứ khi nào bạn xem lại đoạn đó nếu bạn đặt công tắc thành Bật.
klutch

1
@Sam Điều gì xảy ra nếu tôi muốn thay đổi công tắc sang trạng thái BẬT hoặc TẮT bằng phương thức setChcked () và không muốn thực thi phương thức onCheckedChanged? Nhưng khi người dùng một lần nữa chạm vào phương thức chuyển đổi trênCheckedChanged được thực thi ... Có cách nào để làm điều này không?
Deepak kumar

2
Nút có OnCLick, công tắc không có OnChange! Đội ngũ Google được thiết kế tốt!
Vassilis

1
@KZoNE Những gì tôi đã làm ở đây được sử dụng trình nghe nhấp để thay đổi trạng thái & chuyển công tắc sang phương thức (trong trường hợp gọi API của tôi) và sau đó sử dụng phương thức setChecked () để thay đổi trạng thái (như trong onFailure / onError trong lệnh gọi API) . Mong rằng sẽ giúp.
Deepak kumar

53

Sử dụng đoạn mã sau để thêm Chuyển sang bố cục của bạn qua XML:

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

Sau đó, trong phương thức onCreate của Activity, hãy tham khảo Switch của bạn và đặt OnCheckedChangeListener của nó:

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
Đây là một câu trả lời rõ ràng hơn cung cấp cho bạn bố cục và mã phía sau để phù hợp.
AshesToAshes

Làm thế nào để quản lý nhiều switchcompat trong trình nghe đơn? Vui lòng đề xuất câu trả lời cho điều đó
Anand Savć

22

Đối với những người sử dụng Kotlin, bạn có thể đặt trình nghe cho một công tắc (trong trường hợp này có ID mySwitch) như sau:

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

isChecked là đúng nếu công tắc hiện đang được kiểm tra (ON) và sai khác.


19

Xác định bố cục XML của bạn:

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

Sau đó tạo một Hoạt động

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

    ****
}

======== Dành cho API bên dưới 14 sử dụng 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>

Hoạt động

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
đừng quên kiểm tra nútView.isPression ()
JacksOnF1re

5

Bố cục cho widget Switch là một cái gì đó như thế này.

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

Trong lớp Activity, bạn có thể viết mã theo hai cách. Phụ thuộc vào việc sử dụng bạn có thể mã.

Cách thứ nhất

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

Cách thứ hai

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

Bạn có thể sử dụng DataBinding và ViewModel cho sự kiện Thay đổi được kiểm tra chuyển đổi

<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 không có attirbute onCheckedChanged. Bạn sẽ gặp lỗi: AAPT: error: thuộc tính android: onCheckedChanged không tìm thấy.
Bán hết

1

có hai cách,

  1. sử dụng xml onclick view Add Switch in XML như dưới đây:

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

Trong lớp YourActivity (Ví dụ: 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. sử dụng khi nghe

Thêm Switch trong XML như dưới đây:

Trong lớp YourActivity (Ví dụ: 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

Giải pháp của tôi, sử dụng một SwitchCompatvà Kotlin. Trong tình huống của tôi, tôi chỉ cần phản ứng với thay đổi nếu người dùng kích hoạt nó thông qua UI. Trong thực tế, công tắc của tôi phản ứng với a LiveData, và điều này làm cho cả hai setOnClickListenersetOnCheckedChangeListenerkhông thể sử dụng được. setOnClickListenerthực tế phản ứng chính xác với tương tác của người dùng, nhưng nó không được kích hoạt nếu người dùng kéo ngón tay cái qua công tắc.setOnCheckedChangeListenerở đầu bên kia cũng được kích hoạt nếu công tắc được bật theo chương trình (ví dụ bởi người quan sát). Bây giờ trong trường hợp của tôi, công tắc đã có mặt trên hai mảnh và do đó, onRestoreInstanceState sẽ kích hoạt trong một số trường hợp công tắc có giá trị cũ ghi đè giá trị chính xác.

Vì vậy, tôi đã xem mã của SwitchCompat và có thể bắt chước thành công hành vi của nó trong việc phân biệt nhấp và kéo và sử dụng nó để xây dựng một trình nghe cảm ứng tùy chỉnh hoạt động như bình thường. Ở đây chúng tôi đi:

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

Làm thế nào để sử dụng nó:

trình nghe cảm ứng thực tế chấp nhận lambda với mã để thực thi:

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

Để hoàn thiện, đây là cách người quan sát trạng thái switchstate(nếu bạn có) trông giống như:

switchstate.observe(this, Observer {
    myswitch.isChecked = it
})

Nhóm Android thực sự nên khắc phục điều này ... Những gì tôi đã thực hiện là trong trình quan sát LiveData của tôi, tôi hủy đăng ký onCheck, thực hiện hành động của mình, sau đó đặt lại. Điều này chỉ hoạt động vì những thay đổi UI xảy ra trên 1 luồng (luồng chính).
Jeremy Jao

0

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

        }
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.