Intro
Sfortunatamente non c'è modo di impostare lo SearchViewstile del campo di testo usando temi, stili ed ereditarietà in XML come puoi fare con lo sfondo degli elementi nel menu a discesa ActionBar . Questo perché selectableItemBackground è elencato come stilizzabile in R.stylable, mentre searchViewTextField(attributo del tema a cui siamo interessati) non lo è. Pertanto, non possiamo accedervi facilmente dalle risorse XML (riceverai un No resource found that matches the given name: attr 'android:searchViewTextField'errore).
Impostazione dello sfondo del campo di testo di SearchView dal codice
Quindi, l'unico modo per sostituire correttamente lo sfondo del SearchViewcampo di testo è entrare nei suoi interni, acquisire l'accesso alla visualizzazione che ha lo sfondo impostato in base searchViewTextFielde impostare il nostro.
NOTA: la soluzione seguente dipende solo dall'id ( android:id/search_plate) dell'elemento all'interno SearchView, quindi è più indipendente dalla versione dell'SDK rispetto all'attraversamento dei figli (ad esempio, utilizzando searchView.getChildAt(0)per arrivare alla vista giusta all'interno SearchView), ma non è a prova di proiettile. Soprattutto se qualche produttore decide di reimplementare gli interni SearchViewe l'elemento con l'ID sopra menzionato non è presente, il codice non funzionerà.
In SDK, lo sfondo del campo di testo in SearchViewè dichiarato tramite nove patch , quindi lo faremo allo stesso modo. Puoi trovare immagini png originali nella directory drawable-mdpi del repository git di Android . Ci interessano due immagini. Uno per lo stato in cui il campo di testo è selezionato (denominato textfield_search_selected_holo_light.9.png ) e uno per dove non lo è (denominato textfield_search_default_holo_light.9.png ).
Sfortunatamente, dovrai creare copie locali di entrambe le immagini, anche se desideri personalizzare solo lo stato focalizzato . Questo perché textfield_search_default_holo_lightnon è presente in R.drawable . Pertanto non è facilmente accessibile tramite @android:drawable/textfield_search_default_holo_light, che potrebbe essere utilizzato nel selettore mostrato di seguito, invece di fare riferimento al drawable locale.
NOTA: stavo usando il tema Holo Light come base, ma puoi fare lo stesso con Holo Dark . Sembra che non ci sia alcuna reale differenza nelle 9 patch di stato selezionate tra i temi Chiaro e Scuro . Tuttavia, c'è una differenza in 9 patch per lo stato predefinito (vedi Chiaro vs Scuro ). Quindi, probabilmente non è necessario creare copie locali di 9 patch per lo stato selezionato , sia per i temi Dark che per quelli Light (supponendo che tu voglia gestirli entrambi e farli sembrare entrambi uguali a Holo Theme ). Basta fare una copia locale e usarla in formatoselettore disegnabile per entrambi i temi.
Ora, dovrai modificare le nove patch scaricate secondo le tue necessità (cioè cambiare il colore blu in rosso). Puoi dare un'occhiata al file usando lo strumento Draw 9-patch per verificare se è definito correttamente dopo la tua modifica.
Ho modificato i file usando GIMP con lo strumento matita da un pixel (abbastanza facile) ma probabilmente userete lo strumento da soli. Ecco la mia patch 9 personalizzata per lo stato focalizzato :

NOTA: per semplicità, ho utilizzato solo immagini per la densità mdpi . Dovrai creare 9 patch per più densità dello schermo se desideri il miglior risultato su qualsiasi dispositivo. Le immagini per Holo SearchView possono essere trovate in mdpi , hdpi e xhdpi disegnabili.
Ora, dobbiamo creare un selettore disegnabile, in modo che l'immagine corretta venga visualizzata in base allo stato di visualizzazione. Crea file res/drawable/texfield_searchview_holo_light.xmlcon il seguente contenuto:
<?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>
Useremo il disegnabile creato sopra per impostare lo sfondo per la LinearLayoutvista che contiene il campo di testo all'interno SearchView- il suo ID è android:id/search_plate. Quindi, ecco come farlo rapidamente nel codice, durante la creazione del menu delle opzioni:
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);
}
}
Effetto finale
Ecco lo screenshot del risultato finale:

Come ci sono arrivato
Penso che valga la pena conoscere come sono arrivato a questo, in modo che questo approccio possa essere utilizzato quando si personalizzano altre visualizzazioni.
Verifica del layout di visualizzazione
Ho controllato l' SearchViewaspetto del layout. Nel costruttore di SearchView si può trovare una linea che gonfia il layout:
inflater.inflate(R.layout.search_view, this, true);
Ora sappiamo che il SearchViewlayout è nel file denominato res/layout/search_view.xml. Esaminando search_view.xml possiamo trovare un LinearLayoutelemento interno (con id search_plate) che ha android.widget.SearchView$SearchAutoCompleteal suo interno (sembra il nostro campo di testo della vista di ricerca):
<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">
Ora, ora che lo sfondo è impostato in base searchViewTextFieldall'attributo del tema corrente .
Attributo investigativo (è facilmente impostabile?)
Per verificare come searchViewTextFieldè impostato l'attributo, esaminiamo res / values / themes.xml . C'è un gruppo di attributi correlati a SearchViewin impostazione predefinita 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>
Vediamo che per il tema predefinito il valore è @drawable/textfield_searchview_holo_dark. Anche il Theme.Lightvalore è impostato in quel file .
Ora, sarebbe fantastico se questo attributo fosse accessibile tramite R.styleable , ma sfortunatamente non lo è. Per fare un confronto, Altri tema attributi che sono presenti sia in themes.xml e R.attr come textAppearance o selectableItemBackground . Se searchViewTextFieldfosse presente in R.attr(e R.stylable) potremmo semplicemente usare il nostro selettore disegnabile quando definiamo il tema per l'intera nostra applicazione in XML. Per esempio:
<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>
Cosa dovrebbe essere modificato?
Ora sappiamo che dovremo accedere search_platetramite codice. Tuttavia, non sappiamo ancora come dovrebbe essere. In breve, cerchiamo i drawable usati come valori nei temi predefiniti: textfield_searchview_holo_dark.xml e textfield_searchview_holo_light.xml . Guardando il contenuto vediamo che il drawable fa selectorriferimento ad altri due drawable (che successivamente saranno 9 patch) in base allo stato di visualizzazione. Puoi trovare 9 patch estraibili aggregate da (quasi) tutte le versioni di Android su androiddrawables.com
Personalizzazione
Riconosciamo la linea blu in una delle 9 patch , quindi ne creiamo una copia locale e cambiamo i colori come desiderato.