132 votes

Définir le thème d'un fragment

J'essaie de définir le thème d'un fragment.

La définition du thème dans le manifeste ne fonctionne pas :

android:theme="@android:style/Theme.Holo.Light"

En regardant les blogs précédents, il semble que je doive utiliser un ContextThemeWrapper. Quelqu'un peut-il me renvoyer à un exemple codé ? Je ne trouve rien.

217voto

David Points 2298

La définition du thème dans le manifeste est généralement utilisée pour l'activité.

Si vous voulez définir le thème du fragment, ajoutez le code suivant dans le onCreateView() du fragment :

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    // create ContextThemeWrapper from the original Activity Context with the custom theme
    final Context contextThemeWrapper = new ContextThemeWrapper(getActivity(), R.style.yourCustomTheme);

    // clone the inflater using the ContextThemeWrapper
    LayoutInflater localInflater = inflater.cloneInContext(contextThemeWrapper);

    // inflate the layout using the cloned inflater, not default inflater
    return localInflater.inflate(R.layout.yourLayout, container, false);
}

48 votes

Cela ne fonctionne pas pour moi. Le fragment a toujours le même thème que celui spécifié dans le fichier manifeste.

1 votes

Dans le manifeste, vous spécifiez le thème de l'activité, pas le fragment. Utilisez-vous fragment ou fragmentActivity ?

0 votes

J'utilise un ListFragment dans une FragmentActivity.

26voto

Pointer Null Points 14229

Fragment tire son thème de son activité. Chaque fragment se voit attribuer le thème de l'Activité dans laquelle il existe.

Le thème est appliqué dans la méthode Fragment.onCreateView, où votre code crée des vues, qui sont en fait des objets où le thème est utilisé.

Dans Fragment.onCreateView vous obtenez le paramètre LayoutInflater, qui gonfle les vues, et il contient le contexte utilisé pour le thème, en fait c'est l'activité. Ainsi, vos vues gonflées utilisent le thème de l'activité.

Pour passer outre le thème, vous pouvez appeler LayoutInflater.cloneInContext qui mentionne dans les Docs qu'il peut être utilisé pour changer de thème. Vous pouvez utiliser ContextThemeWrapper ici. Ensuite, utilisez l'inflateur cloné pour créer les vues du fragment.

0 votes

Comme le dit le docs google : "...Retourne un tout nouvel objet LayoutInflater associé au Contexte donné..." - developer.Android.com/reference/Android/view/

0 votes

Complément très utile à la solution de code de David. Merci !

24voto

Tomask Points 1030

Pour appliquer un seul style, j'ai utilisé seulement

getContext().getTheme().applyStyle(styleId, true);

sur onCreateView() du fragment avant gonfler la vue Root du fragment et cela fonctionne pour moi.

1 votes

Min api 23 pour getContext()

0 votes

@vigilancer Vérifiez cette réponse pour une solution à votre problème de min api : stackoverflow.com/questions/36736244/

1 votes

Excellente solution. J'ai ajouté le code dans onAttach(Context) qui applique également le thème sur tous les fragments enfants.

12voto

BruceHill Points 2506

J'essayais également de faire en sorte que mon dialogue de fragment s'affiche avec un thème différent de celui de son activité, et j'ai suivi la procédure suivante cette solution . Comme certaines personnes l'ont mentionné dans les commentaires, je n'arrivais pas à le faire fonctionner et la boîte de dialogue s'affichait toujours avec le thème spécifié dans le manifeste. Le problème s'est avéré être que je construisais la boîte de dialogue à l'aide de AlertDialog.Builder dans le onCreateDialog et n'utilisait donc pas la méthode onCreateView comme indiqué dans la réponse dont j'ai donné le lien. Et lorsque j'ai instancié la méthode AlertDialog.Builder Je passais dans le contexte en utilisant getActivity() alors que j'aurais dû utiliser l'objet instancié ConstextThemeWrapper à la place.

Voici le code de mon onCreateDialog :

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    // Create ContextThemeWrapper from the original Activity Context
    ContextThemeWrapper contextThemeWrapper = new ContextThemeWrapper(getActivity(), android.R.style.Theme_DeviceDefault_Light_Dialog);
    LayoutInflater inflater =   getActivity().getLayoutInflater().cloneInContext(contextThemeWrapper);
    // Now take note of the parameter passed into AlertDialog.Builder constructor
    AlertDialog.Builder builder = new AlertDialog.Builder(contextThemeWrapper);
    View view = inflater.inflate(R.layout.set_server_dialog, null);
    mEditText = (EditText) view.findViewById(R.id.txt_server);
    mEditText.requestFocus();  // Show soft keyboard automatically
    mEditText.setOnEditorActionListener(this);
    builder.setView(view);
    builder.setTitle(R.string.server_dialog);
    builder.setPositiveButton(android.R.string.ok, this);
    Dialog dialog = builder.create();
    dialog.setCanceledOnTouchOutside(false);
    return dialog;
}

A l'origine, j'avais le AlertDialog.Builder étant instancié comme suit :

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

que j'ai changé en :

AlertDialog.Builder builder = new AlertDialog.Builder(contextThemeWrapper);

Après cette modification, la boîte de dialogue du fragment s'est affichée avec le thème correct. Donc, si quelqu'un d'autre rencontre un problème similaire et utilise la fonction AlertDialog.Builder puis vérifier le contexte passé au constructeur. J'espère que cela vous aidera ! :)

11voto

Niraj Niroula Points 1725

J'ai résolu le problème en utilisant android:theme = "@style/myTheme" dans le fichier de mise en page du fragment. Par exemple, cela change le style de l'élément LinearLayout et son contenu, mais rien de ce qui est en dehors de la LinearLayout . Ainsi, pour décorer l'ensemble du fragment avec un style quelconque, appliquez le thème à sa disposition parentale la plus externe.

Remarque : si vous n'avez pas encore trouvé de solution, vous pouvez essayer.

           <LinearLayout 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:theme = "@style/myTheme" >

            <TextView
                android:id="@+id/tc_buttom_text1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Time elapsed"/>

            <TextView
                android:id="@+id/tc_buttom_text2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:text="00:00:00 00"/>
        </LinearLayout>

1 votes

Cette solution rapide est meilleure, elle a sauvé ma journée, merci !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X