7 votes

Implémentation correcte de SearchView dans la barre d'outils Android

J'ai un problème avec l'implémentation du searchview dans la barre d'outils Android.

  1. Le remplissage de l'espace vide est trop grand.
  2. Je ne veux pas cacher d'autres actions, mais ces actions sont superposées par SearchView.
  3. Le soulignement de la SearchView n'est pas visible

Comment puis-je résoudre les problèmes mentionnés ci-dessus ?

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

5voto

Fllo Points 7858

En ce qui concerne le code que vous avez affiché, voici le résultat :

Toolbar with SearchView AppCompat by default

Comme vous pouvez le voir, il y a deux marges de gauche : le conteneur du widget et l'icône d'agrandissement. C'est pourquoi vous avez un espace vide plus grand qu'une autre fenêtre avec un titre. Et les éléments du menu sont poussés à l'extérieur de la barre d'outils qui, je pense, est le SearchView par défaut. ActionView quand il ne s'agit pas d'un CollapseActionView pour qu'il remplisse le parent.

De la source de SearchView widget et sa mise en page abc_search_view.xml J'ai essayé de supprimer les marges supplémentaires et d'éviter de pousser les autres éléments en dehors de la barre d'outils.
Mais après de nombreuses manipulations, je pense que vous devez utiliser un widget personnalisé et/ou une mise en page personnalisée. Ou jouer avec setIconifiedByDefault(true) qui supprime l'icône de loupe et sa marge supplémentaire et d'utiliser setMaxWidth(MAX_SIZE) donde MAX_SIZE est calculé dynamiquement par Integer.MAX_VALUE - (SIZE_OF_A_MENU_ITEM * NB_OF_MENU_ITEMS) ... Mais cela demande beaucoup de travail pour rien. L'utilisation d'une mise en page personnalisée pourrait donc être la solution.

Cependant, il existe une possibilité de conserver le widget appcompat quelques petites solutions de contournement. Tout d'abord, pour éviter de faire sortir les autres éléments, vous pouvez utiliser la fonction CollapseActionView .

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

Et pour maintenir vos exigences, vous devez l'étendre lorsque vous l'initialisez :

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

Sachez que vous devez utiliser setOnActionExpandListener() afin de fermer la fenêtre si vous ne voulez pas réduire l'élément. Cette suggestion vous donnera ce résultat :

Toolbar with SearchView AppCompat expanded

Toujours les marges supplémentaires, non ? Par conséquent, vous devez récupérer le conteneur et l'icône de loupe par leurs ids (que vous pouvez trouver dans abc_search_view.xml ... mais gagnons du temps : ils sont R.id.search_edit_frame y R.id.search_mag_icon ). Vous pouvez supprimer leurs marges en utilisant cette méthode :

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

En l'appelant dans un fil :

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

Voici le résultat :

Toolbar with SearchView AppCompat without left margin

Enfin, pour obtenir la ligne sous le champ, il est possible de contourner le problème en utilisant un dessinable 9-patch et en le définissant comme arrière-plan. Vous pouvez facilement trouver le mode d'emploi sur Google. La condition sera donc la suivante :

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

D'après le commentaire de l'OP ci-dessous, le champ de soulignement peut aussi être fait avec la déclaration suivante :

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

Après ces solutions de contournement, comme je l'ai dit, il pourrait être plus facile d'utiliser une mise en page personnalisée. Mais si vous souhaitez conserver le widget SearchView par défaut, ceci pourrait vous aider.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X