android.widget.Switch - açık / kapalı olay dinleyicisi?


229

Bir anahtar düğmesi, android.widget.Switch (API v.14'ten edinilebilir) uygulamak istiyorum.

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

Ancak düğme için nasıl bir olay dinleyicisi ekleyeceğinizden emin değilim. Bir "onClick" dinleyicisi mi olmalı? Ve "açık" olarak değiştirilip değiştirilmediğini nasıl bilebilirim?


6
XML üzerinden OnClick gerçekten işe yarıyor - ancak düğme üzerindeki "tıklamalar" için "slaytlar" için değil.
m02ph3u5

Yanıtlar:


493

Anahtar devralmaCompoundButton öznitelikleri, bu yüzden OnCheckedChangeListener tavsiye ederim

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 Sorun değil. Seni bilmem ama ben On- beri, OnItemSelectedListener benzer bunu OnCheckChangedListener adlı dilek İsim - Fiil -Listener kurulu bir adlandırma Convetion olduğunu.
Sam

2
Ancak, örneğin bir parçasını koyduğunuzda, anahtarı Açık olarak ayarlarsanız parçayı her yeniden ziyaret ettiğinizde bu şey her zaman tetiklenir.
klutch

1
@Sam yöntem setChcked () yöntemini kullanarak anahtarı AÇIK veya KAPALI durumuna değiştirmek ve onCheckedChanged yöntemini yürütmek istemezsem ne olur? Ancak kullanıcı tekrar onCheckedChanged anahtar yöntemine dokunduğunda ... Bunu yapmanın bir yolu var mı?
deepak kumar

2
Düğmeler var OnCLick, anahtarlar yok OnChange! İyi tasarlanmış Google ekibi!
Vassilis

1
@KZoNE Burada yaptığım, durumu değiştirmek için tıklama dinleyicisini kullanıyor ve yöntemi (benim durumumda API çağrısında) geçişe geçiyor ve daha sonra durumu değiştirmek için setChecked () yöntemini kullanıyor (API çağrısında onFailure / onError gibi) . Umarım yardımcı olur.
deepak kumar

53

XML yoluyla mizanpajınıza bir Anahtar eklemek için aşağıdaki snippet'i kullanın:

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

Ardından Etkinliğinizin onCreate yönteminde Switch'inize bir başvuru alın ve OnCheckedChangeListener'ı ayarlayı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
Bu size maç için arka plan ve kodu veren daha açık bir cevaptır.
AshesToAshes

tek dinleyicide birden fazla anahtar uyumunu nasıl yönetebilirim? Lütfen bunun için cevap önerin
Anand Savjani

22

Kotlin'i kullananlar için, bir anahtar için bir dinleyici (bu durumda kimliğe sahip mySwitch) aşağıdaki gibi ayarlayabilirsiniz :

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

isChecked anahtar şu anda işaretliyse (AÇIK) doğrudur, aksi halde false olur.


19

XML düzeninizi tanımlayı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> 

Ardından bir Etkinlik oluşturun

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

    ****
}

======== Aşağıdaki API 14 için SwitchCompat kullanın =========

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>

Aktivite

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

Anahtar widget'ının düzeni şu şekildedir.

<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 sınıfında iki şekilde kod yazabilirsiniz. Kullanabileceğinize göre kodlayabilirsiniz.

Birinci Yol

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

İkinci yol

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

Anahtar İşaretli Değişiklik olayı için DataBinding ve ViewModel kullanabilirsiniz

<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'a sahip değil. Hata alırsınız: AAPT: hata: android: onCheckedChanged özniteliği bulunamadı.
Tükendi

1

iki yol var,

  1. xml onclick view kullanarak XML'de Switch'i aşağıdaki gibi ekleyin:

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

YourActivity Sınıfınızda (Örn. MainActivity.java için)

    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. tıklama dinleyicisini kullanma

XML'de Switch'i aşağıdaki gibi ekleyin:

YourActivity Sınıfınızda (Örn. MainActivity.java için)

    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 SwitchCompatve Kotlin kullanarak çözümüm . Benim durumumda, bir değişime yalnızca kullanıcı kullanıcı arayüzü aracılığıyla tetiklediğinde tepki vermeliydim. Aslında, benim anahtar bir karşı tepki verir LiveDatave bu hem yapılmış setOnClickListenerve setOnCheckedChangeListenerkullanışsız. setOnClickListeneraslında kullanıcı etkileşimine doğru tepki verir, ancak kullanıcı başparmağı anahtar boyunca sürüklerse tetiklenmez. setOnCheckedChangeListenerdiğer uçta da anahtar programlı olarak değiştirilirse (örneğin bir gözlemci tarafından) tetiklenir. Şimdi benim durumumda anahtar iki parça üzerinde mevcuttu ve bu yüzden onRestoreInstanceState bazı durumlarda eski değeri olan anahtarın doğru değerin üzerine yazılmasını tetikleyecektir.

Bu yüzden, SwitchCompat koduna baktım ve tıklama ve sürüklemeyi ayırt etme davranışını başarıyla taklit edebildim ve gerektiği gibi çalışan özel bir dokunmatik liste oluşturmak için kullandım. İşte başlıyoruz:

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

Bu nasıl kullanılır:

yürütmek için kodlu bir lambda kabul eden gerçek dokunmatik dinleyici:

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

Bütünlük uğruna, devletin gözlemcisi switchstate(eğer varsa) şöyle görünüyordu:

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

Android ekibi gerçekten bunu düzeltmeli ... Yaptığım şey LiveData gözlemcimde, onCheck'in kaydını siliyorum, eylemimi yapıyorum, sonra geri ayarlıyorum. Bu yalnızca UI değişiklikleri 1 iş parçacığında (ana iş parçacığı) gerçekleştiği için çalışır.
Jeremy Jao

0

Kotlin'de:

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

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

        }
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.