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.
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 .
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! :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With