I have two tabs and each tabs has its own searchbar.
I bind the searchbar in onCreateOptionsMenu
. However, the searchbars only work if I leave the screen once and return to the screen (meaning it needs one more lifecycle for the searchbars to react). I confirmed that onCreateOptionsMenu is indeed called two times at the time of the creation of the ViewPagerFragment.
I bind them like this:
MenuItem searchItem = menu.findItem(R.id.search);
searchItem.setVisible(true);
SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
...
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
...
return false;
}
});
I am guessing this bug is related to the tabs. How do implement a working searchbar with tabs (i.e. viewpager2)?
I call this on onCreateOptionsMenu:
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
// Call the above...
}
The ViewPager hosting them looks like this:
private void init(View view) {
ViewPager2 viewPager2 = view.findViewById(R.id.view_pager_fragment_view_pager);
TabLayout tabLayout = view.findViewById(R.id.tab_layout_fragment_view_pager);
viewPager2.setUserInputEnabled(true);
viewPager2.setAdapter(new ViewPagerFragmentAdapter(ViewPagerFragment.this));
viewPager2.setOffscreenPageLimit(5);
new TabLayoutMediator
(tabLayout, viewPager2,
(tab, position) -> tab.setText(titles[position])).attach();
}
OP and I were communicating while we found a solution.
First each fragment was changed to
public class MergedItemsFragment extends Fragment implements SearchView.OnQueryTextListener {
/// ------------------------------
/// SearchView.OnQueryTextListener
@Override
public boolean onQueryTextSubmit(String query) {
// ...
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
// ...
return false;
}
/// --------
/// Fragment
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_merged_items, container, false);
}
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
final MenuItem searchItem = menu.findItem(R.id.search);
final SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setOnQueryTextListener(this);
}
}
SearchView
was inflated by using a menu.xml file within the App's Activity.SearchView.OnQueryTextListener
was implemented by each Fragment
that needed access to the SearchView
onCreateOptionsMenu()
is invoked each time a Fragment
is created, or subsequently comes into view (e.g. Swipe); the SearchView
's OnQueryTextListener
is updated to the corresponding Fragment
Fragment
containing the ViewPager2
, which was removed: viewPager2.setOffscreenPageLimit(5);
that caused each Fragment
provided by the FragmentStateAdapter
to instantiate and mutate the SearchView
's OnQueryTextListener
each time a Fragment
was created.
Removing the line made sure that only the Fragment
that was in view was bound to the Toolbar
's SearchView
.If any more code is desired, i'd be happy to post what I have, and if I come up with a solution using viewPager2.setOffscreenPageLimit(5);
i.e. caching, i'll post that as well