Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set theme for a Fragment

People also ask

What are the themes in fragment?

The theme of Fragments is captured in the opening passage of the novel delivered by Naana: Each thing that goes away returns and nothing in the end is lost. The great friend throws all things apart and brings all things together again. That is the way everything goes and turns round.

How do I change the layout of a fragment?

You cannot replace the fragment's layout once it is inflated. If you need conditional layouts, then you either have to redesign your layout and break it down into even smaller elemens like Fragments .

What is ContextThemeWrapper class in Android?

A ContextThemeWrapper allows us to modify or overlay the theme of another context.


Setting Theme in manifest is usually used for Activity.

If you want to set Theme for Fragment, add next code in the onCreateView() of the 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);
}

Fragment takes its theme from its Activity. Each fragment gets assigned the theme of the Activity in which it exists.

The theme is applied in Fragment.onCreateView method, where your code creates views, which are actually objects where theme is used.

In Fragment.onCreateView you get LayoutInflater parameter, which inflates views, and it holds Context used for theme, actually this is the Activity. So your inflated views use Activity's theme.

To override theme, you may call LayoutInflater.cloneInContext, which mentions in Docs that it may be used for changing theme. You may use ContextThemeWrapper here. Then use cloned inflater to create fragment's views.


For applying a single style I've used just

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

in onCreateView() of the fragment before inflating root view of the fragment and it works for me.


I was also trying to get my fragment dialog to display with a different theme to its activity, and followed this solution. Like some people mentioned in the comments, I was not getting it to work and the dialog kept showing with the theme specified in the manifest. The problem turned out to be that I was building the dialog using AlertDialog.Builder in the onCreateDialog method and so was not making use of the onCreateView method as shown in the answer that I linked to. And when I was instantiating the AlertDialog.Builder I was passing in the context using getActivity() when I should have been using the instantiated ConstextThemeWrapper instead.

Here is the code for my 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;
}

I originally had the AlertDialog.Builder being instantiated as follows:

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

which I changed to:

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

After this change the fragment dialog was shown with the correct theme. So if anyone else is having a similar problem and is making using of the AlertDialog.Builder then check the context being passed to the builder. Hope this helps! :)