Search code examples
androidandroid-theme

Theme customization is not loaded with MenuInflater


I've noticed an unexpected behavior with my Theme customization and the inflater.

I have the following theme with the customization on the SearchView

<style name="GTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="searchViewStyle">@style/SearchView</item>
    <!--...-->
</style>

<style name="SearchView" parent="Widget.AppCompat.Light.SearchView">
    <item name="iconifiedByDefault">false</item>
    <item name="queryBackground">@color/white</item>
</style>        

And for the configuration of the search

xml/searchable.xml

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/app_name"
    android:icon="@android:drawable/ic_menu_search"
    android:hint="@string/search_hint"/>

menu/options_menu.xml

<menu
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/search"
        android:title="@string/search_view_title"
        android:icon="@drawable/ic_search_white_24dp"
        android:orderInCategory="100"
        app:showAsAction="collapseActionView|ifRoom"
        app:actionViewClass="android.support.v7.widget.SearchView"/>
</menu>

When I the SearchView is created from the method onCreateOptionsMenu the customization is not loaded

public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    getMenuInflater().inflate(R.menu.options_menu, menu);
    //Here I can already see that the costumization is missing with the debugger
    //...
    return true
}

However if I create a Layout with the SearchView a for a fragment for example :

layout/fragment_explorer.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context="com.geocodle.android.ui.explorer.ExplorerFragment">
    <android.support.v7.widget.SearchView
        android:layout_gravity="center"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:iconifiedByDefault="true">

    </android.support.v7.widget.SearchView>

</FrameLayout>

In the Fragment

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_explorer, container, false);
}

Then my SearchView has the customization

In the first case the Layout is inflated by the MenuInflater and in the second case by the LayoutInflater. I read that in the case the context is not Theme aware like with ApplicationContext the customization is not loaded. But in my case both use the Activity as context.

Do you know if there is a reason why with the menu Inflater the customization is missing ?

Update

Actually the context is not from the same instance in both cases as I thought. Even if the MenuInflater is retrieved from the Activity with this.getMenuInflater(), the context in SearchView (provided by the MenuInflater) is an instance of ContextThemeWrapper wherea with the LayoutInflater the context is my activity GeoCodleActivity. So it seems it's the reason why the behavior is not the same. So now the question is how to get the Activity as context in the MenuInflater. I tried new MenuInflater (this) as suggested by @pskink (thanks for your advices). This time I have the correct theme but then when I retrieve the SearchView it's null. The break point I added in the SearchView constructor is not even triggered

    MenuInflater menuInflater = new MenuInflater(this);
    menuInflater.inflate(R.menu.options_menu, menu);

    //With this the SearchView is not null but Theme is not customized
    //getMenuInflater().inflate(R.menu.options_menu, menu);


    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    //SearchAction has not Searchview
    MenuItem searchAction =  menu.findItem(R.id.search);
    //searchView is null
    SearchView searchView = (SearchView) searchAction.getActionView();

Solution

  • Using SupportMenuInflater instead of MenuInflater it works as expected. Of course My activivity extend AppCompatActivity

    So in onCreateOptionsMenu

    MenuInflater menuInflater = new SupportMenuInflater(this);
    menuInflater.inflate(R.menu.options_menu, menu);