Изменение TextColor в SearchView с помощью панели инструментов Android

У меня есть следующая проблема. Я установил свой Actionbar для использования панели инструментов вместо использования API 21 с помощью appcompat-v7: 21. Тег textColorPrimary настроен на использование цвета @android:color/white , поэтому все заголовки на новой панели инструментов Android будут иметь белый цвет текста (насколько это хорошо).

Теперь я добавил SearchView и настроил для него настраиваемый фон следующим образом:

 <style name="AppTheme.Base" parent="Theme.AppCompat.Light"> <item name="colorPrimary">@color/action_bar_background</item> <item name="colorPrimaryDark">@color/status_background</item> <item name="android:windowNoTitle">true</item> <item name="windowActionBar">false</item> <item name="android:textColorPrimary">@android:color/white</item> <item name="searchViewStyle">@style/SearchViewStyle</item> </style> <style name="SearchViewStyle" parent="Widget.AppCompat.SearchView"> <item name="queryBackground">@drawable/search_background</item> <item name="searchIcon">@drawable/icon_search</item> </style> 

Выделенный @drawable/search_background – это простой белый прямоугольник. Так угадайте, что? Поскольку цвет текста заголовка на панели инструментов белый, теперь цвет текста в SearchView также белый, а поскольку фон SearchView представляет собой белый прямоугольник, пользователь не может видеть, что он печатает.

Мой вопрос: как я могу иметь разные цвета текста для заголовка панели инструментов Android и текста SearchView?

После некоторых исследований я нашел безопасный способ сделать это.

Копаясь в стилях SearchView, я нашел макет, который используется для отображения SearchView. Внутри этого макета есть TextView (фактическое поле, в которое вы вводите SearchView)

 <TextView android:id="@+id/search_badge" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center_vertical" android:layout_marginBottom="2dip" android:drawablePadding="0dip" android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="?android:attr/textColorPrimary" android:visibility="gone" /> 

Обратите внимание на поле android:textColor="?android:attr/textColorPrimary" . Это вызывает проблему, которую я изначально имел, цвет текста в SearchView такой же, как тот, который определен для цвета текста заголовка на панели инструментов Android.

Теперь есть несколько решений, которые могут работать здесь , но я думаю, что большинство этих решений имеют одинаковую проблему. Все они полагаются на идентификатор TextView, чтобы получить доступ к представлению и изменить цвет текста, как описано здесь.

Лично я считаю, что hardcoding идентификатор TextView внутри кода очень рискован, потому что мы не знаем, будет ли в будущем Google использовать другое значение id для этого представления, в этом случае наш код будет сломан.

По этой причине я создал рекурсивный метод, который получает объект TextView в SearchView и меняет цвет на все, что мы хотим.

 @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); menu.clear(); inflater.inflate(R.menu.search, menu); SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView(); searchView.setOnQueryTextListener(new SearchTextListener()); changeSearchViewTextColor(searchView); } private void changeSearchViewTextColor(View view) { if (view != null) { if (view instanceof TextView) { ((TextView) view).setTextColor(Color.BLACK); return; } else if (view instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) view; for (int i = 0; i < viewGroup.getChildCount(); i++) { changeSearchViewTextColor(viewGroup.getChildAt(i)); } } } } 

Я тестировал этот код с помощью API 21 с помощью панели инструментов, имея цвет текста текста панели инструментов, белый, и настраивая цвет текста SearchView на черный, и он отлично работает. Кроме того, когда мы напрямую обращаемся к объекту TextView, мы можем изменить подсказки, чертежи, paddings и все, что связано с TextView.

Решение @David_E работает, но есть и другой способ. Вы также можете определить пользовательский макет:

 <style name=”MySearchViewStyle” parent=”Widget.AppCompat.SearchView”> <item name="layout">@layout/my_Search_view</item> </style> 

Затем вы можете взять файл макета по умолчанию, который вы можете найти по имени: abc_search_view.xml , который используется для поиска и его изменения.

Это можно сделать исключительно в XML с помощью ThemeOverlay :

 <style name="ThemeOverlay.MyApp.ActionBar" parent="ThemeOverlay.AppCompat.ActionBar"> <item name="autoCompleteTextViewStyle">@style/Widget.MyApp.AutoCompleteTextView.SearchView</item> <item name="searchViewStyle">@style/Widget.MyApp.SearchView</item> </style> <style name="Widget.MyApp.AutoCompleteTextView.SearchView" parent="Widget.AppCompat.AutoCompleteTextView"> <item name="android:textColor">#000</item> <item name="android:textColorHint">#5000</item> </style> <style name="Widget.MyApp.SearchView" parent="Widget.AppCompat.SearchView"> <item name="queryBackground">@drawable/search_background</item> <item name="searchIcon">@drawable/icon_search</item> </style> 

А затем в вашем файле макета:

 <android.support.v7.widget.Toolbar app:theme="@style/ThemeOverlay.MyApp.ActionBar" ... /> 

Если вы также хотите, чтобы он применялся к действиям, которые используют ActionBar вместо ToolBar , вы можете добавить это в тему Activity :

 <style name="Theme.MyApp" parent="Theme.AppCompat"> <item name="actionBarTheme">@style/ThemeOverlay.MyApp.ActionBar</item> ... </style> 

Просто измените или добавьте android:textcolorPrimary в свои стили, все ваши стили в некоторых случаях. Ват, который вы выбрали для этого элемента, будет цветом вашего текста searchview .

Вам нужно установить атрибут editTextColor в стиле, чтобы изменить его с помощью XML.

 <style name="SearchViewStyle" parent="Widget.AppCompat.SearchView"> <item name="android:editTextColor">@color/some_color</item> </style> 

И вы применяете этот стиль к SearchView в макете.

 <android.support.v7.widget.Toolbar> <android.support.v7.widget.SearchView android:theme="@style/SearchViewStyle" /> </android.support.v7.widget.Toolbar>