Home > database >  Setting theme for an fragment
Setting theme for an fragment

Time:11-24

I've got the following two themes:

<!-- Base application theme. -->
<style name="Theme.MyDemoApp" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    <!-- Primary brand color. -->
    <item name="colorPrimary">@color/purple_500</item>
    <item name="colorPrimaryVariant">@color/purple_700</item>
    <item name="colorOnPrimary">@color/white</item>
    <!-- Secondary brand color. -->
    <item name="colorSecondary">@color/teal_200</item>
    <item name="colorSecondaryVariant">@color/teal_700</item>
    <item name="colorOnSecondary">@color/purple_500</item>
</style>

<!-- Base application theme with a prominent app bar incl. image -->
<style name="Theme.MyDemoApp.Prominent.Image" parent="Theme.MyDemoApp">

    <!-- Transparent status bar, so that the image extents to the status bar-->
    <item name="android:statusBarColor">@android:color/transparent</item>
    <item name="android:windowTranslucentNavigation">true</item>
</style>

The theme Theme.MyDemoApp is being used my my application or actually my entire application.

One activity opens a special fragment. The fragment is using a prominent app bar with an image, where the image is also displayed on the status bar. Thus, I've created an own theme called Theme.MyDemoApp.Prominent.Image which enables me to display the image on the status bar.

Since the fragment will be called from different actities AND fragments, I want to set the Theme.MyDemoApp.Prominent.Image to the fragment. I've looked many solutions to set the theme to fragment such as:

1)

@Override
public void onAttach(@NonNull Context context) {
    context.setTheme(R.style.Theme_MyDemoApp_Prominent_Image);
    super.onAttach(context);
}
@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.Theme_MyDemoApp_Prominent_Image);

    //clone the inflater using the ContextThemeWrapper
    LayoutInflater localInflater = inflater.cloneInContext(contextThemeWrapper);
    
    return inflater.inflate(R.layout.fragment_demo_appbar_image, container, false);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    getContext().getTheme().applyStyle(R.style.Theme_MyDemoApp_Prominent_Image, true);
    return inflater.inflate(R.layout.fragment_demo_appbar_image, container, false);
}

Setting the theme directly in the fragment xml file

<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    style="@style/Theme.MyDemoApp.Prominent.Image"
    android:theme="@style/Theme.MyDemoApp.Prominent.Image"
    >
<!-- bla bla bla bla -->
</androidx.coordinatorlayout.widget.CoordinatorLayout>

However, NONE of the above tried solutions worked for me. The theme won't change aka the status bar is not transparent. If I put the fragment theme parameters into the activity theme, it work's like a charm, but that is not what I'm planning to do.....

What might the problem be and any idea how can I set the theme in my fragment correctly?

CodePudding user response:

try to return localInflater.inflate(... in 2. try

@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.Theme_MyDemoApp_Prominent_Image);

    //clone the inflater using the ContextThemeWrapper
    LayoutInflater localInflater = inflater.cloneInContext(contextThemeWrapper);
    return localInflater.inflate(R.layout.fragment_demo_appbar_image, container, false);
}

edit: now I see problem more clearly...

you are trying to set statusBarColor and windowTranslucentNavigation - those are params for Activity, not Fragment. so your theme should be applied to Activity, setting up theme on Fragment or View layer/level (kind-of child of Fragment, which is a child of Activity) by Context wrapping or setting programmtacially/by XML is just "too low", hosting Activity just won't apply these attributes

so you have to set up Theme for whole Activity - translucent status bar when your Fragment shows up and returning to default (black?) color when detaching it. but you can set Theme for whole Activity programmatically only by calling setTheme( before super.onCreate( call, so only at very beginning, when you probably won't be sure that translucent-status-Fragment will be shown... (e.g. it may show on some click during runtime)

so you need to restart Activity then, with some additional flag customising setTheme(, also your Fragment should pop-up then at start... you may use Bundle passed for Intent starting this Activity again just after finish() call

I do believe that this is just too much effort and your Fragment should be in fact another Activity with this transparent-status theme set up by XML, optionally it may be some extension of some transparet-Activity-theme instead of your "Theme.MyDemoApp"

  • Related