Android 当充气器与 ApplicationContext 一起使用时,不应用主题/样式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2118251/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 04:36:54  来源:igfitidea点击:

Theme/Style is not applied when inflater used with ApplicationContext

androidcoding-stylethemes

提问by alex2k8

I have theme that specifies textColor for TextView as red.

我有将 TextView 的 textColor 指定为红色的主题。

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.

我正在使用 LayoutInflater 来实例化 TextView。问题是当使用 ApplicationContext 创建充气器时,样式不会应用于 TextView - 颜色不是红色。当 LayoutInflater 使用活动创建时,一切正常。

Why this happens, and how can be fixed?

为什么会发生这种情况,如何解决?

/res/values/styles.xml:

/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:

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

/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:

/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>

回答by alex2k8

Solution # 1

解决方案#1

The inflate method accepts optional 'ViewGroup root' argument:

inflate 方法接受可选的“ViewGroup root”参数:

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:

如果我们有值作为“root”参数传递,那么我们可以使用它来获取“活动上下文”,从那里我们可以获得正确的 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

解决方案#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.

自动设置它,但它没有。

回答by BladeCoder

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.

永远不要使用应用程序上下文来膨胀视图,因为样式不适用于此上下文。在使用视图时始终使用 Activity 的上下文。唯一的例外是当您需要从服务创建 RemoteViews 时。

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

关于不同类型的上下文及其功能的更多信息可以在这篇优秀的文章中找到。

回答by android developer

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

您可以在此处阅读有关此内容的更多信息

回答by abedfar

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

我通常在膨胀自定义视图时遇到这个问题。这是我个人在 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       
}   
}