Buttons strange behavior when pressing - android

I've an Android activity that has some buttons in the bottom of it, these buttons have a one pressed and a three released as a default,
and when any of them pressed it's background supposed to change to the background of the pressed buttons and the others background supposed to change to the background of the released buttons, but when clicking any button I got that result:
this is my code:
xml:
<LinearLayout
android:id="#+id/GrandThree"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginTop="10dp"
android:layout_gravity="center"
android:gravity="center"
android:orientation="horizontal"
android:background="#android:color/transparent">
<Button
android:id="#+id/BedRoom_bottom"
android:layout_width="200dp"
android:layout_height="fill_parent"
android:background="#drawable/light_bottom_buttons_pressed"
android:text="Bedroom"
android:textSize="20dp"
android:textColor="#FFFFFF"
android:layout_gravity="center"
android:layout_marginTop="3dp"
android:layout_marginLeft="3dp"
android:layout_marginBottom="3dp"
android:layout_marginRight="3dp"
android:tag="pressed"
android:clickable="true" />
<Button
android:id="#+id/livingroom"
android:layout_width="200dp"
android:layout_height="fill_parent"
android:background="#drawable/light_bottombuttons"
android:text="Living Room"
android:layout_gravity="center"
android:textSize="20dp"
android:padding="20px"
android:textColor="#FFFFFF"
android:layout_marginTop="3dp"
android:layout_marginLeft="3dp"
android:layout_marginBottom="3dp"
android:layout_marginRight="3dp"
android:tag="released"
android:clickable="true" />
<!.. then two buttons the same way ..!>
</LinearLayout>
JAVA:
// the onClickListener method for the Navigation buttons
public OnClickListener onNavigationClick = new OnClickListener() {
#Override
public void onClick(View v) {
if(v == bedRoom){
String tag = bedRoom.getTag().toString().trim();
if (tag.equals("released")) {
bedRoom.setBackgroundColor(R.drawable.light_bottom_buttons_pressed);
bedRoom.setTag("pressed");
livingRoom.setBackgroundColor(R.drawable.light_bottombuttons);
livingRoom.setTag("released");
masterBedroom.setBackgroundColor(R.drawable.light_bottombuttons);
masterBedroom.setTag("released");
kitchen.setBackgroundColor(R.drawable.light_bottombuttons);
kitchen.setTag("released");
}
}
//then another 3 blocks the same way for the other buttons
}
};
Hint: light_bottombuttons & light_bottom_buttons_pressed are shapes with gradient colors:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="30dp"/>
<gradient
android:startColor="#353535"
android:centerColor="#212121"
android:endColor="#121212" <!.. the values of the other is just upside down these values ..!>
android:angle="270"/>
</shape>

Create a file called button-drawable.xml in your drawable folder containing this:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_selected="true"
android:#drawable/light_bottom_buttons_pressed" />
<item
android:drawable="#drawable/light_bottom_buttons_pressed" />
</selector>
Add a tag to all the buttons in the layout file.
android:background="#drawable/button_drawable"
Now, in your button's click listener set the button's selected state to true any time a new button is chosen.
Example code :
public OnClickListener onNavigationClick = new OnClickListener() {
#Override
public void onClick(View v) {
if(v == bedRoom){
String tag = bedRoom.getTag().toString().trim();
if (tag.equals("released")) {
bedRoom.setTag("pressed");
bedRoom.setSelected(true);
livingRoom.setTag("released");
livingRoom.setSelected(false);
masterBedroom.setTag("released");
masterBedroom.setSelected(false);
kitchen.setTag("released");
kitchen.setSelected(false);
}
}
//then another 3 blocks the same way for the other buttons
}
};

Use radio group and radio button for this.
Your radio group will contain multiple buttons and at a time only one can be selected.

When you get your drawable you should do it like the following
bedRoom.setBackgroundColor(MyActivity.this.getResources().getDrawable(R.drawable.light_bottom_buttons_pressed));
MyActivity Would change to be whatever your activity name is

Related

Changing color of buttons with onclick events

I'm trying to create a Grid with 100 buttons, and a custom color selector. When i click a random button, it should change its' background into the selected color. Unfortunately I'm stuck on the following:
MainActivity:
I'm not sure how to automate the onclick event for every button seperately, as the onclick function doesn't recognise which button is clicked in the inner class.
I'm using a gridview with a custom adapter:
Adapter:
The adapter implemented in my Gridview --> linearlayout.pixel is the xml file for my button.
Code linearlayout.pixel:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:background="#drawable/my_button"
android:id="#+id/grid_button"
/>
code drawable my_button:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="3dp" />
<stroke android:width="5px" android:color="#000000" />
Any suggestions are welcome!
Try this:
Button button = (Button)findViewById(R.id.grid_button);
button.setOnClickListener(new View.OnclickListener()
{
#Override
public void onClick(View view){
button.setBackgroundColor("#4FC3F7");
}
};
Try this:
buttons[i]=new Button(this);
buttons.setId(i);
buttons[i].setOnClickListener(new View.OnclickListener()
{
#Override
public void onClick(View view){
buttons[view.getId()].setBackgroundColor(color);
}
};

How to define color for selected TextViews once in Android?

I have a ListView and created a xml file for ListView items.
<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
android:background="#drawable/list_item_selector_back"
android:minHeight="?attr/listPreferredItemHeight"
android:orientation="vertical">
<CheckedTextView
android:id="#+id/list_item_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:textColor="#color/list_item_selector_fore" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="#+id/list_item_author"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/list_item_selector_fore" />
<!-- and many more TextView elements -->
</LinearLayout>
</LinearLayout>
list_item_selector_fore.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#android:color/white" android:state_pressed="true" />
<item android:color="#android:color/white" android:state_activated="true" />
<item android:color="#android:color/white" android:state_focused="true" />
<item android:color="#android:color/black" />
</selector>
As you can see, I defined the background once in the root LinearLayout. But I had to set android:textColor="#color/list_item_selector_fore" for every TextView.
I tried it with foreground, but nothing happened. How can I get this smarter?
HOW TO LOOK:
two list view items
If you want do it for all TextView, the best way should be to subclass TextView
public class CustomeTextView extends TextView{
public CustomeTextView(Context context) {
super(context);
this.setTextColor(R.color.white);
}
}
If I understand the question correctly you want to change the colour of the text inside a TextView. From your XML it seems you want it to be onClick therefore you can do this:
TextView textView = (TextView) findViewById(R.id.myTextView);
textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
textView.setTextColor('set text color here');
}
});
EDIT:
If you have these items inside of a ListView I would suggest that the easiest way for you to achieve what you want is to set an OnItemClickListenerand then change the textColor based on the OnItemClick event, which may look something like this;
ListView listView = (ListView) findViewById(R.id.listView);
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView textView = (TextView) view.findViewById(R.id.rowItemTextView);
textView.setTextColor('color goes here');
}
});
Hopefully this short snippet will guide you in the right direction to go.

Android Dialog - Rounded Corners and Transparency

I'm trying to make a custom android dialog with rounded corners. My current attempts have given me this result.
As you can see, the corners are rounded, but it leaves the white corner still intact.
Below is the xml that I put in the drawable folder to create the blue dialog with the red border with the rounded corners.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:shape="rectangle">
<solid android:color="#color/transparent_black" />
<corners android:radius="#dimen/border_radius"/>
</shape>
</item>
<item
android:left="#dimen/border_width"
android:right="#dimen/border_width"
android:top="#dimen/border_width"
android:bottom="#dimen/border_width" >
<shape android:shape="rectangle">
<solid android:color="#color/blue" />
<corners android:radius="#dimen/border_radius"/>
</shape>
</item>
</layer-list>
Below is the layout of the dialog.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="#style/fill"
android:orientation="vertical"
android:layout_margin="#dimen/spacing_normal"
android:padding="#dimen/spacing_normal"
android:background="#drawable/border_error_dialog" >
<RelativeLayout
style="#style/block"
android:layout_gravity="center" >
<ImageView
android:id="#+id/imageView1"
style="#style/wrap"
android:layout_alignParentLeft="true"
android:layout_centerHorizontal="true"
android:contentDescription="#string/content_description_filler"
android:src="#drawable/ic_launcher" />
<TextView
android:id="#+id/textView1"
style="#style/error_text"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/imageView1"
android:text="#string/error_login" />
</RelativeLayout>
<Button
android:id="#+id/button1"
style="#style/wrap"
android:layout_gravity="center"
android:text="Button" />
</LinearLayout>
And below is the Activity in which I create the dialog.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button b1 = (Button) findViewById(R.id.button1);
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(MainActivity.this);
View child = getLayoutInflater().inflate(R.layout.dialog_custom_tom, null);
alertDialogBuilder.setView(child);
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
});
}
The only solution I have found is here. Use Dialog instead of AlertDialog and set transparent background:
dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
Therefore you can't use the builder. But you can use new Dialog() also in onCreateDialog callback of DialogFragment if you follow to best guidelines.
This works also for Gingerbread.
Besides the layered drawable can be simplified to one shape with xml element <stroke> for the border.
I had similar issue when made dialog extending DialogFragment and to fix this used:
dialog.setStyle(DialogFragment.STYLE_NO_FRAME, 0);
Like this:
public class ConfirmBDialog extends DialogFragment {
public static ConfirmBDialog newInstance() {
ConfirmBDialog dialog = new ConfirmBDialog();
Bundle bundle = new Bundle();
dialog.setArguments(bundle);
return dialog;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// This removes black background below corners.
setStyle(DialogFragment.STYLE_NO_FRAME, 0);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.confirm_dialog, container, true);
getDialog().setCanceledOnTouchOutside(true);
return view;
}
Hope this helps.
Just try
myDialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
The below code solved the issue
MyDialog mydialog = new MyDialog(this, "for testing",
new myOnClickListener() {
#Override
public void onPositiveButtonClick() {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(),
"I am positive button in the dialog",
Toast.LENGTH_LONG).show();
}
#Override
public void onNegativeButtonClick() {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(),
"I am negative button in the dialog",
Toast.LENGTH_LONG).show();
}
});
// this will remove rectangle frame around the Dialog
mydialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
mydialog.show();
Thanks,
Nagendra
In you java file keep below code and change your layout name
View mView =LayoutInflater.from(mContext).inflate(R.layout.layout_pob,null);
alertDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
just try using this, this worked for me
dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
Use 9-patch PNG with transparency in those corners.
public void initDialog() {
exitDialog = new Dialog(this);
exitDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
View view = View.inflate(this, R.layout.dialoglayout, null);
exitDialog.setContentView(view);
AdSize adSize = new AdSize(300, 250);
dialogAdview = new AdView(this);
dialogAdview.setAdUnitId(getResources().getString(R.string.banner_id));
dialogAdview.setAdSize(adSize);
RelativeLayout adLayout = (RelativeLayout) view.findViewById(R.id.adLayout);
adLayout.addView(dialogAdview);
AdRequest adRequest = new AdRequest.Builder()
.build();
dialogAdview.loadAd(adRequest);
dialogAdview.setAdListener(new AdListener() {
#Override
public void onAdLoaded() {
Log.d("Tag", "adLoaded");
super.onAdLoaded();
}
});
view.findViewById(R.id.yes_btn).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
exit = true;
onBackPressed();
}
});
view.findViewById(R.id.no_btn).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
exit = false;
exitDialog.dismiss();
}
});
}
dialoglayout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/custom_dialog_round"
android:orientation="vertical">
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:text="Do you want to exit?"
android:textColor="#000"
android:textSize="18dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/text"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:id="#+id/yes_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/background_draw"
android:padding="8dp"
android:text="Yes"
android:textAlignment="center"
android:textColor="#9fa8da"
android:textSize="20dp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:id="#+id/no_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:background="#drawable/background_draw"
android:padding="8dp"
android:text="No"
android:textAlignment="center"
android:textColor="#d50000"
android:textSize="20dp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
`
custom_dialog_round.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="#fff"/>
<corners
android:radius="10dp" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
</shape>
reference http://techamongus.blogspot.com/2018/02/android-create-round-corner-dialog.html
UPDATE
I understood that activity's background makes sense. So use #robert's answer with these changes.
in DialogFragment layout set width and height or add minimum sizes:
<LinearLayout 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"
android:layout_width="wrap_content" // Or match_parent, 300dp.
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:background="#drawable/white_round_corner_background"
android:gravity="center"
android:minWidth="300dp"
android:minHeight="200dp"
android:orientation="vertical"
android:padding="15dp"
>
...
Remove <item name="android:background">#color/...</item> from styles of needed activities and set these backgrounds in activity's layouts.
In DialogFragment write:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// This removes black background below corners.
setStyle(DialogFragment.STYLE_NO_FRAME, 0);
}
Old variant
According to robert answer, you should apply setStyle(STYLE_NO_FRAME, 0), but there appear new problems. If you have a narrow DialogFragment like in Custom dialog too small, then you should follow this guide.
Add to styles.xml these 3 lines for dialog size:
<style name="ErrorDialogTheme" parent="#android:style/Theme.Dialog">
<item name="android:minWidth" type="dimen">300dp</item>
<!-- This option makes dialog fullscreen and adds black background, so I commented it -->
<!-- <item name="android:minHeight" type="dimen">200dp</item> -->
<!-- This option doesn't work, so I commented it -->
<!-- <item name="android:layout_width">match_parent</item> -->
</style>
In layout of your DialogFragment add style:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
android:minWidth="300dp" // Optional, remove this line.
android:minHeight="200dp" // Optional, remove this line.
style="#style/ErrorDialogTheme"
android:theme="#style/ErrorDialogTheme"
>
In code of your DialogFragment write:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// This removes black background. If not 0 as a parameter, black background will appear.
setStyle(STYLE_NO_FRAME, 0)
}
// If you want a fullscreen dialog, use this, but it doesn't remove a black background.
override fun onStart() {
super.onStart()
dialog.window?.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT)
}
Look at AndroidManifest.xml and find all activities that can show these dialogs, check android:theme="..." themes and go to styles.xml. Now take a look at <item name="android:background">#color/...</item> items of these themes. There should be a transparent color or these items might not exist. If you have these background items, whole activities will have those backgrounds and dialogs too! So, if you have a camera activity with DialogFragment above it, you will see this.
Remove background items of needed styles. Also maybe background is set in code, check it.
In Dialog with transparent background in Android and many pages it is written to add one of these:
dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(0));
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
probably in onViewCreated() or onCreateDialog(), but it didn't help me, because the background of the Activity was set in styles.
Tested on Samsung Galaxy S4 running Android 5.0.1.
Use CardView and make
app:cardCornerRadius="dp"
According shape xml.
I will post my solution here because it may be helpful. The solution that worked for me was to set the drawable resource in the layout xml and also in the activity that starts the dialog, without switching from AlertDialog to Dialog.
This would mean that in the layout where we create our design for the dialog alert_dialog_design.xml we will have the property android:background filled with our own defined background alert_dialog_shape.xml:
android:background="#drawable/alert_dialog_shape"
But also inside the activity that starts the dialog:
alert.getWindow().setBackgroundDrawableResource(R.drawable.alert_dialog_shape);
This way the parent (the alert itself) of your custom layout will have the shape you desire. Using this method I achieved the following:
https://i.stack.imgur.com/drCw3.png

How to make the drawableLeft of a Android Button keep rotating?

I need to create a button where there is a icon in the left and a text in the right. After pressing the button, I want to see there is an animation of rotating image at the place of the left icon in the button.
I know how to rotate a image with ImageView, but it is not helpful to my current requirement.
I tried to use AnimationDrawable, but it did not work either, there is no animation but only the first png file shown. It is then same whatever I use the background or leftDrawable of the button to run the AnimationDrawable. The code is as below:
package com.example.layout;
import android.app.Activity;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.widget.Button;
public class TestLinearlayoutActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
#Override
public void onStart() {
super.onStart();
Button locationTitleButton = (Button) findViewById(R.id.LocationTitleButton);
//locationTitleButton.setBackgroundResource(R.drawable.loading);
locationTitleButton.setCompoundDrawablesWithIntrinsicBounds(R.drawable.loading, 0, 0, 0);
Drawable[] locationTitleButtonDrawables = locationTitleButton.getCompoundDrawables();
AnimationDrawable animDrawable = (AnimationDrawable) locationTitleButtonDrawables[0];
//AnimationDrawable animDrawable = (AnimationDrawable) locationTitleButton.getBackground();
animDrawable.start();
}
}
//loading.xml:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="#drawable/loc1" android:duration="200" />
<item android:drawable="#drawable/loc2" android:duration="200" />
<item android:drawable="#drawable/loc3" android:duration="200" />
<item android:drawable="#drawable/loc4" android:duration="200" />
</animation-list>
// layout file, main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:orientation="horizontal" android:padding="0dp"
android:layout_height="wrap_content" android:gravity="fill_horizontal" android:layout_margin="0dp">
<Button android:id="#+id/LocationTitleButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="0dip"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:layout_weight="1"
android:ellipsize="end"
android:scrollHorizontally="true"
android:singleLine="true"
android:text="Add location"
android:textStyle="bold" />
<Button android:textColor="#FF000000"
android:layout_weight="0"
android:id="#+id/AddLocationButton"
android:text="Search"
android:gravity="center_vertical"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="-8dp" />
</LinearLayout>
You can try using an AnimationDrawable.
I have also face this issue and I have tried all above solution but no one have worked for me. I have found solution here. Android document says that don't call start() in the onCreate(Bundle) method of activity call it in onWindowFocusChanged(boolean) function. So I do it like this :
#Override
public void onWindowFocusChanged(boolean hasFocus){
if(hasFocus){
final AnimationDrawable d=(AnimationDrawable) mBtnView.getCompoundDrawables()[0];
d.start();
}
}
Use a LinearLayout (orientation horizontal). Treat that as your button by giving it a button drawable selector as it's background drawable. Inside it, put an ImageView and a TextView. Use an OnClickListner on the LinearLayout, as if it were a button. Then animate the ImageView.

Android: How to get a radiogroup with togglebuttons?

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

Categories

Resources