Skip to content

Instantly share code, notes, and snippets.

@romannurik
Last active March 7, 2024 11:13
Show Gist options
  • Star 68 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save romannurik/7026222 to your computer and use it in GitHub Desktop.
Save romannurik/7026222 to your computer and use it in GitHub Desktop.
Android example of how to programmatically instantiate a View with a custom style.
<manifest ...>
...
<!-- Make sure your app (or individual activity) uses the
theme with the custom attribute defined. -->
<application android:theme="@style/AppTheme" ...>
...
</application>
</manifest>
public class MyActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
// Pass in the theme attribute that'll resolve to the
// desired button style resource. The current theme
// must have a value set for this attribute.
Button myButton = new Button(this, null, R.attr.myButtonStyle);
myButton.setText("Hello world");
ViewGroup containerView = (ViewGroup) findViewById(R.id.container);
containerView.addView(myButton);
}
}
<!-- The convention is to put the <style> elements below
in res/values/styles.xml and <declare-styleable> in
res/values/attrs.xml. -->
<resources>
<!-- First declare a custom theme attribute that'll
reference a style resource. -->
<declare-styleable name="AppTheme">
<attr name="myButtonStyle" format="reference" />
</declare-styleable>
<!-- Provide a style resource as the value for the
theme attribute. As a side note, if you want to
change the default button style, you can instead
override the android:buttonStyle attribute. -->
<style name="AppTheme" parent="android:Theme.Holo">
<item name="myButtonStyle">@style/MyButton</item>
</style>
<!-- Define the custom button style itself. Make sure
to inherit from an existing button style. -->
<style name="MyButton" parent="android:Widget.Holo.Button">
<item name="android:textColor">#f00</item>
</style>
</resources>
@cesards
Copy link

cesards commented May 9, 2014

@romannurik This is not working for me. Maybe there is an android bug?

If I use:

TextView textView = new TextView(getActivity(), null, R.style.MassimoTheme_Text_Gray_Small_Light);

where

<style name="MassimoTheme.Text" parent="android:Widget.Holo.TextView"/>

<style name="MassimoTheme.Text.Gray">
    <item name="android:textColor">@color/primary_gray</item>
  </style>

<style name="MassimoTheme.Text.Gray.Small">
    <item name="android:textSize">@dimen/text_small</item>
  </style>

<style name="MassimoTheme.Text.Gray.Small.Light">
    <item name="android:fontFamily">fonts/Gotham-Light.otf</item>
  </style>

And TextView initialization does:

n = 6
if (appearance != null) {
            int n = appearance.getIndexCount();
            for (int i = 0; i < n; i++) {
                int attr = appearance.getIndex(i);

                switch (attr) {

               // it goes to the next cases

case com.android.internal.R.styleable.TextAppearance_textSize:
                    textSize = appearance.getDimensionPixelSize(attr, textSize);
                    break;

 case com.android.internal.R.styleable.TextAppearance_textStyle:
                    styleIndex = appearance.getInt(attr, -1);
                    break;

case com.android.internal.R.styleable.TextAppearance_textColor:
                    textColor = appearance.getColorStateList(attr);
                    break;

case com.android.internal.R.styleable.TextAppearance_textColorHighlight:
                    textColorHighlight = appearance.getColor(attr, textColorHighlight);
                    break;

case com.android.internal.R.styleable.TextAppearance_textColorHint:
                    textColorHint = appearance.getColorStateList(attr);
                    break;

case com.android.internal.R.styleable.TextAppearance_textColorLink:
                    textColorLink = appearance.getColorStateList(attr);
                    break;

But it doesn't recognize fontFamily attribute :S Is it a normal behaviour?

@jrub
Copy link

jrub commented Jun 24, 2015

Very useful indeed, thanks Roman. This should definitely be included into the official documentation for Themes & Styles (http://developer.android.com/guide/topics/ui/themes.html)

@ursusursus
Copy link

For me this does not apply layout params like layout_width, layout_height when I have them in my style. Only default wrap_content LayoutParams gets created in both dimensions

@alexfu
Copy link

alexfu commented Aug 18, 2016

@cesards: Note that you're using a direct style (i.e.R.style) as opposed to an attribute (i.e. R.attr). This tripped me up as well. Difference being, attributes reference styles.

@saretta93
Copy link

Very useful! :)

@wrozwad
Copy link

wrozwad commented Jun 1, 2017

@ursusursus: Setting any global style in theme never set layout_* parameters from style like layout_width or layout_margins

@rodolfo-tenfen
Copy link

Thank you so much!!! I wasn't being able to get a custom button to be displayed properly and your example was REALLY useful, thanks!!

@galymzhan-shakhanov
Copy link

galymzhan-shakhanov commented Oct 17, 2017

    Button myButton = new Button(this, null, R.attr.myButtonStyle);

@cesards The code above does not inject the current context if not used in Activity. Instead use:

    Button myButton = new Button(new ContextThemeWrapper(context, R.attr.myButtonStyle), null, 0);

or if you use AppCompat:

    Button myButton = new AppCompatButton(new ContextThemeWrapper(context, R.attr.myButtonStyle), null, 0);

@jerrychong25
Copy link

Thanks for the info!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment