0

So guys I was reading that it's simply not possible to set the style of a view via Java. There is no such method myView.setStyle("styleName") yet.

Then when you create your layout elements by code, such as textvews, and imageviews or linearlayouts as containers, how do you set their style? Do you assign rule by rule of each newly created element? Or is there a more efficient way to do this task?

@EDIT

Alright, I figured out how do it. Will answer my question with the solution I'm using

Victor Ferreira
  • 6,151
  • 13
  • 64
  • 120

4 Answers4

1

You can subclass the view you want to style and pass the style you wish to apply during runtime. Something like the below class which simply sets a custom font to TextView. Mainly, you need to look into the 3rd constructor where you can supply your style.

public class TextViewRoboto extends TextView {

    public TextViewRoboto(Context context) {
        super(context);
    }

    public TextViewRoboto(Context context, AttributeSet attrs) {
        super(context, attrs);
        setCustomFont(context, attrs);
    }

    public TextViewRoboto(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setCustomFont(context, attrs);
    }

    private void setCustomFont(Context ctx, AttributeSet attrs) {
        setCustomFont(ctx, "roboto-light.ttf");
    }

    public boolean setCustomFont(Context ctx, String asset) {
        Typeface tf = null;
        try {
            tf = Typefaces.get(ctx, asset);
        } catch (Exception e) {
            Logger.e("Could not get typeface: " + e.getMessage());
            return false;
        }

        setTypeface(tf);
        return true;
    }

}
Nitin Sethi
  • 1,416
  • 1
  • 11
  • 19
  • and how do I reference the style? I mean, what should I pass to the constructor as defStyle? for example, if I have set a style 'myStyle' in the styles.xml, how should I use it in the constructor? – Victor Ferreira Sep 23 '13 at 03:22
  • 2
    You can refer the style with R.style.myStyle. You need to replace the TextView element in your XML with the fully qualified name of your TextView's subclass ! – Nitin Sethi Sep 23 '13 at 04:13
  • @NitinSethi No you cannot. Look at https://code.google.com/p/android/issues/detail?id=12683#c15 – Eric Urban Jan 30 '14 at 18:59
1

Each View or its subclass has a third constructor that take the Style argument. For example, this constructor of View. Mention the Style resource id for this view and thus it should be mentioned during view creation.

From documentation

The default style to apply to this view. If 0, no style will be applied (beyond what is included in the theme). This may either be an attribute resource, whose value will be retrieved from the current theme, or an explicit style resource.

prijupaul
  • 2,076
  • 2
  • 15
  • 17
1

The solution I found The goal is to create elements programmatically that were previously styled somewhere else.

First, I created a new XML file in the res/layout folder. I named it template.xml and inserted the following code in it:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    style="@style/rootElement"
    >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/firstChildId"
        style="@style/firstChild" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/secondChild" />

</LinearLayout>

And then I styled then the way I wanted in styles.xml file

<resources xmlns:android="http://schemas.android.com/apk/res/android">
    <style name="rootElement">
        <!-- style -->          
    </style>

    <style name="firstChild">
        <!-- style -->     
    </style>
</resources>

Now, in my Activity class I added:

LinearLayout rootElement = (LinearLayout) getLayoutInflater().inflate(R.layout.template, null);
someOtherView.addView(rootElement);

The inflater will load the template we created in res/layout/template.xml (all the elements in that file and its attributes) and assign it to rootElement that is then used in my code for anything else. Example

TextView firstChild = (TextView) rootElement.getChildAt(0);
firstChild.setText("It is the firstChild element");

or

TextView firstChild = (TextView) rootElement.findViewById(R.id.firstChildId);
...

Quite easy, isn't it?! I hope that helps

Victor Ferreira
  • 6,151
  • 13
  • 64
  • 120
  • 1
    ... and how is this programmatically ? prijupaul's answer is correct. The catch: you can only apply a style when instantiating the view object/element, after that you can alter properties one-by-one, but can't apply a complete style. – Suau Sep 24 '13 at 04:20
  • 1
    this is what he means: new TextView(this, null, R.style.firstChild), then set the appropriate LayoutParams and you're done. – Suau Sep 24 '13 at 04:27
  • 1
    his answer may be correct (and I hope it helps other people). I am adding the solution I found/am using. this is 'programmatically' because the element was created in runtime and I and referring to an existing style. I created this tutorial because i found the examples quite difficult for beginners, and I saw some people with the same opinion commenting on the threads. – Victor Ferreira Sep 24 '13 at 05:32
  • 2
    As an extra little kicker, you can apply a different Theme during view constuction/inflation by using a ContextWrapper. You would construct the ContextWrapper from your current Context, set the Theme in the ContextWrapper and user the ContextWrapper for inflating/constructing views. The contextWrapper will retrieve different styles/resources based on the theme. – C B J Sep 24 '13 at 06:19
0

You can use themes and styles

A theme can be applied to the whole application by specifying the name of the theme in the Android manifest

e.g. <application android:theme="@style/CustomTheme">

You can override the theme for a specific activity by specifying a specific style.

There are various predefined themes Holo Light and Holo Dark are the more common themes. Most apps start by creating a new theme that is inherited from one of the above themes and overriding specific elements as needed.

The best thing to do really is to refer to the documentation, which should always be your first port of call.

http://developer.android.com/guide/topics/ui/themes.html

jamesc
  • 12,423
  • 15
  • 74
  • 113
  • 3
    His question is "Styling Views created programmatically on Android" and not through XML files. – prijupaul Sep 22 '13 at 03:51
  • 2
    @prijupaul widgets created in code pick up the theme applied to the application declaration in the manifest. Styles can be applied in code as well as in XML, Themes and styles should be created as XML documents. So what's your point? – jamesc Sep 22 '13 at 20:39