I have ten toggle buttons. I want to save the state of five of those buttons when clicking the home button. But I want to save it only if the user has made a change to any of the buttons' state. Is there any way to know the change in states without using setOnClickListener()?
I have done the following, its not so nice, but it works:
ttsButton = (ToggleButton) findViewById(R.id.solution_ttsbutton);
ttsButton.setOnCheckedChangeListener(toggleButtonChangeListener);
...
// gets called, if the button state changes
final CompoundButton.OnCheckedChangeListener toggleButtonChangeListener = new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// The user changed the button, do something
}
};
and I do the following, if I want to change the button programatically without executing the change listener:
ttsButton.setOnCheckedChangeListener(null);
ttsButton.setChecked(false);
ttsButton.setOnCheckedChangeListener(toggleButtonChangeListener);
There is a simple way to know if user clicks the CompoundButton (CheckBox, Switch, RadioButton, ToggleButton), use the following:
new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
if (compoundButton.isPressed()) {
// do something related to user click/tap
} else {
// do something related to programmatically state changes (checked/unchecked)
}
}
}
.isPressed()
doesn't toggle for other input devices like a stylus (but I doubt that) –
Bookish Use CompoundButton.OnCheckedChangeListener
class.
ToggleButton button = /* ... */;
button.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// Save the state here
}
});
EDIT: If you want to use a single listener:
CompoundButton.OnCheckedChangeListener listener =
new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
String key = null;
switch(buttonView.getId()) {
case R.id.button1:
key = "key1";
break;
case R.id.button2:
key = "key2";
break;
default:
return;
}
// Save the state here using key
}
});
ToggleButton button1 = /* ... */;
button1.setOnCheckedChangeListener(listener);
ToggleButton button2 = /* ... */;
button2.setOnCheckedChangeListener(listener);
But there're plenty of ways to implement this really. So you can make up another method which suits your need better then this one.
.getId()
does not return the expected id ! –
Ment Use a custom view
import android.content.Context;
import android.util.AttributeSet;
import android.widget.Switch;
public class CustomSwitch extends Switch {
private OnCheckedChangeListener mListener;
public CustomSwitch(Context context) {
super(context);
}
public CustomSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomSwitch(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public CustomSwitch(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
// Do not call supper method
mListener = listener;
}
@Override
public void setChecked(boolean checked) {
super.setChecked(checked);
if (mListener != null) {
mListener.onCheckedChanged(this, checked);
}
}
public void setCheckedProgrammatically(boolean checked) {
// You can call super method, it doesn't have a listener... he he :)
super.setChecked(checked);
}
}
Sample XML usage
<com.your.package.CustomSwitch
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
Now the idea is to call the method setCheckedProgrammatically in code. setChecked gets called by Android when users changes the state of the compund button
Note that I'm using a switch, which extends the compund button, you can use basically the same code on any other (checkbox, ...)
For kotlin use this extension:
fun CompoundButton.setOnUserCheckedChangeListener(callback: (isChecked: Boolean) -> Unit) {
setOnCheckedChangeListener { buttonView, isChecked ->
if (buttonView.isPressed) {
callback.invoke(isChecked)
}
}
}
First check this link http://developer.android.com/resources/tutorials/views/hello-formstuff.html#ToggleButton
A simple onChangeListener will do:
public class TestProjectActivity extends Activity {
ToggleButton one;
ToggleButton two;
ToggleButton three;
ToggleButton four;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
one = (ToggleButton) findViewById(R.id.toggleButton1);
two = (ToggleButton) findViewById(R.id.toggleButton2);
three = (ToggleButton) findViewById(R.id.toggleButton3);
four = (ToggleButton) findViewById(R.id.toggleButton4);
one.setOnCheckedChangeListener(changeChecker);
two.setOnCheckedChangeListener(changeChecker);
three.setOnCheckedChangeListener(changeChecker);
four.setOnCheckedChangeListener(changeChecker);
}
OnCheckedChangeListener changeChecker = new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked){
if (buttonView == one) {
two.setChecked(false);
three.setChecked(false);
four.setChecked(false);
}
if (buttonView == two) {
one.setChecked(false);
three.setChecked(false);
four.setChecked(false);
}
if (buttonView == three) {
two.setChecked(false);
one.setChecked(false);
four.setChecked(false);
}
if (buttonView == four) {
two.setChecked(false);
three.setChecked(false);
one.setChecked(false);
}
}
}
};
}
Use View.OnTouchListener to listen to detect user interactions. I implemented this in my adapter class.
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<ViewHolder>
implements AccountUtils.OnAccountStateChange ,View.OnTouchListener{
// variable to store whether screen id pressed or not
public static boolean pressed=false;
//If User touches the screen
//MotionEvent.ACTION_DOWN is triggred
//and when user lifts his hand (takes away from screen)
//MotionEvent.ACTION_UP is triggred
// Here you should the change the value of pressed accordingly
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
pressed = true;// Screen Touched
break;
case MotionEvent.ACTION_UP:
pressed = false;// Screen
break;
}
return false;
}
static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
final SwitchCompat btnToggle;
public ViewHolder(final View itemView) {
super(itemView);
btnToggle = (SwitchCompat) itemView.findViewById(R.id.btn_toggle);
btnToggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// IF the value in Var pressed is true
// only then trigger this event
if (pressed) {
// YOUR METHOD GOES HERE
Toast.makeText(context, "Checked Changed", Toast.LENGTH_SHORT).show();
}
}
});
}
}
}
I would recommend this solution: https://mcmap.net/q/136765/-how-can-i-distinguish-whether-switch-checkbox-value-is-changed-by-user-or-programmatically-including-by-retention
Briefly, use "boolean CheckBox#isShown()" to determine which case, it returns false even you modify the check state within onStart() or onResume() of an activity. (I haven't tested the Fragment scenario.)
© 2022 - 2024 — McMap. All rights reserved.