web-dev-qa-db-fra.com

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 devrais utiliser un ContextThemeWrapper. Quelqu'un peut-il me renvoyer à un exemple codé? Je ne trouve rien.

100
user1232691

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

Si vous souhaitez définir un thème pour fragment, ajoutez le code suivant dans la 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);
}
166
David

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

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

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

Pour remplacer le thème, vous pouvez appeler LayoutInflater.cloneInContext , qui indique dans Docs qu'il peut être utilisé pour changer de thème. Vous pouvez utiliser ContextThemeWrapper ici. Utilisez ensuite un inflateur cloné pour créer des vues de fragment.

12
Pointer Null

J'essayais également de faire afficher mon dialogue de fragment avec un thème différent de son activité, et suivis cette solution . Comme certaines personnes mentionnées dans les commentaires, cela ne fonctionnait pas et le dialogue continuait de s'afficher avec le thème spécifié dans le manifeste. Le problème s'est avéré que je construisais le dialogue en utilisant AlertDialog.Builder Dans la méthode onCreateDialog et que je n'utilisais donc pas la méthode onCreateView comme indiqué dans la réponse que j'ai lié à. Et lorsque j’ai instancié le AlertDialog.Builder, Je passais dans le contexte en utilisant getActivity() alors que j’aurais dû utiliser l’instance instanciée ConstextThemeWrapper.

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, le AlertDialog.Builder Était instancié comme suit:

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

que j'ai changé pour:

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

Après cette modification, la boîte de dialogue de fragment était affichée avec le thème correct. Donc, si quelqu'un d'autre a un problème similaire et utilise AlertDialog.Builder, Vérifiez le contexte transmis au générateur. J'espère que cela t'aides! :)

11
BruceHill

Assurez-vous que Android:minSdkVersion="11" Est défini dans votre manifeste. Cela pourrait être la cause pour laquelle l'exemple de David n'a pas fonctionné pour vous.

Définissez également l'attribut Android:theme="@Android:style/Theme.Holo.Light" Pour la balise <application> Et [~ # ~] et non [~ # ~] . la balise <activity>.

Un autre problème possible pourrait être la façon dont vous obtenez votre contexte lorsque vous utilisez un ContextThemeWrapper(). Si vous utilisez quelque chose comme getActivity().getApplicationContext(), remplacez-le simplement par getActivity().

Normalement, Theme.Holo devrait s’appliquer aux fragments liés à MainActivity.

Veuillez noter que vous utilisez un ContextThemeWrapper lorsque vous souhaitez appliquer un thème différent à votre fragment. Cela pourrait être utile si vous fournissez le morceau de code, à partir de votre MainActivity, où vous ajoutez vos Fragments.


Quelques liens utiles:

ListView personnalisé dans le fragment n'adhérant pas au thème parent

9
sebster

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

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

dans onCreateView() du fragment avant gonfler la vue racine du fragment et cela fonctionne pour moi.

9
Tomask

J'ai essayé la solution suggérée par David, mais pas dans tous les scénarios:
1. pour le premier fragment ajouté à la pile, le thème de l'activité et non celui défini dans onCrateView, mais sur le deuxième fragment que j'ajoute à la pile, les corriger ont été appliqués sur le fragment.

2. Sur le deuxième fragment que les eux a été affiché correctement, j’ai fait ce qui suit: j’ai forcé l’application à être fermée en nettoyant la mémoire, à la rouvrir de l’application et lorsque l’Activité a été recréée avec le fragment Le fragment a été modifié pour les annuler et pas le même qui a été défini dans le onCrateView du fragment.

Pour résoudre le problème, j'ai fait un petit changement et remplacé l'argument conteneur de inflater.inflate par un null.

je ne sais pas comment inflater utilise dans certains scénarios le contexte de la vue conteneur.

Remarque - que je suis en utilisant Android.support.v4.app.Fragment & Android.support.v7.app.AppCompatActivity.

@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, null, false);
} 
7
avi

Créez une classe Java), puis utilisez la présentation dont vous souhaitez modifier le thème dans la méthode onCreate.

2
Devam03

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 LinearLayout et son contenu, mais pas n'importe quoi en dehors de LinearLayout. Ainsi, afin de décorer le fragment entier avec n'importe quel style, appliquez le thème à sa mise en page la plus externe parente.

Note: Juste au cas où si vous n'avez pas encore trouvé de solution, vous pouvez l'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
Niraj Niroula

Si vous souhaitez simplement appliquer un style à un fragment particulier, ajoutez-y simplement ces lignes avant d'appeler onCreateView() ou onAttach() du fragment,

getActivity().getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
getActivity().getWindow().setStatusBarColor(Color.TRANSPARENT);

et Si vous souhaitez définir une barre d’état transparente, définissez false sur fitsSystemWindows propriété de votre mise en page racine,

Android:fitsSystemWindows="false"
1
Siddharth Sheth

Je dois le faire fonctionner en plaçant le thème sur le fragment fragment avant d'appeler l'inflateur.

REMARQUE: ceci est un exemple pour Xamarin.Android associé à MvvmCross. Je ne suis pas sûr à 100% si cela fonctionnera également pour les programmeurs Java. Mais vous pouvez essayer:)

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    Context.SetTheme(Theme);

    base.OnCreateView(inflater, container, savedInstanceState);

    var view = this.BindingInflate(FragmentLayoutId, container, false);

    // Doing some other stuff

    return view;
}

Le code de la méthode d'extension SetTheme

public static void SetTheme(this Context context, AppThemeStyle themeStyle)
{
    var themeStyleResId = themeStyle == AppThemeStyle.Dark ? Resource.Style.AppTheme : Resource.Style.AppTheme_Light;

    context.SetTheme(themeStyleResId);
}

J'espère que cela aide certaines personnes, bravo!

0
Jop Middelkamp