OBX
OBX

Reputation: 6114

Prevent a ToggleButton from changing state onClick

This question is similar to this. However it did not solve my problem.

I have a ToggleButton and when a user clicks, I do not want to change the state of the ToggleButton, as I am programatically changing the state from another Activity. How do I override it?

Here is my Activity code:

<ToggleButton
       android:id="@+id/alarm1"
       android:background="@drawable/check"
       android:layout_alignParentLeft="true"
       android:layout_margin="8dp"
       android:textOn=""
       android:onClick="alarmSet1"
       android:textOff=""
       android:focusable="false"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content" />

Here is the Java code:

public void alarmSet1(View view)
{
    int a1=1;
    int idTime = (int) System.currentTimeMillis();
    Intent intent = new Intent(MainActivity.this, AddAlarm.class);
    intent.putExtra("pendInt",idTime);
    intent.putExtra("tts",a1);
    startActivity(intent);
}

Upvotes: 1

Views: 2248

Answers (2)

Joozd
Joozd

Reputation: 581

I am late to the party, but I had the exact same question and the given answer didn't fit my needs, so I made something myself.

What I wanted (correct me if this was not the original question):

  • I want to intercept clicks/swipes on a Switch, RadioButton, CheckBox or any other CompoundButton, making sure the button itself doesn't toggle state, but instead calling a function which will eventually lead to the correct state being set programatically. (eg. using LiveData) so the state of the button is always the same as the state of the data it toggles.

What I made:

/**
 * Use this if you want your compoundButton to do something when (un) checked,
 * but not change it's state by itself.
 *
 * It will block the actual changing of the button, but instead run [onCheckedChanged]
 * which should in turn eventually lead to setting `isChecked` to get proper setting of the switch
 * after its action has been performed
 * This might cause some trouble as it will trigger on programmatic sets outside of this listener.
 * To get around that, use [setIsCheckedWithoutBypassedListener] if you don't want that to happen.
 */
fun CompoundButton.setInterceptedOnCheckedChangedListener(onCheckedChanged: CompoundButton.OnCheckedChangeListener){
    compoundButtonListeners[this] = onCheckedChanged
    setOnCheckedChangeListener { compoundButton, b ->
        compoundButton.isChecked = !compoundButton.isChecked
        onCheckedChanged.onCheckedChanged(compoundButton, b)
    }
}

/**
 * Set value without triggering the listener added in [setInterceptedOnCheckedChangedListener]
 */
fun CompoundButton.setIsCheckedWithoutBypassedListener(isChecked: Boolean){
    compoundButtonListeners[this]?.let{ l ->
        setOnCheckedChangeListener(null)
        this.isChecked = isChecked
        setOnCheckedChangeListener(l)
    }
}

/**
 * Holds the OnCheckedChangeListeners for the compoundbuttons, as they are private and cannot
 * be retreived otherwise.
 */
private val compoundButtonListeners = WeakHashMap<CompoundButton, CompoundButton.OnCheckedChangeListener>()

If this ends up putting a lot of _, _ ->'s in your code, feel free to replace the CompoundButton.OnCheckedChangeListener with a View.OnClickListener.

Leaving this here in case somebody else has the same question as I had.

I am pretty sure using a WeakHashMap prevents a memory leak that would happen on recreating activity. If this is not the case, please educate me :)

Upvotes: 2

Anibal Itriago
Anibal Itriago

Reputation: 1051

It is simple: Create a CompoundButton.OnCheckedChangeListener and override onCheckedChanged like this:

private CompoundButton.OnCheckedChangeListener _toggleButtonListener = new  CompoundButton.OnCheckedChangeListener()
{
    @Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
        compoundButton.setChecked(false);

        // And now, do whatever you want.
    }
};

Of course, you have to attach the listener to your button:

... somewhere in the onCreate() method:
ToggleButton toggleButton=findViewById(R.id.alarm1);
toggleButton.setOnCheckedChangeListener(_toggleButtonListener);

And thats it.

Keep coding, and let the code be with you!

Upvotes: 1

Related Questions