Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

retain searchView state on orientation change in a Fragment

I am trying use the actionbarcompat (with the android support library) following the android developer's blog entry.

Basically, I am trying create a Fragment extending the ListFragment. I am using an ArrayAdapter for the listview. I was able to successfully integrate the actionbar compat with a search menu item and could get the search working as well.

I now want to retain the state of the fragment on orientation change as well. I haven't set the setRetainInstance(true) in my fragment. Inorder to retain the state of the search view, i tried the following:

  • save the text in the SearchView in onSaveInstanceState()
  • in onCreateView, retrieve the searchText if available
  • in onCreateOptionsMenu (which would be invoked on every orientation change), I am trying to set the search query to the SearchView instance mSearchView.setQuery(mSearchText, false);

There are 2 issues that I see with this approach:

  1. the onQueryTextChange() is called twice on orientation change - once with the searchText that has been retained (because of mSearchView.setQuery(mSearchText, false);) and again, with an empty String value. This second call with the empty String value updates the list adapater to have all the items without any filtering. I am also not really sure why this is happening.
  2. mSearchView.setQuery(mSearchText, false); isn't setting the query in the SearchView and is not visible in the UI as well (on orientation change, the search view is expanded by default and is focused without any text value though I have set the query).

Outline of my Fragment is as follows:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // create and initialize list adapter
    ....
    setHasOptionsMenu(true);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.plainlist, container, false);
    if (savedInstanceState != null) {
        mSearchText = savedInstanceState.getString(RetainDataKeySearchText, null);
    }
    return view;
}

@Override
public void onSaveInstanceState(Bundle outState) {
    if (isAdded()) {
        if (mSearchView != null) {
            String searchText = mSearchView.getQuery().toString();
            if (!TextUtils.isEmpty(searchText))
                outState.putString(RetainDataKeySearchText, searchText);
            }
        }
    super.onSaveInstanceState(outState);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.search_item_list, menu);
    MenuItem searchItem = menu.findItem(R.id.menu_search);
    mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
    mSearchView.setOnQueryTextListener(this);

    if (!TextUtils.isEmpty(mSearchText))
        mSearchView.setQuery(mSearchText, false);

    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onQueryTextChange(String newText) {
    // Called when the action bar search text has changed.
    searchItems(newText);
    return true;
}

@Override
public boolean onQueryTextSubmit(String searchText) {
    return true;
}

private void searchItems(String searchText) {
    // filter results and update the list adapter
}

The menu xml (search_item_list) file is as follows:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:sprinklr="http://schemas.android.com/apk/res-auto">

    <item android:id="@+id/menu_search"
        android:icon="@android:drawable/ic_menu_search"
        android:title="@string/search"
        android:orderInCategory="0"
        sprinklr:showAsAction="ifRoom|collapseActionView"
        sprinklr:actionViewClass="android.support.v7.widget.SearchView" />

</menu>

I would like to know if there is anything that I am missing or if there is a better alternate to retain the state of the SearchView (android.support.v7.widget.SearchView) on orientation change in a ListFragment with actionbarcompat.

like image 846
user2725461 Avatar asked Nov 02 '22 15:11

user2725461


1 Answers

As a workaround, replace your

mSearchView.setQuery(mSearchText, false); 

with:

final String s = mSearchText;

mSearchView.post(new Runnable() {

    @Override
    public void run() {
        mSearchView.setQuery(s, false);
    }
});

It will set the saved string after the system has set the empty string.

like image 102
Frank Avatar answered Jan 04 '23 13:01

Frank