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
XML을 통한 OnClick은 실제로 작동하지만 "슬라이드"가 아닌 버튼의 "클릭"에 대해서만 작동합니다.
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
@Johan 문제 없습니다. 나는 당신에 관하여 모른다 그러나 나는 온 이후 그들은, OnItemSelectedListener 유사, 그것을 OnCheckChangedListener라는 이름의 소원 명사 - 동사 -Listener가 설립 명명 convetion입니다.
Sam

2
그러나 예를 들어 프래그먼트를 넣을 때 스위치를 On으로 설정하면 프래그먼트를 다시 방문 할 때마다 해당 항목이 항상 발생합니다.
klutch

1
@Sam setChcked () 메소드를 사용하여 스위치를 ON 또는 OFF 상태로 변경하고 onCheckedChanged 메소드를 실행하지 않으려면 어떻게해야합니까? 그러나 사용자가 onCheckedChanged 스위치 방법을 다시 탭하면 실행됩니다 ...이 방법이 있습니까?
deepak kumar

2
버튼에는 OnCLick스위치가 없습니다 OnChange! 잘 설계된 Google 팀!
Vassilis 2016 년

1
@KZoNE 내가 한 것은 클릭 리스너를 사용하여 상태를 변경하고 스위치를 메소드 (내 경우 API 호출)로 전달 한 다음 setChecked () 메소드를 사용하여 상태를 변경합니다 (API 호출의 onFailure / onError와 같이) . 희망이 도움이됩니다.
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"/>

그런 다음 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);
}       

});

3
이것은 당신에게 맞는 레이아웃과 코드를 제공하는 더 명확한 대답입니다.
AshesToAshes

단일 리스너에서 여러 switchcompat를 관리하는 방법은 무엇입니까? 이에 대한 답변을 제안하십시오
Anand Savjani

22

Kotlin을 사용하는 경우 mySwitch다음과 같이 스위치 (이 경우 ID가있는 ) 에 대한 리스너를 설정할 수 있습니다 .

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

isChecked 스위치가 현재 검사 (ON) 된 경우 true이고, 그렇지 않으면 false입니다.


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

스위치 위젯의 레이아웃은 다음과 같습니다.

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

2

스위치 확인 변경 이벤트에 DataBinding 및 ViewModel을 사용할 수 있습니다.

<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 속성이 없습니다. 오류 : AAPT : 오류 : android : onCheckedChanged 속성을 찾을 수 없습니다.
매진

1

두 가지 방법이 있습니다

  1. 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));
            }
        }
    }
  1. 클릭 리스너 사용

아래와 같이 XML로 Switch를 추가하십시오 :

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

SwitchCompat및 Kotlin을 사용하는 내 솔루션 . 내 상황에서 사용자가 UI를 통해 변경 한 경우에만 변경에 반응해야했습니다. 사실, 내 스위치 A에 반응 LiveData하고,이 두 만든 setOnClickListenersetOnCheckedChangeListener사용할 수 있습니다. 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
})

안드로이드 팀은 정말로 이것을 고쳐야합니다 ... 내가 수행 한 것은 내 LiveData 관찰자에 있습니다. onCheck를 등록 취소하고 작업을 수행 한 다음 다시 설정하십시오. UI 변경은 1 스레드 (주 스레드)에서 발생하기 때문에 작동합니다.
Jeremy Jao

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"

        }
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.