Setting styles of programmatically added Views - android

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>

Related

How do you set a default textColor inside a LinearLayout that contains multiple TextViews?

I have a LinearLayout with that has multiple TextViews and want to set up a default global color for that layout only without having to add a textColor field inside each TextView. Also, if it's possible, would it also be possible to override the color value by adding it inside the TextView? i.e. If I set blue as a default color and black for a single TextView, would the blue change to black?
To set the default global TextView colors, first you can create your own theme in AndroidManifest.xml file for the following items:
textColorPrimary - for Large texts
textColorSecondary - for Medium texts
textColorTertiary - for Small texts
textColorHint - for Hint texts
For example, in AndroidManifest.xml:
<style name="TextViewTheme" parent="android:Widget.TextView">
<!-- Set the default global color for TextViews to Holo Blue Dark -->
<item name="android:textColorPrimary">#android:color/holo_blue_dark</item>
<item name="android:textColorSecondary">#android:color/holo_blue_dark</item>
<item name="android:textColorTertiary">#android:color/holo_blue_dark</item>
<item name="android:textColorHint">#android:color/holo_blue_dark</item>
</style>
Next, set the theme style on your LinearLayout. You can also override the default for a single TextView to black color, like the following which set the first TextView Hint text color to black in activity_main.xml:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:theme="#style/TextViewTheme">
<TextView
android:id="#+id/phone_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="#string/phone_tv"
android:textColor="#android:color/black"
android:textColorHint="#android:color/black" />
<TextView
android:id="#+id/email_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="#string/email_tv" />
</LinearLayout>
Hope this helps!
You can override default text colors for the entire application by setting textColorPrimary and textColorSecondary in your parent in styles.xml
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
<item name="textColorPrimary">#color/black</item>
<item name="textColorSecondary">#color/grey</item>
</style>
If your TextViews are indeed very many to the extent that calling setTextColor() on each of them would be a herculean task, why not use a view that supports an adapter (i.e ListView, RecyclerView etc). Your TextViews would show up the exact same way as you intend them to appear with the LinearLayout.
While using an adapter, you can set up a model TextView layout and set a global textColor for all the TextViews. You can override this global textcolor in your adapter by using simple if and else statements.
I hope this helps.. Merry coding!
This code will work even if you add or remove TextViews from your layout. Just put it in your activity's onCreate();
LinearLayout layout = (LinearLayout)findViewById(R.id.layout);
for (int i = 0; i < layout.getChildCount(); i++) {
View v = layout.getChildAt(i);
if (v instanceof TextView) {
((TextView) v).setTextColor(Color.BLACK);
}
}
change the color to what you like.
If you want after this code you can change the color for any specific TextView.
Pretty late answer but this does the trick.
Inside style.xml lately changed to themes.xml
<style name="ErrorStyle">
<item name="android:textColor">#FF0000</item>
</style>
Then inside your xml layout
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:theme="#style/ErrorStyle">
.. All of your TextView
</LinearLayout>
Using this approach we can use other xml variation such as night mode, etc... and we still have te possibility to override the internal TextViews.

Android: Global style for all Spinners in my app

I'm using Xamarin Android in Visual Studio 2017.
I have a few existing Spinners which are created in xml layout which all work perfectly and are styled exactly how I want them to look. The code for these is typically:
<Spinner
android:spinnerMode="dialog"
android:id="#+id/SpnProject"
android:layout_width="fill_parent"
android:layout_height="40dp"
android:layout_marginBottom="8dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:background="#drawable/myspinner"
android:prompt="#string/project_prompt" />
That works great and my little background image is all rendered correctly..
Now I am trying to create some other spinners dynamically, 100% through code (not layout XML). I'm putting them inside a LinearLayout dynamically with my code.
To create one of these, the code is typically:
Spinner CustomPicker = new Spinner(TheActivity);
List<CustomAttributeOption> AttOptions = db.GetCustomAttributeOptions(ThisAtt.AttributeId);
ArrayAdapter<CustomAttributeOption> AttOptionsAdapter = new ArrayAdapter<CustomAttributeOption>(Activity, Android.Resource.Layout.SimpleSpinnerDropDownItem, AttOptions);
CustomPicker.Adapter = AttOptionsAdapter;
customAttributeHolder.AddView(CustomPicker, StackerPosition);
This code all completely works and a new dynamic Spinner appears on my form.
But it has default styling and I want to apply the same styles as my other spinners, specifically, I want these dynamic spinners to have a specified height = 40dp. I can't seem to be able to specify layoutHeight=40dp anywhere using code? Does it have to be done using styles/xml?
I played around a lot trying to setup a Theme and specifying a style for all Spinners in my Activity, but the app wouldn't build or run.
Ideally, I'd really like to remove the layout_height and layout_width values out of layout XML and just have it defined somewhere ONCE like in a global style for ALL SPINNERS IN MY ENIRE PROJECT kind of thing.
Can this be done, or are you forced to specify width and height for every single widget on a case by case basis?
You can use the layout inflater in order to "auto-magically" apply the styles you can defined.
Lets assume you have a "global" style for your Spinner:
<style name="MySpinnerStyle" parent="android:Widget.Spinner">
<item name="android:spinnerMode">dialog</item>
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">40dp</item>
<item name="android:layout_marginBottom">8dp</item>
<item name="android:paddingTop">8dp</item>
<item name="android:paddingBottom">8dp</item>
<item name="android:paddingStart">8dp</item>
<item name="android:paddingEnd">8dp</item>
<item name="android:background">#drawable/myspinner</item>
<item name="android:prompt">#string/project_prompt</item>
</style>
Create an independent Layout for the dynamic Spinner(s) that you create that uses your global Spinner style
<?xml version="1.0" encoding="UTF-8" ?>
<Spinner xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/masterSpinner"
style="#style/MySpinnerStyle" />
Now instead of instancing a new Spinner, inflate the layout and all the associated properties will be assigned:
var spinner = LayoutInflater.Inflate(Resource.Layout.Spinner, rootLayout, false) as Spinner;
spinner.Adapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleSpinnerItem, new string[] { "Stack", "Over", "Flow" });
customAttributeHolder.AddView(spinner, StackerPosition);

what style has dynamically added view?

I experience strange situation: when I put check box by code, it has diffrent style then check box added by xml file.
this is the dynamically adding the check boxes:
LinearLayout checkboxGroup = (LinearLayout) v.findViewById(R.id.category_checkbox_group);
for(String category : categories) {
CheckBox checkBox = new CheckBox(getActivity());
checkBox.setText("dynamically added");
checkBox.setOnClickListener(mCategoryChecked);
checkboxGroup.addView(checkBox);
}
fragment of xml:
<LinearLayout
android:id="#+id/category_checkbox_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:orientation="vertical">
<CheckBox
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="xml added" />
</LinearLayout>
So after all I have one checkbox form xml and few checkboxes from code.
The screen looks like below:
so my questions are:
what style is default for dynamic views?
how to apply this style to xml's views?
is a easy way to change box in check box?
The style for the dynamically added view depends on the context. In your situation the context is your activity, so the style of the added view is the style of your activity. If you didn't setup a theme for your activity, then it is the theme of your application, that you defined in your styles.xml. Example:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
</style>
You most probably inflated the xml layout from a different context. If you are inflating it from the same context like your added views, the views should have the same style. Try to check this.
You can also set a style for one view in xml like that:
<View
style="#style/Example" />

adding the style attribute via code [duplicate]

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 !

How to programmatically set style attribute in a view

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 !

Categories

Resources