代码之家  ›  专栏  ›  技术社区  ›  alex2k8

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

  •  43
  • alex2k8  · 技术社区  · 15 年前

    我有一个主题,它将文本视图的文本颜色指定为红色。

    我正在使用LayoutInflator实例化TextView。问题是,当使用ApplicationContext创建充气器时,样式不会应用于textView-颜色不是红色。当使用“活动”创建“布局充气器”时,所有功能都可以正常工作。

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

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

    代码:

    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);
        }
    }
    

    /资源/布局/测试\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>
    
    3 回复  |  直到 8 年前
        1
  •  51
  •   alex2k8    15 年前

    解1

    充气方法接受可选的“viewgroup root”参数:

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

    如果我们有值作为“根”参数传递,那么我们可以使用它来获取“活动上下文”,从中我们可以得到正确的layoutInflator:

    ViewGroup root > activity context > LayoutInflater
    

    所以我的代码可以是:

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

    解2

    只是尝试以编程方式设置应用程序上下文主题, 作品 :

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

    我认为期望这个标记是合乎逻辑的:

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

    自动设置,但不设置。

        2
  •  33
  •   BladeCoder    10 年前

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

    可以找到有关不同类型上下文及其功能的更多信息 in this excellent article .

        3
  •  0
  •   abedfar    8 年前

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