I'm getting a view from the XML with the code below:
Button view = (Button) LayoutInflater.from(this).inflate(R.layout.section_button, null);
I would like to set a "style" for the button how can I do that in java since a want to use several style for each button I will use.
First of all, you don't need to use a layout inflater to create a simple Button. You can just use:
button = new Button(context);
If you want to style the button you have 2 choices: the simplest one is to just specify all the elements in code, like many of the other answers suggest:
button.setTextColor(Color.RED);
button.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
The other option is to define the style in XML, and apply it to the button. In the general case, you can use a ContextThemeWrapper for this:
ContextThemeWrapper newContext = new ContextThemeWrapper(baseContext, R.style.MyStyle);
button = new Button(newContext);
To change the text-related attributes on a TextView (or its subclasses like Button) there is a special method:
button.setTextAppearance(R.style.MyTextStyle);
Or, if you need to support devices pre API-23 (Android 6.0)
button.setTextAppearance(context, R.style.MyTextStyle);
This method cannot be used to change all attributes; for example to change padding you need to use a ContextThemeWrapper. But for text color, size, etc. you can use setTextAppearance.
Generally you can't change styles programmatically; you can set the look of a screen, or part of a layout, or individual button in your XML layout using themes or styles. Themes can, however, be applied programmatically.
There is also such a thing as a StateListDrawable which lets you define different drawables for each state the your Button can be in, whether focused, selected, pressed, disabled and so on.
For example, to get your button to change colour when it's pressed, you could define an XML file called res/drawable/my_button.xml directory like this:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:drawable="#drawable/btn_pressed" />
<item
android:state_pressed="false"
android:drawable="#drawable/btn_normal" />
</selector>
You can then apply this selector to a Button by setting the property android:background="#drawable/my_button".
Yes, you can use for example in a button
Button b = new Button(this);
b.setBackgroundResource(R.drawable.selector_test);
You can do style attributes like so:
Button myButton = new Button(this, null,android.R.attr.buttonBarButtonStyle);
in place of:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn"
style="?android:attr/buttonBarButtonStyle"
/>
If you are using the Support library, you could simply use
TextViewCompat.setTextAppearance(textView, R.style.AppTheme_TextStyle_ButtonDefault_Whatever);
for TextViews and Buttons. There are similar classes for the rest of Views :-)
Depending on what style attributes you'd like to change you may be able to use the Paris library:
Button view = (Button) LayoutInflater.from(this).inflate(R.layout.section_button, null);
Paris.style(view).apply(R.style.YourStyle);
Many attributes like background, padding, textSize, textColor, etc. are supported.
List of currently supported attributes
Installation instructions
Disclaimer: I authored the library.
The answer by #Dayerman and #h_rules is right.
To give an elaborated example with code,
In drawable folder, create an xml file called button_disabled.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" android:padding="10dp">
<solid android:color="#color/silver"/>
<corners
android:bottomRightRadius="20dp"
android:bottomLeftRadius="20dp"
android:topLeftRadius="20dp"
android:topRightRadius="20dp"/>
</shape>
Then in Java,
((Button) findViewById(R.id.my_button)).setEnabled(false);
((Button) findViewById(R.id.my_button)).setBackgroundResource(R.drawable.button_disabled);
This will set the button's property to disabled and sets the color to silver.
[The color is defined in color.xml as:
<resources>
<color name="silver">#C0C0C0</color>
</resources>
For anyone looking for a Material answer see this SO post: Coloring Buttons in Android with Material Design and AppCompat
I used a combination of this answer to set the default text color of the button to white for my button:
https://stackoverflow.com/a/32238489/3075340
Then this answer https://stackoverflow.com/a/34355919/3075340 to programmatically set the background color. The code for that is:
ViewCompat.setBackgroundTintList(your_colored_button,
ContextCompat.getColorStateList(getContext(),R.color.your_custom_color));
your_colored_button can be just a regular Button or a AppCompat button if you wish - I tested the above code with both types of buttons and it works.
EDIT: I found that pre-lollipop devices do not work with the above code. See this post on how to add support for pre-lollipop devices: https://stackoverflow.com/a/30277424/3075340
Basically do this:
Button b = (Button) findViewById(R.id.button);
ColorStateList c = ContextCompat.getColorStateList(mContext, R.color.your_custom_color;
Drawable d = b.getBackground();
if (b instanceof AppCompatButton) {
// appcompat button replaces tint of its drawable background
((AppCompatButton)b).setSupportBackgroundTintList(c);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// Lollipop button replaces tint of its drawable background
// however it is not equal to d.setTintList(c)
b.setBackgroundTintList(c);
} else {
// this should only happen if
// * manually creating a Button instead of AppCompatButton
// * LayoutInflater did not translate a Button to AppCompatButton
d = DrawableCompat.wrap(d);
DrawableCompat.setTintList(d, c);
b.setBackgroundDrawable(d);
}
At runtime, you know what style you want your button to have. So beforehand, in xml in the layout folder, you can have all ready to go buttons with the styles you need. So in the layout folder, you might have a file named: button_style_1.xml. The contents of that file might look like:
<?xml version="1.0" encoding="utf-8"?>
<Button
android:id="#+id/styleOneButton"
style="#style/FirstStyle" />
If you are working with fragments, then in onCreateView you inflate that button, like:
Button firstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);
where container is the ViewGroup container associated with the onCreateView method you override when creating your fragment.
Need two more such buttons? You create them like this:
Button secondFirstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);
Button thirdFirstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);
You can customize those buttons:
secondFirstStyleBtn.setText("My Second");
thirdFirstStyleBtn.setText("My Third");
Then you add your customized, stylized buttons to the layout container you also inflated in the onCreateView method:
_stylizedButtonsContainer = (LinearLayout) rootView.findViewById(R.id.stylizedButtonsContainer);
_stylizedButtonsContainer.addView(firstStyleBtn);
_stylizedButtonsContainer.addView(secondFirstStyleBtn);
_stylizedButtonsContainer.addView(thirdFirstStyleBtn);
And that's how you can dynamically work with stylized buttons.
I made a helper interface for this using the holder pattern.
public interface StyleHolder<V extends View> {
void applyStyle(V view);
}
Now for every style you want to use pragmatically just implement the interface, for example:
public class ButtonStyleHolder implements StyleHolder<Button> {
private final Drawable background;
private final ColorStateList textColor;
private final int textSize;
public ButtonStyleHolder(Context context) {
TypedArray ta = context.obtainStyledAttributes(R.style.button, R.styleable.ButtonStyleHolder);
Resources resources = context.getResources();
background = ta.getDrawable(ta.getIndex(R.styleable.ButtonStyleHolder_android_background));
textColor = ta.getColorStateList(ta.getIndex(R.styleable.ButtonStyleHolder_android_textColor));
textSize = ta.getDimensionPixelSize(
ta.getIndex(R.styleable.ButtonStyleHolder_android_textSize),
resources.getDimensionPixelSize(R.dimen.standard_text_size)
);
// Don't forget to recycle!
ta.recycle();
}
#Override
public void applyStyle(Button btn) {
btn.setBackground(background);
btn.setTextColor(textColor);
btn.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
}
}
Declare a stylable in your attrs.xml, the styleable for this example is:
<declare-styleable name="ButtonStyleHolder">
<attr name="android:background" />
<attr name="android:textSize" />
<attr name="android:textColor" />
</declare-styleable>
Here is the style declared in styles.xml:
<style name="button">
<item name="android:background">#drawable/button</item>
<item name="android:textColor">#color/light_text_color</item>
<item name="android:textSize">#dimen/standard_text_size</item>
</style>
And finally the implementation of the style holder:
Button btn = new Button(context);
StyleHolder<Button> styleHolder = new ButtonStyleHolder(context);
styleHolder.applyStyle(btn);
I found this very helpful as it can be easily reused and keeps the code clean and verbose, i would recommend using this only as a local variable so we can allow the garbage collector to do its job once we're done with setting all the styles.
I faced the same problem recently. here is how i solved it.
<?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">
<!-- This is the special two colors background START , after this LinearLayout, you can add all view that have it for main background-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="2"
android:background="#FFFFFF"
android:orientation="horizontal"
>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#0000FF" />
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#F000F0" />
</LinearLayout>
<!-- This is the special two colors background END-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:text="This Text is centered with a special backgound,
You can add as much elements as you want as child of this RelativeLayout"
android:textColor="#FFFFFF"
android:textSize="20sp" />
</RelativeLayout>
I used a LinearLayout with android:weightSum="2"
I gave to the two child elements android:layout_weight="1"
(I gave each 50% of the parent space(width & height))
And finally, i gave the two child element different background colors to have the final effect.
Thanks !
Related
I have an ImageButton with a transparent image in it. I changed the background color of the ImageButton.
When an ImageButton that has the default color is pressed the button shows that it has been pressed by "glowing" for a very short time. But when the background color is changed the "glow" effect doesn't show. The different behavior doesn't have to do with the image, because the "glow" effect is shown when the button has the standard "grayish" color.
How could I have the "glow" effect in a colored Imagebutton?
P.S. I am aware of how to change the color of the ImageButton on a click event. But I want to have the same effect with the default grey-colored ImageButton.
The same thing (glowing not shows) happen also with the Button object.
You can use this library
RippleView
You can use ColorStateList to define your button's pressed color.
You should review the documentation I linked above for details. Here's a quick example from the doc, which covers the basics:
XML file saved at res/color/button_text.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:color="#ffff0000"/> <!-- pressed -->
<item android:state_focused="true"
android:color="#ff0000ff"/> <!-- focused -->
<item android:color="#ff000000"/> <!-- default -->
</selector>
This layout XML will apply the color list to a View:
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/button_text"
android:textColor="#color/button_text" />
In your case, you'll want to set android:background to point to your new XML resource, instead of android:textColor.
Hope that helps.
The android have the glow effect as a transparent background resource, so I solved the problem by putting a colored view behind the button and setting the button background to the transparent glow effect.
For example in my xml like:
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#color/custom_color"
android:orientation="vertical">
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
and in my onCreate:
TypedValue outValue = new TypedValue();
getContext().getTheme().resolveAttribute(R.attr.selectableItemBackground, outValue, true);
Button mButton = (Button) findViewById(R.id.button);
mButton.setBackgroundResource(outValue.resourceId);
Its working only, if you have just one buttons in your LinearLayout, if you want to put there something else you can use a view inside a RelativeLayout with the same parameters as your button.
Tell me if you have any other questions!
I have a static layout file, let's say something like :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="24dp"
android:src="#drawable/some_drawable" />
<TextView
android:id="#id/placeholder_error_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="something"
/>
</LinearLayout>
I would like to be able to reuse this layout file multiple times throughout my application but change the text & src attributes according to each usecase.
I don't want to duplicate the layout files and a custom View for this seems overkill. Is there a solution in the framework for this ?
I would abandon the LinearLayout concept – you can go easily with the TextView only.
Move all global attributes to style
<style name="TextWithImage">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">match_parent</item>
<item name="android:drawablePadding">24dp</item>
</style>
And in your layouts use this TextView with overriden text and drawable
<TextView
style="#style/TextWithImage"
android:drawableTop="#drawable/some_drawable"
android:text="something" />
This does not have any disadvantages over <include> AFAIK. The only issue is you dont have full control over the image size, but if your drawables have 56dp (and they should) you are completely fine.
I assume you are inflating this layout in your Activity's onCreate(). You will need to get a reference to the ImageView and TextView in your code after the layout is inflated, and then you can call methods on them.
First, add an id to the ImageView: android:id="#+id/image.
Then, in your Java code:
#Override
public void onCreate(Bundle savedInstanceState) {
// inflate the layout
setContentView(R.layout.your_layout);
// get references
ImageView imageView = (ImageView) findViewById(R.id.image);
TextView textView = (TextView) findViewById(R.id.placeholder_error_info);
// set properties
imageView.setImageResource(R.drawable.some_drawable);
textView.setText("something");
}
You can replace the calls to setImageResource and setText with anything you like. Good luck!
In my code, I add input elements like radioButtons, checkboxes etc to my Layout programmatically.
The problem is, that the style of those elements is not the default style that you would get, when you would add let's say a radioButton via xml. (It looks really white and almost see-through on a white application background. A bit like it is transparent)
Also, the EditText elements I'm adding have the same style and if you type something in them, the text is too big and overlaps the text line a bit.
So I guess it all comes down to somehow giving those elements their default style, like they look when defined via xml.
A sample of my code looks like this:
RadioGroup radioGroup = new RadioGroup(mContext);
radioGroup.setLayoutParams(fullWidthWrapHeight);
for (int i = 0; i < arg0.getOptions().size(); i++){
RadioButton radioButton = new RadioButton(mContext, null);
radioButton.setPadding(padding16dp , padding8dp, padding16dp, padding8dp);
radioButton.setText(arg0.getOptions().get(i).getText());
radioButton.setLayoutParams(wrapBoth);
radioButton.setGravity(Gravity.CENTER_HORIZONTAL);
radioButton.setTextAppearance(mContext, R.style.Default_Text);
radioGroup.addView(radioButton);
}
My target API lvl is 21 (Lollipop)
You can pass a style defined inside styles.xml as an argument of a View constructor. So considering your example, you would have to call:
RadioButton radioButton = new RadioButton(mContext, null, R.attr.radioButtonStyle);
then add custom attribute inside attrs.xml
<attr name="radioButtonStyle" format="reference" />
and inside your application theme in styles.xml add
<item name="radioButtonStyle">#style/YourRadioButtonStyle</item>
YourRadioButtonStyle is custom radio button style defined in styles.xml
As for me, it has been successfully solved just by that way:
Activity.java
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
...
{
RadioButton rb = (RadioButton) inflater.inflate(R.layout.radio_butt, null);
rb.setText(this_currency_option);
rb.setTextColor(context.getResources().getColor(R.color.colorWhite));
rb.setId(100 + i);
radioGroup.addView(rb);
}
radio_butt.xml
<?xml version="1.0" encoding="utf-8"?>
<RadioButton
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textColor="#color/colorWhite"
android:theme="#style/MyRadioButtonStyle"/>
slyles.xml
<style name="MyRadioButtonStyle" parent="#android:style/Widget.CompoundButton.RadioButton">
<item name="colorControlNormal">#color/colorAlfaWhite</item>
<item name="colorControlActivated">#color/colorWhite</item>
</style>
I need a UI element that will allow the user to expand/collapse (show/hide) a view that contains optional/advanced information.
I envision this as a text label (e.g. 'advanced options', 'more/less') plus an icon that toggles between open and close. I've got some icons that could serve the purpose, and the functionality of the element closely matches that of a ToggleButton, so I attempted to solve this problem with a styled ToggleButton.
This solution turned out to be super ugly (from the maintenance perspective). I'll add it as an answer below.
I'm hoping someone could suggest a better solution, or point out how my solution could be simplified.
BTW, animating the expanding/collapsing of the view is addressed well in this SO Q/A.
Thankfully, I've found a much simpler way.
Instead of using a ToggleButton (which involved 11 resource files to style it) I'm just using a TextView with a CompoundDrawable, and then managing the state myself.
This way involves a little more code, but saves a huge mess of resource files. It also makes it easier to handle multiple themes, e.g. here I set the resource ID's for the needed icons depending on the theme:
final MainActivity ma = (MainActivity) getActivity();
if (ma.isDarkTheme()) {
icon_expand = getResources().getIdentifier( "ic_action_expand","drawable", ma.getPackageName() );
icon_collapse = getResources().getIdentifier( "ic_action_collapse","drawable", ma.getPackageName() );
} else {
icon_expand = getResources().getIdentifier( "ic_action_expand_light","drawable", ma.getPackageName() );
icon_collapse = getResources().getIdentifier( "ic_action_collapse_light","drawable", ma.getPackageName() );
}
I do this in my fragment's onCreate. It is unfortunate that I have to resolve the icon ID's at runtime, but that seems to be how it is done.
I have no idea why my icons are displayed at normal size in this case and at double size when I specified them as a layer of the background of the ToggleButton (which necessitating ScaledDrawable resources for all of my icons).
Here is my onClickListener (for the TextView):
protected OnClickListener expandCtrlListener = new OnClickListener() {
public void onClick(View v) {
assertTrue( v == expandCtrl );
isExpanded = !isExpanded;
advancedView.setVisibility( isExpanded ? View.VISIBLE : View.GONE );
expandCtrl.setCompoundDrawablesWithIntrinsicBounds( isExpanded ? icon_collapse : icon_expand, 0, 0, 0 );
}
};
Note that none of this shows the animation of the expand/collapse. That is addressed in the article I mention at the end of the question.
As I wrote in the question, the functionality of the button closely matches ToggleButton so I started with a layout that shows a styled ToggleButton next to some text:
<RelativeLayout
android:id="#+id/expandLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="12dp" >
<ToggleButton
android:id="#+id/expcollButton"
style="#style/expCollToggleBtn"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="false"/>
<TextView
android:id="#+id/expandText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="8dp"
android:layout_toRightOf="#id/expcollButton"
android:text="Show Options" />
</RelativeLayout>
The style (in styles.xml file) looks like this. This nulls out the button text and points to the background drawable.
<style name="expCollToggleBtn">
<item name="android:background">#drawable/expcoll_btn_toggle_bg_light</item>
<item name="android:textOn"></item>
<item name="android:textOff"></item>
<item name="android:disabledAlpha">?android:attr/disabledAlpha</item>
</style>
The background drawable is a layer-list xml file that points to another drawable (perhaps there is some way to get rid of this file and just point directly to the selector below?)
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+android:id/background" android:drawable="#android:color/transparent" />
<item android:id="#+android:id/toggle" android:drawable="#drawable/expcoll_btn_toggle" />
</layer-list>
The selector lists the images for open/closed:
<?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/ic_action_expand" />
<item android:state_checked="true" android:drawable="#drawable/ic_action_collapse" />
</selector>
Now, the first complication is that this results in a very oversized button/image. I've provided suitable images for all pixel densities, so I'm not sure why this is happening, but the solution is to scale the images.
Unfortunately, this seems to require a ScaledDrawable for every image. I actually have four images because I foolishly decided to support light and dark themes in my app. So I need four of these.
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="#drawable/ic_action_expand"
android:scaleGravity="center"
android:scaleHeight="50%"
android:scaleWidth="50%"
/>
Also, note that there is a bug in ScaledDrawables, described here, so that needs to be accounted for.
And finally, since I'm trying to support two themes I need multiple copies of the selector and the layer-list files too, and need to add attributes to the attrs.xml file. At this point, I've got 11 XML files involved (plus the 10 image files for all the densities) all for a pretty ordinary button.
This can't be right!
A simple Expand Collapse Code
//show/hide boxes panel
var expansion: Boolean = false
expand_up.setOnClickListener {
if (!expansion) {
expand_up.setImageResource(R.drawable.collapse)
boxes_panel.visibility = View.VISIBLE
expansion = true
}
else{
expand_up.setImageResource(R.drawable.expand)
boxes_panel.visibility = View.GONE
expansion = false
}
}
There is a library for this.
It is called SAExpandableButton, you can find it here
I'm getting a view from the XML with the code below:
Button view = (Button) LayoutInflater.from(this).inflate(R.layout.section_button, null);
I would like to set a "style" for the button how can I do that in java since a want to use several style for each button I will use.
First of all, you don't need to use a layout inflater to create a simple Button. You can just use:
button = new Button(context);
If you want to style the button you have 2 choices: the simplest one is to just specify all the elements in code, like many of the other answers suggest:
button.setTextColor(Color.RED);
button.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
The other option is to define the style in XML, and apply it to the button. In the general case, you can use a ContextThemeWrapper for this:
ContextThemeWrapper newContext = new ContextThemeWrapper(baseContext, R.style.MyStyle);
button = new Button(newContext);
To change the text-related attributes on a TextView (or its subclasses like Button) there is a special method:
button.setTextAppearance(R.style.MyTextStyle);
Or, if you need to support devices pre API-23 (Android 6.0)
button.setTextAppearance(context, R.style.MyTextStyle);
This method cannot be used to change all attributes; for example to change padding you need to use a ContextThemeWrapper. But for text color, size, etc. you can use setTextAppearance.
Generally you can't change styles programmatically; you can set the look of a screen, or part of a layout, or individual button in your XML layout using themes or styles. Themes can, however, be applied programmatically.
There is also such a thing as a StateListDrawable which lets you define different drawables for each state the your Button can be in, whether focused, selected, pressed, disabled and so on.
For example, to get your button to change colour when it's pressed, you could define an XML file called res/drawable/my_button.xml directory like this:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:drawable="#drawable/btn_pressed" />
<item
android:state_pressed="false"
android:drawable="#drawable/btn_normal" />
</selector>
You can then apply this selector to a Button by setting the property android:background="#drawable/my_button".
Yes, you can use for example in a button
Button b = new Button(this);
b.setBackgroundResource(R.drawable.selector_test);
You can do style attributes like so:
Button myButton = new Button(this, null,android.R.attr.buttonBarButtonStyle);
in place of:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btn"
style="?android:attr/buttonBarButtonStyle"
/>
If you are using the Support library, you could simply use
TextViewCompat.setTextAppearance(textView, R.style.AppTheme_TextStyle_ButtonDefault_Whatever);
for TextViews and Buttons. There are similar classes for the rest of Views :-)
Depending on what style attributes you'd like to change you may be able to use the Paris library:
Button view = (Button) LayoutInflater.from(this).inflate(R.layout.section_button, null);
Paris.style(view).apply(R.style.YourStyle);
Many attributes like background, padding, textSize, textColor, etc. are supported.
List of currently supported attributes
Installation instructions
Disclaimer: I authored the library.
The answer by #Dayerman and #h_rules is right.
To give an elaborated example with code,
In drawable folder, create an xml file called button_disabled.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" android:padding="10dp">
<solid android:color="#color/silver"/>
<corners
android:bottomRightRadius="20dp"
android:bottomLeftRadius="20dp"
android:topLeftRadius="20dp"
android:topRightRadius="20dp"/>
</shape>
Then in Java,
((Button) findViewById(R.id.my_button)).setEnabled(false);
((Button) findViewById(R.id.my_button)).setBackgroundResource(R.drawable.button_disabled);
This will set the button's property to disabled and sets the color to silver.
[The color is defined in color.xml as:
<resources>
<color name="silver">#C0C0C0</color>
</resources>
For anyone looking for a Material answer see this SO post: Coloring Buttons in Android with Material Design and AppCompat
I used a combination of this answer to set the default text color of the button to white for my button:
https://stackoverflow.com/a/32238489/3075340
Then this answer https://stackoverflow.com/a/34355919/3075340 to programmatically set the background color. The code for that is:
ViewCompat.setBackgroundTintList(your_colored_button,
ContextCompat.getColorStateList(getContext(),R.color.your_custom_color));
your_colored_button can be just a regular Button or a AppCompat button if you wish - I tested the above code with both types of buttons and it works.
EDIT: I found that pre-lollipop devices do not work with the above code. See this post on how to add support for pre-lollipop devices: https://stackoverflow.com/a/30277424/3075340
Basically do this:
Button b = (Button) findViewById(R.id.button);
ColorStateList c = ContextCompat.getColorStateList(mContext, R.color.your_custom_color;
Drawable d = b.getBackground();
if (b instanceof AppCompatButton) {
// appcompat button replaces tint of its drawable background
((AppCompatButton)b).setSupportBackgroundTintList(c);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// Lollipop button replaces tint of its drawable background
// however it is not equal to d.setTintList(c)
b.setBackgroundTintList(c);
} else {
// this should only happen if
// * manually creating a Button instead of AppCompatButton
// * LayoutInflater did not translate a Button to AppCompatButton
d = DrawableCompat.wrap(d);
DrawableCompat.setTintList(d, c);
b.setBackgroundDrawable(d);
}
At runtime, you know what style you want your button to have. So beforehand, in xml in the layout folder, you can have all ready to go buttons with the styles you need. So in the layout folder, you might have a file named: button_style_1.xml. The contents of that file might look like:
<?xml version="1.0" encoding="utf-8"?>
<Button
android:id="#+id/styleOneButton"
style="#style/FirstStyle" />
If you are working with fragments, then in onCreateView you inflate that button, like:
Button firstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);
where container is the ViewGroup container associated with the onCreateView method you override when creating your fragment.
Need two more such buttons? You create them like this:
Button secondFirstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);
Button thirdFirstStyleBtn = (Button) inflater.inflate(R.layout.button_style_1, container, false);
You can customize those buttons:
secondFirstStyleBtn.setText("My Second");
thirdFirstStyleBtn.setText("My Third");
Then you add your customized, stylized buttons to the layout container you also inflated in the onCreateView method:
_stylizedButtonsContainer = (LinearLayout) rootView.findViewById(R.id.stylizedButtonsContainer);
_stylizedButtonsContainer.addView(firstStyleBtn);
_stylizedButtonsContainer.addView(secondFirstStyleBtn);
_stylizedButtonsContainer.addView(thirdFirstStyleBtn);
And that's how you can dynamically work with stylized buttons.
I made a helper interface for this using the holder pattern.
public interface StyleHolder<V extends View> {
void applyStyle(V view);
}
Now for every style you want to use pragmatically just implement the interface, for example:
public class ButtonStyleHolder implements StyleHolder<Button> {
private final Drawable background;
private final ColorStateList textColor;
private final int textSize;
public ButtonStyleHolder(Context context) {
TypedArray ta = context.obtainStyledAttributes(R.style.button, R.styleable.ButtonStyleHolder);
Resources resources = context.getResources();
background = ta.getDrawable(ta.getIndex(R.styleable.ButtonStyleHolder_android_background));
textColor = ta.getColorStateList(ta.getIndex(R.styleable.ButtonStyleHolder_android_textColor));
textSize = ta.getDimensionPixelSize(
ta.getIndex(R.styleable.ButtonStyleHolder_android_textSize),
resources.getDimensionPixelSize(R.dimen.standard_text_size)
);
// Don't forget to recycle!
ta.recycle();
}
#Override
public void applyStyle(Button btn) {
btn.setBackground(background);
btn.setTextColor(textColor);
btn.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
}
}
Declare a stylable in your attrs.xml, the styleable for this example is:
<declare-styleable name="ButtonStyleHolder">
<attr name="android:background" />
<attr name="android:textSize" />
<attr name="android:textColor" />
</declare-styleable>
Here is the style declared in styles.xml:
<style name="button">
<item name="android:background">#drawable/button</item>
<item name="android:textColor">#color/light_text_color</item>
<item name="android:textSize">#dimen/standard_text_size</item>
</style>
And finally the implementation of the style holder:
Button btn = new Button(context);
StyleHolder<Button> styleHolder = new ButtonStyleHolder(context);
styleHolder.applyStyle(btn);
I found this very helpful as it can be easily reused and keeps the code clean and verbose, i would recommend using this only as a local variable so we can allow the garbage collector to do its job once we're done with setting all the styles.
I faced the same problem recently. here is how i solved it.
<?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">
<!-- This is the special two colors background START , after this LinearLayout, you can add all view that have it for main background-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="2"
android:background="#FFFFFF"
android:orientation="horizontal"
>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#0000FF" />
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#F000F0" />
</LinearLayout>
<!-- This is the special two colors background END-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:text="This Text is centered with a special backgound,
You can add as much elements as you want as child of this RelativeLayout"
android:textColor="#FFFFFF"
android:textSize="20sp" />
</RelativeLayout>
I used a LinearLayout with android:weightSum="2"
I gave to the two child elements android:layout_weight="1"
(I gave each 50% of the parent space(width & height))
And finally, i gave the two child element different background colors to have the final effect.
Thanks !