2010-01-22 7 views
39

Ich habe Thema, das textColor für TextView als rot angibt.Thema/Stil wird nicht angewendet, wenn mit ApplicationContext inflater verwendet

Ich verwende LayoutInFlater, um TextView zu instanziieren. Das Problem besteht darin, dass Stile nicht auf TextView angewendet werden, wenn der Inflator mit ApplicationContext erstellt wurde - die Farbe ist nicht rot. Alles funktioniert gut, wenn LayoutInflater mit Aktivität erstellt wurde.

Warum dies passiert und wie kann behoben werden?

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

Antwort

45

Lösung # 1

Die aufblasen Methode akzeptiert optional 'Viewgroup root' Argument:

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

Wenn wir Wert haben übergeben als 'root' Parameter, als daher können wir es verwenden, um 'Aktivitätskontext' zu bekommen, von wo wir richtig bekommen können LayoutInflater:

ViewGroup root > activity context > LayoutInflater 

So könnte meinen Code sein:

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

Lösung # 2

Gerade versucht programmatisch Anwendungskontext Thema zu setzen, und es arbeitet:

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

Ich denke, Es war logisch, dieses Markup zu erwarten:

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

, um es automatisch einzustellen, aber es tut es nicht.

+0

Herr Sie haben meinen Tag gerettet. Danke –

+0

Das ist so falsch. Es gibt einen Grund, warum es nicht so funktioniert, wie du denkst, dass es funktioniert: Es sollte nicht so funktionieren. Das Designattribut des Tags ist einfach der Standard, der auf alle Aktivitäten angewendet wird. Viele andere Dinge funktionieren nicht wirklich mit dem App-Kontext, zum Beispiel werden Sie Ressourcen verlieren, die sich als Reaktion auf Konfigurationsänderungen usw. ändern. – dcow

+0

Lösung # 2 funktionierte wie ein Zauber. Meine Anwendung sieht jetzt großartig aus. Vielen Dank! – Mauker

31

Verwenden Sie niemals einen Anwendungskontext, um Ansichten aufzublasen, da das Formatieren in diesem Kontext nicht funktioniert. Verwenden Sie immer den Kontext einer Aktivität, wenn Sie mit Ansichten spielen. Die einzige Ausnahme ist, wenn Sie RemoteViews von einem Service erstellen müssen.

Weitere Informationen über die verschiedenen Arten von Kontexten und ihre Fähigkeiten finden Sie unter in this excellent article.

+2

Das ist nicht wirklich wahr, die Verwendung von Application Context zum Erstellen von Ansichten wird ebenfalls empfohlen, um Speicherlecks zu vermeiden, mit denen ich mich gerade beschäftige. – David

+2

Hängt davon ab, wie Ihre Ansichten verwendet werden. Wenn Ihre Ansichten nicht Teil einer Aktivität sind, sollten Sie den Kontext der Aktivität natürlich nicht verwenden. – BladeCoder

+0

Sir Sie haben meinen Tag gerettet. Danke –

0

Ich stoße normalerweise auf dieses Problem beim Aufblasen einer benutzerdefinierten Ansicht.Hier ist, was ich persönlich mache, um das gleiche Thema der Aktivität in der CustomView zu halten:

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  
} 
} 
Verwandte Themen