Изменение фонового рисунка виджета searchview

Я пытаюсь изменить drawable, который сидит в виджетах виджета панели действий Android.

В настоящее время это выглядит так: Введите описание изображения здесь

Но мне нужно изменить синий фон, пригодный для красного цвета.

Я пробовал много вещей, не сводя свой собственный виджет поиска, но ничего не работает.

Может ли кто-нибудь указать мне в правильном направлении, чтобы изменить это?

Solutions Collecting From Web of "Изменение фонового рисунка виджета searchview"

вступление

К сожалению, нет способа установить SearchView текстового поля SearchView с использованием тем, стилей и наследования в XML, как вы можете сделать с фоном элементов в раскрывающемся списке ActionBar . Это связано с тем, что selectableItemBackground указан как стиль в R.stylable , тогда как searchViewTextField (атрибут темы, который нас интересует) не является. Таким образом, мы не можем легко получить доступ к ним из XML-ресурсов (вы получите No resource found that matches the given name: attr 'android:searchViewTextField' ).

Установка поля текстового поля SearchView из кода

Таким образом, единственный способ правильно заменить фон текстового поля SearchView – это войти в его внутренности, получить доступ к просмотру, который имеет набор фона, основанный на searchViewTextField и установить наш собственный.

ПРИМЕЧАНИЕ. Решение ниже зависит только от идентификатора ( android:id/search_plate ) элемента в SearchView , поэтому он более независим от SDK-версии, чем обход детей (например, с помощью searchView.getChildAt(0) чтобы перейти в правильное представление в SearchView ), но Он не пуленепробиваемый. Особенно, если какой-либо производитель решает переопределить внутренние SearchView а элемент с указанным выше идентификатором отсутствует – код не будет работать.

В SDK фон для текстового поля в SearchView объявлен через девять патчей , поэтому мы сделаем это точно так же. Вы можете найти оригинальные png- изображения в каталоге drawable-mdpi в хранилище git для Android . Нам интересно два изображения. Один для состояния, когда выбрано текстовое поле (с именем 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 недоступен через @android:drawable/textfield_search_default_holo_light , который может быть использован в селекторе, показанном ниже, вместо ссылки на локальный доступный.

ПРИМЕЧАНИЕ. Я использовал тему Holo Light в качестве базы, но вы можете сделать то же самое с Holo Dark . По-видимому, нет никакой реальной разницы в выбранных состояниях 9-патчей между темными и темными темами. Тем не менее, разница в 9-патчах для состояния по умолчанию (см. « Свет против тьмы» ). Таким образом, вероятно, нет необходимости создавать локальные копии 9-патчей для выбранного состояния , как для темных, так и для светлых тем (при условии, что вы хотите обрабатывать оба варианта, и сделать их одинаковыми, как в теме Holo ). Просто создайте одну локальную копию и используйте ее в селекторе, предназначенном для обеих тем.

Теперь вам нужно отредактировать загруженные девять патчей в соответствии с вашими потребностями (т. Е. Сменить синий цвет на красный). Вы можете посмотреть файл, используя инструмент draw 9-patch, чтобы проверить, правильно ли он определен после редактирования.

Я редактировал файлы с помощью GIMP с помощью инструмента с одним пиксельным карандашом (довольно легко), но вы, вероятно, будете использовать собственный инструмент. Вот мой настраиваемый 9-патч для сфокусированного состояния :

Введите описание изображения здесь

ПРИМЕЧАНИЕ. Для простоты я использовал только изображения для плотности mdpi . Вам нужно будет создать 9 патчей для множества плотностей экрана, если вы хотите получить лучший результат на любом устройстве. Изображения для Holo SearchView можно найти в mdpi , hdpi и xhdpi drawable .

Теперь нам нужно создать управляемый селектор, чтобы отображалось правильное изображение в зависимости от состояния представления. Создайте файл 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 – его id – 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 . В конструкторе SearchView можно найти строку, которая раздувает макет:

 inflater.inflate(R.layout.search_view, this, true); 

Теперь мы знаем, что макет SearchView находится в файле с именем res/layout/search_view.xml . Заглядывая в search_view.xml, мы можем найти внутренний элемент LinearLayout (с идентификатором 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 текущей темы.

Исследуйте атрибут (легко ли его можно настроить?)

Чтобы проверить, как 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 , но, к сожалению, это не так. Для сравнения см. Другие атрибуты темы, которые присутствуют как в theme.xml, так и в R.attr, например textAppearance или selectableItemBackground . Если searchViewTextField присутствовал в R.attrR.stylable ), мы могли бы просто использовать наш drawable селектор при определении темы для всего нашего приложения в 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 через код. Однако мы все еще не знаем, как это должно выглядеть. Короче говоря, мы ищем drawables, используемые в качестве значений по умолчанию: textfield_searchview_holo_dark.xml и textfield_searchview_holo_light.xml . Рассматривая контент, мы видим, что drawable – это selector который ссылается на два других drawables (которые позже будут на 9 патчей) в зависимости от состояния представления. Вы можете найти агрегированные 9-патч-черточки из (почти) всех версий Android на androiddrawables.com

Пользовательская настройка

Мы признаем синюю линию в одном из 9-патчей , поэтому мы создаем локальную копию и меняем цвета по желанию.

Вышеупомянутые решения могут не работать, если вы используете библиотеку appcompat. Возможно, вам придется изменить код, чтобы он работал в библиотеке appcompat.

Вот рабочее решение для библиотеки appcompat.

  @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main_menu, menu); SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); MenuItem searchMenuItem = menu.findItem(R.id.action_search); SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchMenuItem); searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName())); SearchView.SearchAutoComplete searchAutoComplete = (SearchView.SearchAutoComplete)searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text); searchAutoComplete.setHintTextColor(Color.WHITE); searchAutoComplete.setTextColor(Color.WHITE); View searchplate = (View)searchView.findViewById(android.support.v7.appcompat.R.id.search_plate); searchplate.setBackgroundResource(R.drawable.texfield_searchview_holo_light); ImageView searchCloseIcon = (ImageView)searchView.findViewById(android.support.v7.appcompat.R.id.search_close_btn); searchCloseIcon.setImageResource(R.drawable.abc_ic_clear_normal); ImageView voiceIcon = (ImageView)searchView.findViewById(android.support.v7.appcompat.R.id.search_voice_btn); voiceIcon.setImageResource(R.drawable.abc_ic_voice_search); ImageView searchIcon = (ImageView)searchView.findViewById(android.support.v7.appcompat.R.id.search_mag_icon); searchIcon.setImageResource(R.drawable.abc_ic_search); return super.onCreateOptionsMenu(menu); } 

Ваш метод onCreateOptionsMenu должен быть:

 @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.option, menu); SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView(); int linlayId = getResources().getIdentifier("android:id/search_plate", null, null); ViewGroup v = (ViewGroup) searchView.findViewById(linlayId); v.setBackgroundResource(R.drawable.searchviewredversion); return super.onCreateOptionsMenu(menu); } 

Где menu_search пункт поиска menu_search off

И здесь находится searchviewredversion (эта версия – версия xhdpi): http://img836.imageshack.us/img836/5964/searchviewredversion.png

Введите описание изображения здесь

Вышеприведенное решение не работает с ActionBarSherlock 4.2 и поэтому не поддерживает обратную совместимость с Android 2.x. Вот рабочий код, который настраивает фон SearchView и текст подсказки в ActionBarSherlock 4.2:

 public static void styleSearchView(SearchView searchView, Context context) { View searchPlate = searchView.findViewById(R.id.abs__search_plate); searchPlate.setBackgroundResource(R.drawable.your_custom_drawable); AutoCompleteTextView searchText = (AutoCompleteTextView) searchView.findViewById(R.id.abs__search_src_text); searchText.setHintTextColor(context.getResources().getColor(R.color.your_custom_color)); } 

Я тоже устал делать это, и я использую v7. Приложение было разбито, когда я попытался захватить searchPlate через getIdentifier() поэтому я сделал это следующим образом:

 View searchPlate = searchView.findViewById(android.support.v7.appcompat.R.id.search_plate); 

Сначала давайте создадим XML-файл с именем search_widget_background.xml, который будет использоваться в качестве переносимого, то есть под доступным каталогом.

 <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <solid android:color="@color/red" /> </shape> 

Этот drawable будет использоваться в качестве фона для нашего виджета поиска. Я установил цвет в красный цвет, потому что это то, о чем вы просили, но вы можете установить его на любой цвет, определенный тегом @color. Вы можете даже изменить его дальше, используя атрибуты, определенные для тега формы (сделайте закругленные углы, овальный фон и т. Д.).

Следующий шаг – установить фон нашего виджета поиска на этот. Это может быть выполнено следующим образом:

  public boolean onCreateOptionsMenu(Menu menu) { SearchView searchView = (SearchView)menu.findItem(R.id.my_search_view).getActionView(); Drawable d = getResources().getDrawable(R.drawable.search_widget_background); searchView.setBackground(d); ... } 

Я также столкнулся с той же проблемой. Я использовал библиотеку appcompat v7 и определил ее стиль. В выпадающей папке поместите файл bottom_border.xml, который выглядит так:

 <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android" > <item> <shape > <solid android:color="@color/blue_color" /> </shape> </item> <item android:bottom="0.8dp" android:left="0.8dp" android:right="0.8dp"> <shape > <solid android:color="@color/background_color" /> </shape> </item> <!-- draw another block to cut-off the left and right bars --> <item android:bottom="2.0dp"> <shape > <solid android:color="@color/main_accent" /> </shape> </item> </layer-list> 

В значениях папки styles_myactionbartheme.xml:

 <?xml version="1.0" encoding="utf-8"?> <resources> <style name="AppnewTheme" parent="Theme.AppCompat.Light"> <item name="android:windowBackground">@color/background</item> <item name="android:actionBarStyle">@style/ActionBar</item> <item name="android:actionBarWidgetTheme">@style/ActionBarWidget</item> </style> <!-- Actionbar Theme --> <style name="ActionBar" parent="Widget.AppCompat.Light.ActionBar.Solid.Inverse"> <item name="android:background">@color/main_accent</item> <!-- <item name="android:icon">@drawable/abc_ic_ab_back_holo_light</item> --> </style> <style name="ActionBarWidget" parent="Theme.AppCompat.Light"> <!-- SearchView customization--> <!-- Changing the small search icon when the view is expanded --> <!-- <item name="searchViewSearchIcon">@drawable/ic_action_search</item> --> <!-- Changing the cross icon to erase typed text --> <!-- <item name="searchViewCloseIcon">@drawable/ic_action_remove</item> --> <!-- Styling the background of the text field, ie blue bracket --> <item name="searchViewTextField">@drawable/bottom_border</item> <!-- Styling the text view that displays the typed text query --> <item name="searchViewAutoCompleteTextView">@style/AutoCompleteTextView</item> </style> <style name="AutoCompleteTextView" parent="Widget.AppCompat.Light.AutoCompleteTextView"> <item name="android:textColor">@color/text_color</item> <!-- <item name="android:textCursorDrawable">@null</item> --> <!-- <item name="android:textColorHighlight">@color/search_view_selected_text</item> --> </style> </resources> 

Я определил файл custommenu.xml для отображения меню:

 <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:com.example.actionbartheme="http://schemas.android.com/apk/res-auto" > <item android:id="@+id/search" android:title="@string/search_title" android:icon="@drawable/search_buttonn" com.example.actionbartheme:showAsAction="ifRoom|collapseActionView" com.example.actionbartheme:actionViewClass="android.support.v7.widget.SearchView"/> 

Ваша активность должна расширять ActionBarActivity вместо Activity.

 @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.custommenu, menu); } 

В файле манифеста:

 <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppnewTheme" > 

Для получения дополнительной информации см. Здесь:
Здесь http://www.jayway.com/2014/06/02/android-theming-the-actionbar/

 public boolean onCreateOptionsMenu(Menu menu) { ........ // Set the search plate color int linlayId = getResources().getIdentifier("android:id/search_plate", null, null); View view = searchView.findViewById(linlayId); Drawable drawColor = getResources().getDrawable(R.drawable.searchcolor); view.setBackground( drawColor ); ........ } 

И это файл searchablecolor.xml

 <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android" > <item> <shape > <solid android:color="#ffffff" /> </shape> </item> <!-- main color --> <item android:bottom="1.5dp" android:left="1.5dp" android:right="1.5dp"> <shape > <solid android:color="#2c4d8e" /> </shape> </item> <!-- draw another block to cut-off the left and right bars --> <item android:bottom="18.0dp"> <shape > <solid android:color="#2c4d8e" /> </shape> </item> </layer-list>