Reputation: 1333
I'm trying to set the theme for a fragment.
Setting the theme in the manifest does not work:
android:theme="@android:style/Theme.Holo.Light"
From looking at previous blogs, it appears as though I have to use a ContextThemeWrapper. Can anyone refer me to a coded example? I can't find anything.
Upvotes: 133
Views: 124756
Reputation: 1017
Use this in fragment which you want different theme:
@Override
public void onAttach(@NonNull Context context) {
context.setTheme(R.style.your_them);
super.onAttach(context);
}
Upvotes: 0
Reputation: 2424
I solved the problem using android:theme = "@style/myTheme"
in the layout file of the fragment.
For instance this changes the style of the LinearLayout
and it's content but not any thing out side the LinearLayout
. So, in order to decor the whole fragment with any style apply the theme to it's outer most parent layout.
Note: Just in case if you haven't found a solution yet, you can give it a try.
<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>
Upvotes: 14
Reputation: 109
I know its a bit late but it might help someone else because this helped me.You can also try adding the line of code below inside the onCreatView function of the fragment
inflater.context.setTheme(R.style.yourCustomTheme)
Upvotes: 7
Reputation: 37536
Setting Theme in manifest is usually used for Activity.
If you want to set Theme for Fragment, add next code in the onGetLayoutInflater() of the Fragment:
override fun onGetLayoutInflater(savedInstanceState: Bundle?): LayoutInflater {
val inflater = super.onGetLayoutInflater(savedInstanceState)
val contextThemeWrapper: Context = ContextThemeWrapper(requireContext(), R.style.yourCustomTheme)
return inflater.cloneInContext(contextThemeWrapper)
}
Upvotes: 220
Reputation: 153
I've got it to work by setting the theme on the fragment context before calling the inflator.
NOTE: This is an example for Xamarin.Android in combination with MvvmCross. I'm not 100% sure if this will also work for the Java programmers. But you can try :)
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;
}
The SetTheme extension method code
public static void SetTheme(this Context context, AppThemeStyle themeStyle)
{
var themeStyleResId = themeStyle == AppThemeStyle.Dark ? Resource.Style.AppTheme : Resource.Style.AppTheme_Light;
context.SetTheme(themeStyleResId);
}
I hope this helps some people out, cheers!
Upvotes: 0
Reputation: 217
If you just want to apply style for particular fragment then just add this lines before calling onCreateView()
or onAttach()
of the fragment,
getActivity().getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
getActivity().getWindow().setStatusBarColor(Color.TRANSPARENT);
and If you want to set transparent status bar then set false to fitsSystemWindows
property of your root layout,
android:fitsSystemWindows="false"
Upvotes: 3
Reputation: 1320
Make sure you have android:minSdkVersion="11"
set in your manifest. This could be the cause why David's example didn't work for you.
Also, set the android:theme="@android:style/Theme.Holo.Light"
attribute for the <application>
tag and NOT the <activity>
tag.
Another possible problem might be the way you get your Context when using a ContextThemeWrapper()
. If you use something like getActivity().getApplicationContext()
just replace it with getActivity()
instead.
Normally, the Theme.Holo should apply to Fragments linked to the MainActivity.
Please note that you use a ContextThemeWrapper when you want to apply a different theme for your Fragment. It might help if you provide the piece of code, from your MainActivity, where you add your Fragments.
Some useful links:
Custom ListView in Fragment not adhering to parent theme
Upvotes: 9
Reputation: 40370
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.
Upvotes: 26
Reputation: 91
I tried the solution that David suggested it did works but not in all scenarios:
1. for the first fragment that added to the stack has the the theme of the activity and not the one that defined in onCrateView , but on the second fragment that i add to the stack correct them was applied on the fragment.
2. On the second fragment that the them was displayed correctly ,i did the following i forced the App to be closed by clean the memory , re open the App and when the Activity was recreated with the fragment The fragment changed the them wrong them of the Activity and not the same that was set in the onCrateView of the fragment .
To fix the issue i did a small change and replaced the container argument from the inflater.inflate with a null.
i don't know way the inflater uses in some scenarios the context from the container view .
Note - that im using 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);
}
Upvotes: 8
Reputation: 422
you can try this for lollipop in onAttach
final Window window = activity.getWindow(); window.setStatusBarColor(myStatusBarColor)
and set it back to default in ondettach
Upvotes: -1
Reputation: 2394
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.
Upvotes: 24
Reputation: 141
Create a java class and then use the layout you want to change the theme of in the onCreate method.Then mention it in manifest as normal
Upvotes: 2
Reputation: 7164
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! :)
Upvotes: 12