I am trying to change the background colour of a activity where the user can change the colour using 3 radio buttons in an android app. I am doing this using sharedPreferences.
So I have the activity page where the colour is chosen with the radio group and the code to use sharedPrefernces looks like this (i know the switch statement works aswell as I have a toast message apperring when the colour is supposed to change):
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_preferences);
RadioGroup radioGroup = (RadioGroup) findViewById(R.id.radiogroup);
radioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(RadioGroup group, int checkedId) {
SharedPreferences prefs = getSharedPreferences("bgColour", MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
String colourSelected = "";
switch (checkedId) {
case R.id.radioButton1 :
colourSelected = "YELLOW";
editor.putString("colour", colourSelected);
editor.commit();
break;
case R.id.radioButton2 :
colourSelected = "YELLOW";
editor.putString("colour", colourSelected);
editor.commit();
break;
case R.id.radioButton3 :
colourSelected = "BLUE";
editor.putString("colour", colourSelected);
editor.commit();
break;
}
}
});
}
The XML looks like this
<LinearLayout 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"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.practical3_10327751_donnacha_holmes.Preferences" >
<RadioGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="#+id/radiogroup"
>
<RadioButton
android:id="#+id/radioButton1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Green" />
<RadioButton
android:id="#+id/radioButton2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Yellow" />
<RadioButton
android:id="#+id/radioButton3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Blue" />
</RadioGroup>
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Back" />
Then there is the activity that changes the background colour, which looks like this when trying to change the colour:
public class Activity2 extends ActionBarActivity {
RelativeLayout rl;
String colour;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_activity2);
SharedPreferences prefs = getSharedPreferences("bgColour", MODE_PRIVATE);
colour = prefs.getString("Colour", "WHITE");
rl = (RelativeLayout)findViewById(R.id.RelativeLayout);
if(colour=="GREEN"){
rl.setBackgroundColor(Color.GREEN);
}
else if(colour=="YELLOW"){
rl.setBackgroundColor(Color.YELLOW);
}
else if(colour=="BLUE"){
rl.setBackgroundColor(Color.BLUE);
}
else{
rl.setBackgroundColor(Color.RED);
}
I know that the background colour is being changed because it is being set to red every time I go to this page.
Thanks for any help!
The == operator checks to see if the two strings are exactly the same object.
The .equals() method will check if the two strings have the same value.
Therefore to compare Strings use .equals(),i.e. rewrite your comparison as
if(colour.equals("GREEN")){
rl.setBackgroundColor(Color.GREEN);
}
else if(colour.equals("YELLOW")){
rl.setBackgroundColor(Color.YELLOW);
}
else if(colour.equals("BLUE")){
rl.setBackgroundColor(Color.BLUE);
}
else{
rl.setBackgroundColor(Color.RED);
}
and you are saving value as colour and try to retrieving as Colour,so change
colour = prefs.getString("Colour", "WHITE");
to
colour = prefs.getString("colour", "WHITE");
Related
As the title says, I get this error while interacting with a Spinner. I've noticed that there are many post about this argument, but every one is different from each other (answers too). Unfortunately, I didn't find a solution, so I'm asking here.
Here is a screenshot of the Spinner:
As you can see, the first Spinner is ok, but the second has two problems:
First one, it doesn't show values
Second one, when I tap the spinner, nothing happen. If I tap again the spinner, I get the error "Attempted to finish an input event but the input event receiver has already been disposed."
Maybe the two things are connected somehow...
Here is the code:
public class Settings extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings);
Integer[] radiusArray = new Integer[]{500,700,1000,1500,2000,2500,3000,4000,5000};
Integer[] geofenceRadius = new Integer[]{100,200,300,400,500};
try {
final Spinner spinnerRA = (Spinner) findViewById(R.id.search_radius);
final Spinner spinnerGR = (Spinner) findViewById(R.id.geofence_radius);
ArrayAdapter<Integer> adapterRA = new ArrayAdapter<Integer>(this,android.R.layout.simple_spinner_item, radiusArray);
spinnerRA.setAdapter(adapterRA);
ArrayAdapter<Integer> adapterGR = new ArrayAdapter<Integer>(this,android.R.layout.simple_spinner_item, geofenceRadius);
spinnerRA.setAdapter(adapterGR);
//Getting from preference files, saved settings, if any
//1000 and 100 are default settings
final SharedPreferences sharedPref = getSharedPreferences("Settings",Context.MODE_PRIVATE);
String temp = getResources().getString(R.string.search_radius);
int savedRadius = sharedPref.getInt(temp, 1000);
temp = getResources().getString(R.string.geofence_radius);
int savedGeofence = sharedPref.getInt(temp, 100);
//Show selected value for spinner, or default value
int i;
for(i=0; i<radiusArray.length; i++){
if(radiusArray[i].equals(savedRadius)){
break;
}
}
spinnerRA.setSelection(i);
for(i=0; i<geofenceRadius.length; i++){
if(geofenceRadius[i].equals(savedGeofence)){
break;
}
}
spinnerGR.setSelection(i);
Button Save = (Button) findViewById(R.id.save_settings_button);
Save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Integer searchRadius = (Integer)spinnerRA.getSelectedItem();
Integer geofenceRadius = (Integer)spinnerGR.getSelectedItem();
//Saving new value of search_radius
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt(getString(R.string.search_radius),searchRadius);
editor.putInt(getString(R.string.geofence_radius),geofenceRadius);
editor.putBoolean(getString(R.string.initialized),true);
editor.commit();
CharSequence text = "Changes saved succesfully!";
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(getApplicationContext(), text, duration);
toast.show();
}
});
}catch (Exception e){
e.printStackTrace();
}
}
}
And here is the xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Settings"
android:textSize="14pt"
android:layout_marginTop="8pt"
android:gravity="center"/>
<View android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="5pt"
android:id="#+id/second_gray_line"
android:background="#android:color/darker_gray"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="10pt">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Initial search radius (in meters):"
android:textColor="#FF8500"
android:layout_marginLeft="10pt"
android:layout_marginTop="15pt"
android:textSize="11pt"/>
<Spinner
android:layout_width="60pt"
android:layout_height="wrap_content"
android:id="#+id/search_radius"
android:layout_marginTop="5pt"
android:layout_marginLeft="5pt">
</Spinner>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="10pt">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Location radius (in meters):"
android:textColor="#FF8500"
android:layout_marginLeft="10pt"
android:layout_marginTop="15pt"
android:textSize="11pt"/>
<Spinner
android:layout_width="60pt"
android:layout_height="wrap_content"
android:id="#+id/geofence_radius"
android:layout_marginTop="5pt"
android:layout_marginLeft="5pt">
</Spinner>
</LinearLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/save_settings_button"
android:text="Save Settings"
android:textSize="10pt"
android:layout_gravity="center"
android:layout_marginTop="50pt"/>
</LinearLayout>
I think it's a really stupid error, but I can't figure out what causes it. Could you help me? Thank you!
I solved and, as I said, the error was really stupid... I made a mistake here, in the second adapter:
ArrayAdapter<Integer> adapterGR = new ArrayAdapter<Integer>(this,android.R.layout.simple_spinner_item, geofenceRadius);
spinnerRA.setAdapter(adapterGR);
This must be changed in:
ArrayAdapter<Integer> adapterGR = new ArrayAdapter<Integer>(this,android.R.layout.simple_spinner_item, geofenceRadius);
spinnerGR.setAdapter(adapterGR);
It was just an oversight. I was setting the second adapter using spinnerRA instead of spinnerGR. Now it works!
I'm trying to do in android a group of buttons that can be selected and activate only one of them. I need to work with the same logic of a radiogroup and radiobuttons.
I tried many alternatives but I want the most effective way. How can I do it?
You can use this simple way :
1.activity_button_group.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A"
android:id="#+id/btn0"
android:layout_gravity="center_vertical" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="B"
android:id="#+id/btn1"
android:layout_gravity="center_vertical" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="C"
android:id="#+id/btn2"
android:layout_gravity="center_vertical" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="D"
android:id="#+id/btn3"
android:layout_gravity="center_vertical" />
</LinearLayout>
2.ButtonGroupActivity.java
public class ButtonGroupActivity extends Activity implements View.OnClickListener{
private Button[] btn = new Button[4];
private Button btn_unfocus;
private int[] btn_id = {R.id.btn0, R.id.btn1, R.id.btn2, R.id.btn3};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_button_group);
for(int i = 0; i < btn.length; i++){
btn[i] = (Button) findViewById(btn_id[i]);
btn[i].setBackgroundColor(Color.rgb(207, 207, 207));
btn[i].setOnClickListener(this);
}
btn_unfocus = btn[0];
}
#Override
public void onClick(View v) {
//setForcus(btn_unfocus, (Button) findViewById(v.getId()));
//Or use switch
switch (v.getId()){
case R.id.btn0 :
setFocus(btn_unfocus, btn[0]);
break;
case R.id.btn1 :
setFocus(btn_unfocus, btn[1]);
break;
case R.id.btn2 :
setFocus(btn_unfocus, btn[2]);
break;
case R.id.btn3 :
setFocus(btn_unfocus, btn[3]);
break;
}
}
private void setFocus(Button btn_unfocus, Button btn_focus){
btn_unfocus.setTextColor(Color.rgb(49, 50, 51));
btn_unfocus.setBackgroundColor(Color.rgb(207, 207, 207));
btn_focus.setTextColor(Color.rgb(255, 255, 255));
btn_focus.setBackgroundColor(Color.rgb(3, 106, 150));
this.btn_unfocus = btn_focus;
}
}
You could still use Radio Buttons inside a Radio Group, and attributes to make each radio button look like a button.
In xml, for each radio button set android:button="#null", so that dots won't be visible. You could add some padding to make it look different.
In code, set a CheckedChangeListener to your radioGroup, then find the reference to the checkedView (RadioButton) with checkedId. In this example I've just changed the background color of the view, but you could add a different background too. If the radioButton is not null, it means it has already been changed, so I'll set its initial state again.
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (radioButton != null) {
radioButton.setBackgroundColor(Color.TRANSPARENT);
radioButton.setButtonDrawable(0); // removes the image
}
radioButton = (RadioButton) group.findViewById(checkedId);
radioButton.setBackgroundColor(Color.YELLOW);
radioButton.setButtonDrawable(R.drawable.icon); //sets the image
}
});
Hope this helps!
While you can set this in code as Denny Schuldt suggested, a "cleaner" way is to do it in xml (e.g. drawable/radio.xml):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/button_checked" android:state_checked="true" />
<item android:drawable="#android:color/transparent" />
</selector>
And set it as button background: android:background="#drawable/radio"
I have an ImageView(see image below), which is clickable. When the user clicks on the ImageView, he gets redirected to website. This is all running fine.
My question is, how to let user know, he can click the image, how to make this feature visible?
I can add text under the image, but thats not, what i want. I would like some small icon or window(like dialog), which can be closed.
Thanks!
you can check by bellow:
imageViewObject.isClickable();
Maybe you could animate a small finger/hand icon tapping the image when the ImageView shows up to indicate the element is clickable.
Like this: http://cmsresources.windowsphone.com/windowsphone/en-us/How-to/wp7/block/gettingstarted-concept-tap-and-hold-gesture.png
Or you could use gradients and shadows to give the image a button look.
So I searched and found this. This is #kgandroid suggested.
I add a little bit of code:
private FrameLayout mFrame;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mFrame = new FrameLayout(this);
mFrame.addView(LayoutInflater.from(getBaseContext()).inflate(R.layout.activity_single_list_view, null));
setContentView(mFrame);
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
boolean overlayShown = settings.getBoolean("overlayShown", false);
if(!overlayShown){
setupHelpOverlay();
}
...
}
private void setupHelpOverlay(){
final View tutView = LayoutInflater.from(getBaseContext()).inflate(R.layout.activity_detail_overlay, null);
if(mFrame != null){
mFrame.addView(tutView);
}
// We need an Editor object to make preference changes.
// All objects are from android.context.Context
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("overlayShown", true);
// Commit the edits!
editor.commit();
Button btnDismiss = (Button) tutView.findViewById(R.id.button_overlay);
btnDismiss.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v){
mFrame.removeView(tutView);
}
});
}
And the activity_deatil_overlay.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/transparent_gray" >
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/textView1"
android:layout_centerHorizontal="true"
android:textSize="20sp"
android:gravity="center"
android:textColor="#color/white"
android:text="#string/overlay_text"
android:paddingBottom="10dp" />
<View
android:id="#+id/textView1"
android:layout_width="1dp"
android:layout_height="1dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true" />
<Button
android:id="#+id/button_overlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView1"
android:layout_centerHorizontal="true"
android:text="#string/overlay_button"
android:textColor="#color/white"
android:paddingTop="10dp" />
</RelativeLayout>
On the first start, it shows help overlay.
You could put a bar around the Image and change its color when the image is pressed. So it looks like a button.
I have a simple activity which needs to accept a 4-digit PIN number using a custom pin-pad (buttons on the screen). The digits are stored in four EditTexts.
When I click a button, the text in the button is stored in a char[] (myEditText.getText() shows that this is happening), the focus is moved to the next EditText through an onFocusListener() and the Log output shows that this is all happening correctly.
11-20 10:19:56.969: I/DebugA(17742): Pin1 updated to: 1 // Pin1 is the ID
11-20 10:19:58.289: I/DebugA(17742): Pin2 updated to: 2 // '2' is Pin2.getText()
11-20 10:19:58.849: I/DebugA(17742): Pin3 updated to: 3
11-20 10:19:59.659: I/DebugA(17742): Pin4 updated to: 4
The screen itself is simply not being updated. The EditTexts all appear empty, even though the code executes perfectly.
I have looked through a whole heap of answers on SO and tried many of the suggestions with absolutely no luck, so I am posting this question which I hope someone can shed some light on! Has anyone else had this happen?
Here's some of the layout file:
<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" >
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/layout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="42dp" >
<EditText
android:id="#+id/Pin1"
android:tag="Pin1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="2"
android:gravity="center_vertical|center_horizontal"
android:nextFocusDown="#+id/Pin2"
android:maxLength="1"
android:inputType="textPassword" />
...
...
...
</RelativeLayout>
...and the buttons are:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/layout2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="21dp"
android:layout_below="#+id/layout1" >
<Button
android:id="#+id/Button01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="btnPinClick"
android:text="1" />
<Button
android:id="#+id/Button02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="btnPinClick"
android:layout_marginLeft="21dp"
android:text="2" />
<Button
android:id="#+id/Button03"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="btnPinClick"
android:layout_marginLeft="21dp"
android:text="3" />
</LinearLayout>
The activity is a standard activity (MyActivity extends Activity).
Any thoughts?
UPDATE
Here's some of the java as requested:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
RelativeLayout layout = (RelativeLayout)inflater.inflate(R.layout.activity_login, null);
EditText Pin1 = (EditText) layout.findViewById(R.id.Pin1);
Pin1.setOnFocusChangeListener(focusListener);
Pin1.setText("1"); // <--THIS HAS NO EFFECT
EditText Pin2 = (EditText) layout.findViewById(R.id.Pin2);
Pin2.setOnFocusChangeListener(focusListener);
EditText Pin3 = (EditText) layout.findViewById(R.id.Pin3);
Pin3.setOnFocusChangeListener(focusListener);
EditText Pin4 = (EditText) layout.findViewById(R.id.Pin4);
Pin4.setOnFocusChangeListener(focusListener);
...
...
...
}
The Onclick method is:
public void btnPinClick(View btnPin) {
String PinNumber = ((Button)btnPin).getText().toString();
RelativeLayout layout = (RelativeLayout)getLayoutInflater().inflate(R.layout.activity_login, null);
ArrayList<View> views = (ArrayList<View>) layout.getFocusables(View.FOCUS_DOWN);
EditText nextItem = null;
for (int i = 0; i < views.size(); i++) {
// THIS IS THE CORRECT EditText FOR EACH OF THESE
EditText textBox = (EditText) views.get(i);
if (textBox.getTag().toString().equals(currentText)) {
textBox.setText(PinNumber);
pin[i] = PinNumber.toCharArray()[0];
Log.i("DebugA", textBox.getTag().toString() + " updated to: " + textBox.getText().toString());
textBox.invalidate();
textBox.refreshDrawableState();
if(i+1 < views.size()) {
nextItem = (EditText) views.get(i+1);
}
else {
doCheckPin();
}
break;
}
}
if(nextItem != null){
nextItem.requestFocus();
currentText = nextItem.getTag().toString();
}
}
UPDATE 2
Here is the code for the OnFocusChangeListener as requested:
protected OnFocusChangeListener focusListener = new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus) {
//THIS SIMPLY SETS A VARIABLE STRING TO SAY WHICH
//EditText HAS FOCUS.
currentText = v.getTag().toString();
}
}
};
It looks like you're using a layout inflater in addition to setContentView in your activity. And affecting the edittexts referenced by the inflater. Try removing use of the inflater and rely solely on setContentView for this part of the activity. You might be performing in an incorrect view hierarchy.
I want a group of buttons where a user can choose one of them as option. It has to be a radiobuttongroup like behaviour, but I don't want the radio circle to be present. I just want the user to be able to toggle only one of the buttons.
I think I would need someting like a togglegroup.
Does something like this exist in Android?
I'd just re-use the RadioGroup like so: (please note the onClick attribute,i.e. a button click will trigger your Activity's onToggle(View) method.
<RadioGroup android:id="#+id/toggleGroup"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:orientation="horizontal"
>
<ToggleButton android:id="#+id/btn_Letter"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="1"
android:textSize="14sp"
android:textOn="Letter"
android:textOff="Letter"
android:onClick="onToggle"
android:checked="true"
/>
<ToggleButton android:id="#+id/btn_A4"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="1"
android:textSize="14sp"
android:textOn="A4"
android:textOff="A4"
android:onClick="onToggle"
/>
</RadioGroup>
In your Activity, or some place else, you can define a listener, e.g.
static final RadioGroup.OnCheckedChangeListener ToggleListener = new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(final RadioGroup radioGroup, final int i) {
for (int j = 0; j < radioGroup.getChildCount(); j++) {
final ToggleButton view = (ToggleButton) radioGroup.getChildAt(j);
view.setChecked(view.getId() == i);
}
}
};
and register it, for instance in onCreate():
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.scan_settings);
((RadioGroup) findViewById(R.id.toggleGroup)).setOnCheckedChangeListener(ToggleListener);
}
finally in onToggle(View), you would do whatever needs to happen, specific to your app. and also call the RadioGroup's check method, with the toggled view's id. Like so:
public void onToggle(View view) {
((RadioGroup)view.getParent()).check(view.getId());
// app specific stuff ..
}
You can use regular radio buttons and use an image for the RadioButton background and don't specify a text string:
<RadioButton
android:id="#+id/custom_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:button="#null"
android:background="#drawable/button_custom"
/>
For the background, use any drawable, but most likely you'll want to use a selector to be able to provide different images for the different states. The simplest version uses just two images:
<item android:state_checked="true" android:state_pressed="true"
android:drawable="#drawable/custom_selected" />
<item android:state_checked="false" android:state_pressed="true"
android:drawable="#drawable/custom_normal" />
<item android:state_checked="true" android:state_focused="true"
android:drawable="#drawable/custom_selected" />
<item android:state_checked="false" android:state_focused="true"
android:drawable="#drawable/custom_normal" />
<item android:state_checked="false" android:drawable="#drawable/custom_normal" />
<item android:state_checked="true" android:drawable="#drawable/custom_selected" />
With this, the radio button looks like a regular button (or rather, looks like whatever drawable you provided) and behaves like a radio button in a radio group.
I tried all the methods outlined above and none really worked that well.
Trying to hack a radiobutton to look like a real button looks bad.
Eventually I just took the RadioGroup source code and Modified it to accept a ToggleButton rather than a RadioButton. Works really well!
Here is the source on Github: ToggleGroup
Usage:
<com.rapsacnz.ToggleGroup
android:id="#+id/deal_detail_toolbar"
android:layout_width="fill_parent"
android:layout_height="60dip"
android:layout_alignParentBottom="true"
android:background="#drawable/bgnd_toggle_button">
<ToggleButton
android:id="#+id/b1"
android:textOn="#string/tab_1_label"
android:textOff="#string/tab_1_label"
android:textSize="10sp"
android:textColor="#color/tab_button_color"
android:checked="true"
android:layout_width="fill_parent"
android:layout_height="60dp"
android:layout_weight="1"
android:drawableTop="#drawable/toggle_spotlight"
android:drawablePadding="-5dp "
android:gravity="bottom|center"
android:paddingTop="10dp"
android:paddingBottom="5dp"
android:background="#drawable/bgnd_transparent" />
<ToggleButton
android:id="#+id/b2"
android:textOn="#string/tab_2_label"
android:textOff="#string/tab_2_label"
android:textSize="10sp"
android:textColor="#color/tab_button_color"
android:checked="false"
android:layout_width="fill_parent"
android:layout_height="60dp"
android:layout_weight="1"
android:drawableTop="#drawable/toggle_browse"
android:gravity="bottom|center"
android:paddingTop="10dp"
android:paddingBottom="5dp"
android:background="#drawable/bgnd_transparent" />
<ToggleButton
android:id="#+id/b3"
android:textOn="#string/tab_3_label"
android:textOff="#string/tab_3_label"
android:textSize="10sp"
android:textColor="#color/tab_button_color"
android:checked="false"
android:layout_width="fill_parent"
android:layout_height="60dp"
android:layout_weight="1"
android:drawableTop="#drawable/toggle_purchased"
android:gravity="bottom|center"
android:paddingTop="10dp"
android:paddingBottom="5dp"
android:background="#drawable/bgnd_transparent" />
</com.rapsacnz.ToggleGroup>
Hope this helps
Here is how I managed to do it (no RadioGroup involved):
private CompoundButton.OnCheckedChangeListener toggleListener = new CompoundButton.OnCheckedChangeListener()
{
boolean avoidRecursions = false;
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
if(avoidRecursions) return;
avoidRecursions = true;
// don't allow the un-checking
if(!isChecked)
{
buttonView.setChecked(true);
avoidRecursions = false;
return;
}
// un-check the previous checked button
if(buttonView != toggleButton1 && toggleButton1.isChecked()) toggleButton1.setChecked(false);
else if(buttonView != toggleButton2 && toggleButton2.isChecked()) toggleButton2.setChecked(false);
else if(buttonView != toggleButton3 && toggleButton3.isChecked()) toggleButton3.setChecked(false);
else if(buttonView != toggleButton4 && toggleButton4.isChecked()) toggleButton4.setChecked(false);
avoidRecursions = false;
}
};
// ...
toggleButton1.setOnCheckedChangeListener(toggleListener);
toggleButton2.setOnCheckedChangeListener(toggleListener);
toggleButton3.setOnCheckedChangeListener(toggleListener);
toggleButton4.setOnCheckedChangeListener(toggleListener);
I'm using Kotlin and I tried Wolf Paulus's answer and it didn't work well for me.
I played around with it and was able to make it work in the following way:
First, I removed the "onClick" from the xml:
<RadioGroup android:id="#+id/toggleGroup"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:orientation="horizontal"
>
<ToggleButton android:id="#+id/btn_Letter"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="1"
android:textSize="14sp"
android:textOn="Letter"
android:textOff="Letter"
android:checked="true"
/>
<ToggleButton android:id="#+id/btn_A4"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_weight="1"
android:textSize="14sp"
android:textOn="A4"
android:textOff="A4"
/>
</RadioGroup>
I didn't use the ToggleListener, instead, inside the onCreate() I listened to each of the ToggleButtons I have:
btn_Letter.setOnClickListener { it -> onToggle(it) }
btn_A4.setOnClickListener { it -> onToggle(it) }
And the most important part, the onToggle(btn: View)
private fun onToggle(btn: View) {
val radioGroup = (btn.parent as RadioGroup)
for (index in 0 until radioGroup.childCount) {
val child = radioGroup.getChildAt(index) as ToggleButton
child.isChecked = child.id == btn.id
// do what ever else you need to do
}
}
This is it. I hope this helps.
my solution achieves the same effect but without using the radiobuttons.
For the xml, first un "selector" in "#drawable/myselectorfile":
<?xml version="1.0" encoding="UTF-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false"
android:drawable="#drawable/icon_off" />
<item android:state_checked="true"
android:drawable="#drawable/icon_on" />
</selector>
un file for items of my listview:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/txtInfo"
android:layout_width="140dp"
android:layout_height="wrap_content"
android:paddingTop="15dip" />
<ToggleButton
android:id="#+id/BtnToggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="14dp"
android:background="#drawable/toggle_style"
android:padding="10dip"
android:textOff=""
android:textOn=""
android:focusable="false"/>
</LinearLayout>
and my listview :
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/lv_lista"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
in the oncreate methode:
lista.setOnItemClickListener(new OnItemClickListener() {
#SuppressWarnings("deprecation")
#Override
public void onItemClick(AdapterView<?> pariente, View view, int posicion, long id) {
#SuppressWarnings("unused")
ListEntity elegido = (ListEntity) pariente.getItemAtPosition(posicion);
varToggle = (ToggleButton) view.findViewById(R.id.BtnToggle);
varToggle.setChecked(true);
// showDialog(0); // dialog optional
//restart btn's
reStart(posicion);
}
});
in the Activity class:
#Override
protected Dialog onCreateDialog(int id){
Dialog dialogo = crearDialogoConfirmacion();
return dialogo;
}
public void reStart(int posicion){
for(int j=0;j<lista.getCount();j++)
{
View vista = lista.getChildAt(j);
ToggleButton varToggle2 = (ToggleButton) vista.findViewById(R.id.BtnToggle);
if(j != posicion){ varToggle2.setChecked(false); }
}
}
I did it with LinearLayout instead of RadioGroup, using ButterKnife:
#BindViews({R.id.one, R.id.two, R.id.three})
List<ToggleButton> toggleGroup;
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
ButterKnife.bind(this, view);
}
#OnClick({R.id.one, R.id.two, R.id.three})
public void toggle(ToggleButton selected) {
if (selected.isChecked()) {
// Deselect other buttons
for (ToggleButton button : toggleGroup) {
if (button.getId() != selected.getId()) {
button.setChecked(false);
}
}
} else {
// Disallow deselecting the current button
selected.toggle();
}
}
So you want buttons from that only one can be selected at a time?
If you don't show the radio button how does the user know what she has selected?
You can work with RadioButton and RadioGroup but I don't know if you easily can generate a custom radio button with a look more suitable to your app. But it should be possible somehow if you can extend the radiobutton itself and override the draw method, or look what kid of buttons can be integrated in a radiogroup. Maybe you can implement a special interface for your view and then join some of your custom buttons together in one radiogroup.
Using any container ViewGroup add your CompoundButtons (CheckBox, RadioButton, Switch, SwitchCompat, ToggleButton) and then inside your onCheckedChanged call a utility function to clear the other buttons.
<LinearLayout
android:id="#+id/toggle_group"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ToggleButton
android:id="#+id/toggle_btn1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textOff="Off1"
android:textOn="On1" />
<View
android:layout_width="2dp"
android:layout_height="match_parent"
android:layout_margin ="8dp"
android:background="#ffff" />
<ToggleButton
android:id="#+id/toggle_btn2"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textOff="Off2"
android:textOn="On2" />
</LinearLayout>
Inside your onCheckedChanged, deal with the state change and call the utility method to clear the other children. The following supports all view container groups which are derived from ViewGroup and allows you to mixed non-CompoundButton objects in the container. Since you often have a onCheckedChanged callback already, there only new code is to call the utility function.
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int id = buttonView.getId();
switch (id) {
case R.id.toggle_btn1:
if (isChecked) {
doBtn1Action();
doRadioGroupChange((ViewGroup)buttonView.getParent(), id);
}
break;
case R.id.toggle_btn2:
if (isChecked) {
doBtn2Action();;
doRadioGroupChange((ViewGroup)buttonView.getParent(), id);
}
break;
And here is the utility function to clear children.
/**
* Emulate radioGroup and clear buttons which don't match checkedId.
* #param viewGroup
* #param checkedId
*/
private static void doRadioGroupChange(final ViewGroup viewGroup, final int checkedId) {
for (int rgIdx = 0; rgIdx < viewGroup.getChildCount(); rgIdx++) {
View child = viewGroup.getChildAt(rgIdx);
if (child instanceof CompoundButton) {
final CompoundButton view = (CompoundButton) viewGroup.getChildAt(rgIdx);
view.setChecked(view.getId() == checkedId);
}
}
}
public void OnTabSelected(View v){
RadioGroup radioGroup = (RadioGroup)v.getParent();
for (int j = 0; j < radioGroup.getChildCount(); j++) {
ToggleButton toggleButton = (ToggleButton) radioGroup.getChildAt(j);
toggleButton.setChecked(v.getId() == toggleButton.getId());
}
}
Kotlin version:
for(index in 0..(radioGroup.childCount-1))
(radioGroup.getChildAt(index) as ToggleButton).isChecked = false