Intro
Malheureusement, il n'y a aucun moyen de définir SearchView
le style des champs de texte à l'aide de thèmes, de styles et de l'héritage en XML, comme vous le souhaitez peut faire avec l'arrière-plan des éléments dans le dropdown de la barre d'action . Cela s'explique par le fait que selectableItemBackground
est listé comme pouvant être stylé en R.stylable
alors que searchViewTextField
(attribut du thème qui nous intéresse) ne l'est pas. Ainsi, nous ne pouvons pas y accéder facilement à partir des ressources XML (vous obtiendrez un message d'erreur No resource found that matches the given name: attr 'android:searchViewTextField'
erreur).
Définir l'arrière-plan du champ de texte SearchView à partir du code
Donc, la seule façon de substituer correctement le fond d'écran de SearchView
est d'entrer dans son fonctionnement interne, d'obtenir l'accès à une vue dont l'arrière-plan est défini sur la base de l'arrière-plan du champ de texte. searchViewTextField
et de fixer les nôtres.
NOTE : La solution ci-dessous ne dépend que de l'id ( android:id/search_plate
) de l'élément dans SearchView
Il s'agit donc d'une méthode plus indépendante de la version du SDK que la traversée des enfants (par exemple, en utilisant la fonction searchView.getChildAt(0)
pour arriver à la bonne vue dans SearchView
), mais ce n'est pas à l'épreuve des balles. En particulier si un fabricant décide de réimplémenter des éléments internes de SearchView
et l'élément avec l'id mentionné ci-dessus n'est pas présent - le code ne fonctionnera pas.
Dans le SDK, l'arrière-plan du champ de texte dans la zone SearchView
est déclaré par le biais de neuf pattes alors on va faire de même. Vous pouvez trouver l'original png images en drawable-mdpi répertoire de Dépôt git Android . Nous sommes intéressés par deux images. L'une pour l'état lorsque le champ de texte est sélectionné (nommée textfield_search_selected_holo_light.9.png ) et un autre pour les endroits où il ne l'est pas (nommé textfield_search_default_holo_light.9.png ).
Malheureusement, vous devrez créer des copies locales des deux images, même si vous ne souhaitez personnaliser que l'image de l'entreprise. ciblé l'état. Cela s'explique par le fait que textfield_search_default_holo_light
n'est pas présent dans R.drawable . Il n'est donc pas facilement accessible par @android:drawable/textfield_search_default_holo_light
qui pourrait être utilisé dans le sélecteur ci-dessous, au lieu de faire référence à la drawable locale.
NOTE : J'utilisais Holo Light comme base, mais vous pouvez faire la même chose avec Holo Dark . Il semble qu'il n'y ait pas de réelle différence dans état sélectionné 9-patchs entre Lumière y Dark thèmes. Cependant, il y a une différence dans les 9-patches pour état par défaut (voir Lumière vs Dark ). Ainsi, il n'est probablement pas nécessaire de faire des copies locales de 9-patches pour état sélectionné pour les deux Dark y Lumière (en supposant que vous souhaitiez les gérer tous les deux et leur donner la même apparence qu'en Thème Holo ). Il suffit de faire une copie locale et de l'utiliser dans sélectionnable pour les deux thèmes.
Maintenant, vous devez modifier les neuf patchs téléchargés selon vos besoins (par exemple, changer la couleur bleue en rouge). Vous pouvez jeter un coup d'oeil au fichier en utilisant dessiner l'outil 9-patch pour vérifier s'il est correctement défini après votre modification.
J'ai édité des fichiers en utilisant GIMP avec l'outil crayon à un pixel (assez facile) mais vous utiliserez probablement l'outil de votre choix. Voici mon 9-patch personnalisé pour état ciblé :
NOTE : Pour simplifier, j'ai utilisé uniquement des images pour mdpi densité. Vous devrez créer 9 patchs pour plusieurs densités d'écran si vous voulez obtenir le meilleur résultat sur n'importe quel appareil. Images pour Holo SearchView
peuvent être trouvés dans mdpi , hdpi y xhdpi traçable.
Maintenant, nous devons créer un sélecteur drawable, afin que l'image appropriée soit affichée en fonction de l'état de la vue. Créer le fichier res/drawable/texfield_searchview_holo_light.xml
avec le contenu suivant :
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true"
android:drawable="@drawable/textfield_search_selected_holo_light" />
<item android:drawable="@drawable/textfield_search_default_holo_light" />
</selector>
Nous utiliserons la table de dessin créée ci-dessus pour définir l'arrière-plan de la table de dessin. LinearLayout
qui contient un champ de texte dans SearchView
- son identifiant est android:id/search_plate
. Voici donc comment faire cela rapidement en code, lors de la création du menu d'options :
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
// Getting SearchView from XML layout by id defined there - my_search_view in this case
SearchView searchView = (SearchView) menu.findItem(R.id.my_search_view).getActionView();
// Getting id for 'search_plate' - the id is part of generate R file,
// so we have to get id on runtime.
int searchPlateId = searchView.getContext().getResources().getIdentifier("android:id/search_plate", null, null);
// Getting the 'search_plate' LinearLayout.
View searchPlate = searchView.findViewById(searchPlateId);
// Setting background of 'search_plate' to earlier defined drawable.
searchPlate.setBackgroundResource(R.drawable.textfield_searchview_holo_light);
return super.onCreateOptionsMenu(menu);
}
}
Effet final
Voici la capture d'écran du résultat final :
Comment j'en suis arrivé là
Je pense que cela vaut la peine de mentionner comment j'en suis arrivé là, afin que cette approche puisse être utilisée lors de la personnalisation d'autres vues.
Vérification de la disposition des vues
J'ai vérifié comment SearchView
la disposition ressemble. Sur Contructeur SearchView on peut trouver une ligne qui gonfle la mise en page :
inflater.inflate(R.layout.search_view, this, true);
Nous savons maintenant que SearchView
est dans un fichier nommé res/layout/search_view.xml
. En regardant dans vue_de_recherche.xml nous pouvons trouver un LinearLayout
(avec l'id search_plate
) qui a android.widget.SearchView$SearchAutoComplete
à l'intérieur (ressemble à notre champ de texte de la vue de recherche) :
<LinearLayout
android:id="@+id/search_plate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:orientation="horizontal"
android:background="?android:attr/searchViewTextField">
Maintenant, nous savons que l'arrière-plan est défini sur la base du thème actuel. searchViewTextField
attribut.
Recherche d'un attribut (est-il facilement paramétrable ?)
Pour vérifier comment searchViewTextField
est défini, nous examinons res/values/themes.xml . Il y a un groupe d'attributs liés à SearchView
par défaut Theme
:
<style name="Theme">
<!-- (...other attributes present here...) -->
<!-- SearchView attributes -->
<item name="searchDropdownBackground">@android:drawable/spinner_dropdown_background</item>
<item name="searchViewTextField">@drawable/textfield_searchview_holo_dark</item>
<item name="searchViewTextFieldRight">@drawable/textfield_searchview_right_holo_dark</item>
<item name="searchViewCloseIcon">@android:drawable/ic_clear</item>
<item name="searchViewSearchIcon">@android:drawable/ic_search</item>
<item name="searchViewGoIcon">@android:drawable/ic_go</item>
<item name="searchViewVoiceIcon">@android:drawable/ic_voice_search</item>
<item name="searchViewEditQuery">@android:drawable/ic_commit_search_api_holo_dark</item>
<item name="searchViewEditQueryBackground">?attr/selectableItemBackground</item>
Nous voyons que pour le thème par défaut la valeur est @drawable/textfield_searchview_holo_dark
. Pour Theme.Light
valeur est également défini dans ce fichier .
Maintenant, ce serait bien si cet attribut était accessible par le biais de R.stylisable mais, malheureusement, ce n'est pas le cas. Pour comparaison, voir d'autres thème qui sont présents à la fois dans thèmes.xml y R.attr comme apparence du texte o selectableItemBackground . Si searchViewTextField
était présent dans R.attr
(y R.stylable
), nous pourrions simplement utiliser notre sélecteur drawable lors de la définition du thème de l'ensemble de notre application en XML. Par exemple :
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="AppTheme" parent="android:Theme.Light">
<item name="android:searchViewTextField">@drawable/textfield_searchview_holo_light</item>
</style>
</resources>
Qu'est-ce qui doit être modifié ?
Maintenant nous savons, que nous devrons accéder search_plate
par le biais du code. Cependant, nous ne savons toujours pas à quoi cela devrait ressembler. En bref, nous recherchons les drawables utilisés comme valeurs dans les thèmes par défaut : textfield_searchview_holo_dark.xml y textfield_searchview_holo_light.xml . En regardant le contenu, nous voyons que le drawable est selector
qui font référence à deux autres objets dessinés (qui deviendront plus tard des "9-patches") en fonction de l'état de la vue. Vous pouvez trouver des graphiques 9-patchs agrégés pour (presque) toutes les versions d'Android à l'adresse suivante androiddrawables.com
Personnalisation de
Nous reconnaissons la ligne bleue dans une des 9 pièces Nous créons donc une copie locale et changeons les couleurs comme nous le souhaitons.
1 votes
Je crois ce poste SO peut vous aider dans ce que vous voulez accomplir, si vous ne l'avez pas déjà consulté.
0 votes
@Angelo Malheureusement, ceci n'est pas possible avec
SearchView
fond parce qu'il n'est pas disponible par l'intermédiaire deR.styleable
. Ma réponse ci-dessous décrit comment le faire en code.0 votes
Comment avez-vous obtenu le texte "Enter film name" ?
0 votes
Vous pouvez définir le texte de l'indice dans la vue de recherche comme suit : SearchView.SearchAutoComplete searchAutoComplete = (SearchView.SearchAutoComplete) searchView.findViewById(Android.support.v7.appcompat.R.id.search_src_text) ; searchAutoComplete.setHint("hint text") ;
0 votes
J'ai expliqué à la fin de ce post. avec des images https://stackoverflow.com/questions/47426541/how-to-change-searchbar-cancel-button-image-in-xamarin-forms/51297028#51297028