Theme/Style is not applied when inflater used with ApplicationContext

I have theme that specifies textColor for TextView as red.

I am using LayoutInflater to instantiate TextView. The problem is that styles are not applied to TextView when inflater created using ApplicationContext - the color is not red. All works fine when LayoutInflater created using activity.

Why this happens, and how can be fixed?

/res/values/styles.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="MyTheme">
        <item name="android:textViewStyle">@style/MyTextView</item>
    </style>

    <style name="MyTextView" parent="@android:style/Widget.TextView">
        <item name="android:textColor">#f00</item>
    </style>
</resources>

AndroidManifest.xml:

<application 
    android:icon="@drawable/icon" 
    android:label="@string/app_name"
    android:theme="@style/MyTheme"
    >

Code:

public class A extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test_a);

        final LayoutInflater goodInflater = getInflater((Activity)this); 
        final LayoutInflater badInflater = getInflater(getApplicationContext());
        final LinearLayout container = (LinearLayout)findViewById(R.id.container);

        findViewById(R.id.add_with_appContext).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                add(container, badInflater); // Creates gray TextView
            }            
        });

        findViewById(R.id.add_with_activity).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                add(container, goodInflater); // Creates red TextView
            }            
        });
    }

    private LayoutInflater getInflater(Context context) {
        return (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    private void add(LinearLayout container, LayoutInflater inflater) {
        inflater.inflate(R.layout.my_template, container, true);
    }
}

/res/layout/test_a.xml

<?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="vertical">

    <Button 
        android:text="Add with AppContext" 
        android:id="@+id/add_with_appContext" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        />

    <Button 
        android:text="Add with Activity" 
        android:id="@+id/add_with_activity" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        />

    <LinearLayout
        android:id="@+id/container"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"  
        />

</LinearLayout>

/res/layout/my_template.xml:

<?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"
    >

    <TextView
        android:id="@+id/text"
        android:text="Some text..."
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content"
    />

</LinearLayout>


Asked by: Julian457 | Posted: 25-01-2022






Answer 1

Solution # 1

The inflate method accepts optional 'ViewGroup root' argument:

public View inflate (int resource, ViewGroup root, boolean attachToRoot)

If we have value to pass as 'root' parameter, than hence we can use it to get 'activity context' from where we can get correct LayoutInflater:

ViewGroup root > activity context > LayoutInflater

So my code could be:

private void add(LinearLayout container) {
    LayoutInflater inflater = getInflater(container.getContext());
    inflater.inflate(R.layout.my_template, container, true);
}

Solution # 2

Just tried to set Application Context theme programmatically, and it works:

getApplicationContext().setTheme(R.style.MyTheme);

I think it was logical to expect this markup:

<application 
    android:icon="@drawable/icon" 
    android:label="@string/app_name"
    android:theme="@style/MyTheme"
    >

to set it automatically, but it does not.

Answered by: Carlos263 | Posted: 26-02-2022



Answer 2

Never use an Application Context to inflate views, because styling doesn't work with this context. Always use an Activity's context when playing with views. The only exception is when you need to create RemoteViews from a Service.

More info about the different types of Contexts and their capabilities can be found in this excellent article.

Answered by: Kelvin307 | Posted: 26-02-2022



Answer 3

You probably use a context that isn't one that has a theme.

To solve it, use something as such:

val inflater= LayoutInflater.from(context).cloneInContext(ContextThemeWrapper(context, R.style.some_activity_theme))

You can read more about this here

Answered by: Julian876 | Posted: 26-02-2022



Answer 4

I usually come across this issue on inflating a custom view. Here is what I personally do to keep the same theme of the activity in the CustomView

public class CustomView extends ViewGroup{

public CustomView (Context context) {
    super(context);
    init(context);
}

public CustomView (Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

public CustomView (Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    init(context);
}

@TargetApi(21)
public CustomView (Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    init(context);
}

private void init(Context context) {
    LayoutInflater  mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View v = mInflater.inflate(R.layout.review_list_item, this, true);
    //rest of view initialization       
}   
}

Answered by: Samantha375 | Posted: 26-02-2022



Similar questions

android - What is the applicationcontext in makeTest() Method, please explain with the following snippet

Toast.makeTest(HelloGridView.this,"Text to be displayed",Toast.LENGTH.SHORT).show(); What is the 'HelloGridView.this' refers? why it is called as appliactioncontext?


android - Store Objects in ApplicationContext

When my application goes to background , my (static and singleton) objects are cleared. So I tried to store these objects in Applicaton Context . I am using the following code. Accounts.create(getApplicationContext()) will be called once to store the accounts instance. Is that possible(reliable) to store objects in Application Context ? I am not sure the following way is correct or not . pl...


java - Technique for get the ApplicationContext anywhere

Recently I discovered a snippet that use the following technique in order to access statically from anywhere to the application context. It looks cool but is really a nice option or is a bad tech for some reason? public class MyApp extends Application { private static MyApp instance; public static MyApp getInstance() { return instance; } public static Context getContext(){ ...


java - Use ApplicationContext in Helper-Class

What I'm trying to do I'm trying to create a Login which is fully handled in a Helperclass, to keep the code simple. For this I created a helperclass with all the functionality I need, now the Problem is that I always get a NullPointer-Exception, probably because of the getApplicationContext. Question ...


android - Video in WebView - ApplicationContext vs Activity Context

I am playing a video in a WebView. If a memory leak is to be avoided, the ApplicationContext (as against an Activity context) has to be used to instantiate the WebView (refer to this) If I pass in the ApplicationContext and the VideoView inside the


How to Access Android Custom Application Object in simple Java Class which Also has ApplicationContext object?

I have created a custom application class like this: class A extends android.app.Application{ public String abc = "xyz"; } And I have a simple java class class B { private appContext; // This constructor is called from activity. B(Context ctx){ this.appContext = ctx; } private void foo(){ // want to access Class A's abc Str...


android - get applicationContext in TextView.setText()

I'm building a TextView subclass to change the text that is inserted in the android:text. For instance, I want to capitalize the whole text but, to make sure that it is needed, I need to access the Application instance (I have a boolean that tells if it must or not be capitalized). I implemented this subclass: public class UpperTextView extends TextView { private Context c...


android - getting "androidApplicationContext must be not null!" crashes from crash reporting service

after supporing linkedin social network, an app i'm working on has caused many crashes that the only thing that is written there is &quot;androidApplicationContext must be not null!&quot; . i've searched the internet , and found only the next links as clues: http://pastebin.com/QeV9D8XH


android - How can I pass ApplicationContext into the function in a new Thread()?

I need to get location information about GPS location every 30 seconds in an infinity loop and send in to a server via HTTP-request. Endless cycle if GPS scanning should be stopped If i get an appropriate response from the server. Service is called DataTransferService, gps scanner is called GPSTracker for this and service . The problem is that I can't get a proper Context for my GPSTracke...


android - Service context not working as ApplicationContext

I have a WakefulBroadcastReceiver that catches Google Cloud Messages and starts an IntentService to handle the incoming message. In the IntentService, I need to get access to a singleton SQLite database. Normally, I open the database from an Activity with getApplicationContext(), but that throws errors and gives an NPE sometimes when opened from the IntentService. If the app has been backgrounded for a long time, when ...






Still can't find your answer? Check out these communities...



Android Google Support | Android Community | Android Community (Facebook) | Dev.io Android



top