검색 창 위젯의 배경 드로어 블 변경
Android 작업 표시 줄 검색보기 위젯에있는 드로어 블을 변경하려고합니다.
현재 다음과 같습니다. 
파란색 배경 드로어 블을 빨간색으로 변경해야합니다.
내 검색 위젯을 굴리지 않고 많은 것을 시도했지만 아무것도 작동하지 않는 것 같습니다.
누군가가 이것을 바꾸는 올바른 방향으로 나를 가리킬 수 있습니까?
소개
불행히도 ActionBar 드롭 다운의 항목 배경SearchView 으로 할 수 있듯이 XML의 테마, 스타일 및 상속을 사용하여 텍스트 필드 스타일 을 설정할 수있는 방법이 없습니다 . 때문이다 selectableItemBackground styleable로 나열되어 있는 R.stylable반면, searchViewTextField(우리가 관심이 있다는 것을 테마 속성)되지 않습니다. 따라서 XML 리소스 내에서 쉽게 액세스 할 수 없습니다 ( No resource found that matches the given name: attr 'android:searchViewTextField'오류가 발생 함).
코드에서 SearchView 텍스트 필드 배경 설정
따라서 SearchView텍스트 필드의 배경을 올바르게 대체하는 유일한 방법 은 내부로 들어가 배경을 기반으로 searchViewTextField설정하고 자체 설정 한 뷰에 액세스하는 것입니다.
참고 : 아래 솔루션 android:id/search_plate은 내의 element의 id ( ) 에만 의존 SearchView하므로 어린이 순회보다 SDK 버전에 더 독립적이지만 (예 : searchView.getChildAt(0)에서 올바른 뷰를 얻는 데 사용 SearchView) 방탄하지는 않습니다. 특히 일부 제조업체가 내부를 다시 구현하기로 결정 SearchView하고 위에서 언급 한 ID를 가진 요소가 존재하지 않으면 코드가 작동하지 않습니다.
SDK에서 텍스트 필드의 배경은 nine-patches를SearchView 통해 선언 되므로 동일한 방식으로 수행합니다. Android git repository 의 drawable-mdpi 디렉토리 에서 원본 png 이미지를 찾을 수 있습니다 . 우리는 두 가지 이미지에 관심이 있습니다. 하나는 텍스트 필드를 선택했을 때의 상태 (이름이 textfield_search_selected_holo_light.9.png )이고 다른 하나는 이름이없는 곳 (이름은 textfield_search_default_holo_light.9.png )입니다.
불행하게도, 집중된 상태 만 사용자 정의하려는 경우에도 두 이미지의 로컬 사본을 작성해야합니다 . R.drawable에 없기 때문 textfield_search_default_holo_light입니다 . 따라서 로컬 드로어 블을 참조하는 대신 아래에 표시된 선택기에서 사용할 수 있는를 통해 쉽게 액세스 할 수 없습니다 .@android:drawable/textfield_search_default_holo_light
참고 : 내가 사용했다 홀로 빛의 기지로 테마를하지만과 동일 할 수 홀로 어둠 . 밝은 테마 와 어두운 테마 사이의 선택된 상태 9 패치 에는 실질적인 차이가없는 것 같습니다 . 그러나 기본 상태에 대한 9 패치에는 차이가 있습니다 ( Light vs Dark 참조 ). 따라서 어둡 거나 밝은 테마 모두에 대해 선택한 상태 에 대해 9 패치의 로컬 사본을 만들 필요가 없습니다 ( 두 테마 를 모두 처리하고 Holo 테마 와 동일하게 가정한다고 가정 ). 하나의 로컬 사본을 만들어서 사용하십시오.두 테마 모두에 대한 선택기 드로어 블 .
이제 다운로드 한 9 개의 패치를 필요에 따라 편집해야합니다 (예 : 파란색을 빨간색으로 변경). draw 9-patch 도구 를 사용하여 파일을보고 편집 후에 올바르게 정의되었는지 확인할 수 있습니다.
1 픽셀 연필 도구로 김프 를 사용하여 파일을 편집 했지만 (아주 쉬움) 아마도 자신 만의 도구를 사용하게 될 것입니다. 다음은 집중 상태에 대한 맞춤형 9 패치입니다 .

참고 : 간단하게하기 위해 mdpi 밀도에 이미지 만 사용했습니다 . 모든 장치에서 최상의 결과를 얻으려면 여러 화면 밀도에 대해 9 패치 를 만들어야 합니다. Holo 이미지 SearchView는 mdpi , hdpi 및 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텍스트 필드를 보유 하는 뷰의 배경을 설정합니다 . SearchViewid는 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 의 (거의) 모든 버전의 Android에서 집계 된 9 패치 드로어 블을 찾을 수 있습니다
커스터마이징
우리 는 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벗어난 곳
그리고 여기 searchviewredversion(이것은 xhdpi 버전입니다) : http://img836.imageshack.us/img836/5964/searchviewredversion.png

위의 솔루션은 ActionBarSherlock 4.2에서 작동하지 않으므로 Android 2.x와 호환되지 않습니다. 다음은 ActionBarSherlock 4.2에서 SearchView 배경 및 힌트 텍스트를 설정하는 작업 코드입니다.
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);
나는 또한 같은 문제에 직면했다 .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, i.e. 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를 확장해야합니다.
@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/
먼저 drawable 디렉토리, 즉 drawable 디렉토리 아래에 사용할 search_widget_background.xml이라는 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>
This drawable will be used as the background for our search widget. I set the color to red because that's what you asked for, but you can set it to any color defined by @color tag. You can even modify it further using the attributes defined for shape tag (make rounded corners, do an oval background, etc.).
Next step is to set the background of our search widget to this one. This can be accomplished by the following:
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);
...
}
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 );
........
}
and this is the searchablecolor.xml file
<?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>
Update
If you are using AndroidX then you can do it like this
View searchPlate = svSearch. findViewById(androidx.appcompat.R.id.search_plate);
if (searchPlate != null) {
AutoCompleteTextView searchText = searchPlate.findViewById(androidx.appcompat.R.id.search_src_text);
if (searchText != null){
searchText.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.edittext_text_size));
searchText.setMaxLines(1);
searchText.setSingleLine(true);
searchText.setTextColor(getResources().getColor(R.color.etTextColor));
searchText.setHintTextColor(getResources().getColor(R.color.etHintColor));
searchText.setBackground(null);
}
}
I explained in the end of this post with images this is apply for xamarin forms. But i think you can understand it, because it is based on the source code of searchview of android
How to change searchbar cancel button image in xamarin forms
이 "getMenuInflater (). inflate (R.menu.search_menu, menu);"와 같이 Searchview를 팽창시키는 경우 그런 다음 아래처럼 style.xml을 통해이 검색보기를 사용자 정의 할 수 있습니다.
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="searchViewStyle">@style/SearchView.ActionBar</item>
</style>
<style name="SearchView.ActionBar" parent="Widget.AppCompat.SearchView.ActionBar">
<item name="queryBackground">@drawable/drw_search_view_bg</item>
<item name="searchHintIcon">@null</item>
<item name="submitBackground">@null</item>
<item name="closeIcon">@drawable/vd_cancel</item>
<item name="searchIcon">@drawable/vd_search</item>
</style>
'Programming' 카테고리의 다른 글
| PHP에서 두 날짜를 어떻게 비교할 수 있습니까? (0) | 2020.07.13 |
|---|---|
| 파이썬 인터프리터 쉘에서 마지막 명령을 반복하는 방법은 무엇입니까? (0) | 2020.07.13 |
| React Native에서 뷰 크기 가져 오기 (0) | 2020.07.13 |
| MAMP에 추가 PHP 버전을 추가하는 방법 (0) | 2020.07.13 |
| 팬 & 줌 이미지 (0) | 2020.07.13 |