Вступ
На жаль, немає можливості встановити SearchViewстиль текстового поля за допомогою тем, стилів та успадкування в XML, як це можна зробити з фоном елементів у спадному меню ActionBar . Це відбувається тому , що selectableItemBackground перераховано як styleable дюйма R.stylable, в той час як searchViewTextField(атрибут теми , що ми зацікавлені в) немає. Таким чином, ми не можемо легко отримати доступ до нього з ресурсів XML (ви отримаєте No resource found that matches the given name: attr 'android:searchViewTextField'помилку).
Налаштування фону тексту коду SearchView з коду
Отже, єдиний спосіб належним чином замінити тло SearchViewтекстового поля - це потрапити у його внутрішні місця, отримати доступ до перегляду, який має фон, встановлений на основі, searchViewTextFieldі встановити власний.
ПРИМІТКА. Рішення нижче залежить лише від id ( android:id/search_plate) елемента всередині SearchView, тому вона є більш незалежною від SDK-версії, ніж прохідність дітей (наприклад, searchView.getChildAt(0)для отримання потрібного вигляду всередині SearchView), але це не є кулезахисним. Особливо, якщо якийсь виробник вирішить повторно заповнити внутрішні SearchViewелементи та елемента з вищезгаданим ідентифікатором, немає - код не працює.
У SDK фон для текстового поля в SearchViewдекларується через дев'ять патчів , тому ми будемо робити це так само. Ви можете знайти оригінальні зображення у форматі png у каталозі Dravable-mdpi у сховищі Android git . Нас цікавлять два зображення. Одне для стану, коли вибрано текстове поле (з ім'ям textfield_search_selected_holo_light.9.png ), і те, де його немає (з ім'ям textfield_search_default_holo_light.9.png ).
На жаль, вам доведеться створити локальні копії обох зображень, навіть якщо ви хочете налаштувати лише зосереджений стан. Це тому textfield_search_default_holo_light, що немає у R.drawable . Таким чином, це нелегко доступно через @android:drawable/textfield_search_default_holo_light, що може бути використане у показаному нижче селекторі, замість посилання на локальний малюнок.
ПРИМІТКА: Я використовував тему Holo Light як основу, але ви можете зробити те ж саме з Holo Dark . Здається, що немає жодної реальної різниці у вибраних станах 9-патчів між темами Light і Dark . Однак є різниця у 9-патчах за станом за замовчуванням (див. Світло проти Темного ). Тому, ймовірно, немає необхідності робити локальні копії 9-патчів для вибраного стану для темних і світлих тем (якщо припустити, що ви хочете обробити обидва та зробити так, щоб обидва виглядали так само, як у темі Holo ). Просто зробіть одну локальну копію та використовуйте їїперемикач для обох тем.
Тепер вам потрібно буде відредагувати завантажені дев'ять патчів відповідно до ваших потреб (тобто змінити синій колір на червоний). Ви можете переглянути файл за допомогою інструмента малювання 9-патчів, щоб перевірити, чи правильно він визначений після редагування.
Я редагував файли, використовуючи GIMP, інструментом для олівців з одним пікселем (досить легко), але ви, ймовірно, використовуєте власний інструмент. Ось мій індивідуальний 9-патч для зосередженого стану :

ПРИМІТКА. Для простоти я використовував лише зображення для щільності mdpi . Вам доведеться створити 9 патчів для різної щільності екрана, якщо ви хочете отримати найкращий результат на будь-якому пристрої. Зображення для Холо SearchView можуть бути знайдені в MDPI , ІПЧР і xhdpi витяжці.
Тепер нам знадобиться створити перетягувальний селектор, щоб правильно відображатись зображення залежно від стану перегляду. Створіть файл res/drawable/texfield_searchview_holo_light.xmlіз наступним вмістом:
<?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>
Ми будемо використовувати створений вище файл для LinearLayoutперегляду для встановлення фону для перегляду, який містить текстове поле в межах SearchView- його ідентифікатор є android:id/search_plate. Ось ось як це швидко зробити в коді під час створення меню параметрів:
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);
}
}
Кінцевий ефект
Ось скріншот кінцевого результату:

Як я дійшов до цього
Я думаю, що варто згадати, як я дійшов до цього, щоб цей підхід можна було використовувати при налаштуванні інших поглядів.
Перевірка макета перегляду
Я перевірив, як SearchViewвиглядає макет. У конвекторі SearchView можна знайти лінію, що надуває макет:
inflater.inflate(R.layout.search_view, this, true);
Тепер ми знаємо, що SearchViewмакет знаходиться у файлі з назвою res/layout/search_view.xml. Заглянувши в search_view.xml, ми можемо знайти внутрішній LinearLayoutелемент (з id search_plate), який є android.widget.SearchView$SearchAutoCompleteвсередині нього (виглядає як наше текстове поле перегляду пошуку):
<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">
Тепер ми тепер встановили фон на основі searchViewTextFieldатрибуту поточної теми .
Досліджуючий атрибут (чи легко його встановити?)
Щоб перевірити, як встановлено searchViewTextFieldатрибут, ми досліджуємо res / values / themes.xml . Існує група атрибутів, пов’язаних із SearchViewзамовчуванням 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>
Ми бачимо, що для теми за замовчуванням це значення @drawable/textfield_searchview_holo_dark. У цьому файлі також встановленоTheme.Light значення .
Тепер було б чудово, якби цей атрибут був доступний через R.styleable , але, на жаль, це не так. Для порівняння див. Інші атрибути теми, які присутні як у themes.xml та R.attr, як textAppearance або selectableItemBackground . Якщо він searchViewTextFieldбув присутній в R.attr(і R.stylable), ми можемо просто використовувати наш графічний селектор, визначаючи тему для всієї нашої програми в XML. Наприклад:
<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>
Що слід змінити?
Тепер ми знаємо, що нам доведеться отримати доступ search_plateчерез код. Однак ми досі не знаємо, як це має виглядати. Коротше кажучи, ми шукаємо рисунки, які використовуються як значення у темах за замовчуванням: textfield_searchview_holo_dark.xml та textfield_searchview_holo_light.xml . Дивлячись на вміст, ми бачимо, що тематичне зображення, selectorяке посилається на два інші малюнки (які, можливо, пізніше будуть 9-латними), базується на стані перегляду. На сайті androiddrawables.com ви можете знайти зведені 9 патчі з чернетки (майже) всієї версії Android
Налаштування
Ми розпізнаємо синю лінію в одному з 9-ти патчів , тому створюємо локальну її копію та змінюємо кольори за бажанням.