Correct implementation of SearchView in android toolbar

I have a problem with searchview implementation in android toolbar.

  • The empty space padding is too big.
  • I don't want to hide other actions, but these actions are overlapped by SearchView.
  • SearchView's underline is not visible
  • How do i fix issues mentioned above ?

    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();
            }
        });
    }
    

    Regarding your posted code, this is the output:

    工具栏默认使用SearchView AppCompat

    As you can see, there is two left margins: the widget's container and the magnify icon. This is why you have an empty space bigger than an another window with a title. And the menu items are pushed outside the toolbar which, I think, it's the default SearchView ActionView when it's not a CollapseActionView so it fills the parent.

    From the source of SearchView widget and its layout abc_search_view.xml, I tried to remove the extra margins and avoid pushing the other items outside the toolbar.
    But after many manipulations, my guess is you have to use a custom widget and/or a custom layout. Or to play with setIconifiedByDefault(true) which removes the magnify icon and its extra margin and to use setMaxWidth(MAX_SIZE) where MAX_SIZE is calculated dynamically by Integer.MAX_VALUE - (SIZE_OF_A_MENU_ITEM * NB_OF_MENU_ITEMS) ... But it requires a lot of work for nothing. So using a custom layout could be the solution.

    However, there is a possible way to keep the appcompat widget , some little workarounds. First, to avoid puhsing out the other items, you can use the CollapseActionView .

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

    And to maintain your requirements, you have to expand it when you initialize it:

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

    Be aware that you have to use setOnActionExpandListener() in order to close the window if you don't want to collapse the item. This suggestion will give you this result:

    带有SearchView AppCompat的工具栏已展开

    Still the extra margins, right? Therefore, you have to retrieve the container and the magnify icon by their ids (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 remove their margins by 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));
            }
        }
    }
    

    By calling it in a thread:

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

    Here's the output:

    带有SearchView AppCompat的工具栏,不带左边距

    Finally, to get the line under the field, there is a possible workaround as using a 9-patch drawable and set it as a background. You can easily find how-to on Google. So 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's comment below, the underline's field can also be done with the following statement:

    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 might be easier to use a custom layout. But if you want to keep the default SearchView widget, this might help.

    链接地址: http://www.djcxy.com/p/94484.html

    上一篇: 理解Scala中的类型推理

    下一篇: 在android工具栏中正确实施SearchView