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

สลับ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
@Janan ไม่มีปัญหา ฉันไม่ทราบเกี่ยวกับคุณ แต่ฉันหวังว่าพวกเขาตั้งชื่อมัน OnCheckChangedListener คล้ายกับ OnItemSelectedListener ตั้งแต่ On- คำนาม - คำกริยา - Listener เป็นตัวตั้งชื่อที่สร้างขึ้น
Sam

2
แต่เมื่อคุณใส่แฟรกเมนต์ลงบนชิ้นส่วนนั้นไฟจะเกิดขึ้นทุกครั้งที่คุณกลับมาแฟรกเมนต์อีกครั้งหากคุณตั้งสวิตช์เป็นเปิด
klutch

1
@Sam เกิดอะไรขึ้นถ้าฉันต้องการเปลี่ยนสวิตช์เป็นเปิดหรือปิดโดยใช้วิธีการ setChcked () วิธีการและไม่ต้องการที่จะดำเนินการวิธีการ onCheckedChanged? แต่เมื่อผู้ใช้อีกครั้งแตะที่วิธีการเปลี่ยนในการตรวจสอบการเปลี่ยนแปลงได้รับการดำเนินการ ... มีวิธีการทำเช่นนี้?
deepak kumar

2
มีปุ่มOnCLickสวิตช์ไม่มีOnChange! ทีมงาน Google ที่ออกแบบมาอย่างดี!
Vassilis

1
@ KZoNE สิ่งที่ฉันทำที่นี่ใช้ตัวฟังคลิกเพื่อเปลี่ยนสถานะ & ผ่านสวิตช์เป็นวิธี (ในกรณีของฉันเรียก API) จากนั้นใช้เมธอด setChecked () เพื่อเปลี่ยนสถานะ (เช่น onFailure / onError ในการเรียก API) . หวังว่าจะช่วย
deepak kumar

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

วิธีการจัดการ switchcompat หลาย ๆ ตัวใน listener เดียว? กรุณาแนะนำคำตอบสำหรับสิ่งนั้น
Anand Savjani

22

สำหรับผู้ที่ใช้ Kotlin คุณสามารถตั้งค่าฟังสำหรับสวิตช์ (ในกรณีนี้มี ID mySwitch) ดังต่อไปนี้:

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

isChecked เป็นจริงถ้าสวิตช์ถูกตรวจสอบในขณะนี้ (ON) และเท็จเป็นอย่างอื่น


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.isPressed ()
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: ข้อผิดพลาด: แอตทริบิวต์ android: ไม่พบ onCheckedChanged
จำหน่ายหมด

1

มีสองวิธีคือ

  1. ใช้ xml onclick view เพิ่ม Switch ใน XML ดังต่อไปนี้:

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

ใน YourActivity Class (เช่น 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 Class (เช่น 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

ทางออกของฉันโดยใช้SwitchCompatและ Kotlin ในสถานการณ์ของฉันฉันจำเป็นต้องตอบสนองต่อการเปลี่ยนแปลงเฉพาะเมื่อผู้ใช้ทริกเกอร์ผ่าน UI ในความเป็นจริงสวิตช์ของฉันตอบสนองต่อ a 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
})

ทีม Android ควรแก้ไขสิ่งนี้ ... สิ่งที่ฉันทำอยู่ในผู้สังเกตการณ์ LiveData ของฉันฉันยกเลิกการลงทะเบียน onCheck ทำการกระทำแล้วตั้งค่ากลับมา ใช้งานได้เนื่องจากการเปลี่ยนแปลง UI เกิดขึ้นใน 1 เธรด (เธรดหลัก)
Jeremy Jao

0

ใน 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"

        }
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.