The correct implementation of SearchView in the Android toolbar

I have a problem with the implementation of searchview on the Android toolbar.

  • The empty space is too large.
  • I do not want to hide other actions, but these actions are blocked by SearchView.
  • Underscore SearchView not displayed

How to fix the problems mentioned above?

enter image description here

menu.xml

<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/action_search" android:title="@string/car_num" android:icon="@drawable/ic_search_white_24dp" app:actionViewClass="android.support.v7.widget.SearchView" app:showAsAction="always" /> <item android:id="@+id/action_add_client" android:icon="@drawable/ic_account_multiple_plus" android:title="@string/action_add_client" app:showAsAction="always" /> </menu> 

fragment

 @Override public void onCreateOptionsMenu(final Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.menu_fragment_reg_vehicles, menu); final MenuItem item = menu.findItem(R.id.action_search); searchView = (SearchView) MenuItemCompat.getActionView(item); searchView.setQueryHint("Search"); searchView.setMaxWidth(Integer.MAX_VALUE); searchView.setIconifiedByDefault(false); searchView.setOnQueryTextListener(this); searchView.setOnCloseListener(new SearchView.OnCloseListener() { @Override public boolean onClose() { setItemsVisibility(menu, item, true); return false; } }); searchView.setOnSearchClickListener(new View.OnClickListener() { @Override public void onClick(View view) { setItemsVisibility(menu, item, false); searchView.requestFocus(); } }); } 
+6
source share
1 answer

As for your published code, this is the result:

Toolbar with default SearchView AppCompat

As you can see, there are two fields on the left: the widget container and the zoom icon. This is why you have more white space than another title bar. And the menu items are pushed out of the toolbar, which, I think, is the default SearchView ActionView when it is not a CollapseActionView , so it fills the parent element.

From the source of the SearchView widget and its layout abc_search_view.xml, I tried to remove additional fields and not click on other elements outside the toolbar.
But after many manipulations, I think you should use your own widget and / or custom layout. Or play with setIconifiedByDefault(true) , which removes the enlargement icon and its additional margin and use setMaxWidth(MAX_SIZE) , where MAX_SIZE calculated dynamically on Integer.MAX_VALUE - (SIZE_OF_A_MENU_ITEM * NB_OF_MENU_ITEMS) ... But it takes a lot of work. So using a custom layout might be a solution.

However, there is a possible way to save the appcompat widget , some small workarounds. First, you can use CollapseActionView to avoid hitting other items.

 <item ... app:actionViewClass="android.support.v7.widget.SearchView" app:showAsAction="always|collapseActionView"/> 

And in order to support your requirements, you must expand it when you initialize it:

 final SearchView searchView = (SearchView) MenuItemCompat.getActionView(item); MenuItemCompat.expandActionView(item); 

Remember that you need to use setOnActionExpandListener() to close the window if you do not want to collapse the item. This sentence will give you this result:

Toolbar with SearchView AppCompat Extension

More extra fields, right? Thus, you should get the container and the enlargement icon with their identifiers (which you can find in abc_search_view.xml ... but let's save some time: they are R.id.search_edit_frame and R.id.search_mag_icon ). You can delete their fields using this method:

 private void changeSearchViewElements(View view) { if (view == null) return; if (view.getId() == R.id.search_edit_frame || view.getId() == R.id.search_mag_icon) { LinearLayout.LayoutParams p = (LinearLayout.LayoutParams) view.getLayoutParams(); p.leftMargin = 0; // set no left margin view.setLayoutParams(p); } if (view instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) view; for (int i = 0; i < viewGroup.getChildCount(); i++) { changeSearchViewElements(viewGroup.getChildAt(i)); } } } 

Calling it in a stream:

 final SearchView searchView = (SearchView) MenuItemCompat.getActionView(item); ... searchView.post(new Runnable() { @Override public void run() { changeSearchViewElements(searchView); } }); 

Here's the conclusion:

Toolbar with SearchView AppCompat without left margin

Finally, to get the line below the field, there is a possible workaround using 9-patch drawable and set as the background. You can easily find instructions on Google. Thus, the condition will be:

 private void changeSearchViewElements(View view) { ... if (view.getId() == R.id.search_edit_frame || view.getId() == R.id.search_mag_icon) { LinearLayout.LayoutParams p = (LinearLayout.LayoutParams) view.getLayoutParams(); p.leftMargin = 0; // set no left margin view.setLayoutParams(p); } else if (view.getId() == R.id.search_src_text) { AutoCompleteTextView searchEdit = (AutoCompleteTextView) view; searchEdit.setBackgroundResource(R.drawable.rect_underline_white); } ... } 

From the OP comment below, the underline can also be done with the following expression:

 searchView.findViewById(android.support.v7.appcompat.R.id.se‌​arch_src_text) .setBa‌​ckgroundResource(R.d‌​rawable.abc_textfiel‌​d_search_default_mtr‌​l_alpha); 

After these workarounds, as I said, it would be easier to use a custom layout. But if you want to keep the default SearchView widget, this might help.

+4
source

Source: https://habr.com/ru/post/1013355/


All Articles