소개
안타깝게도 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
은 내 요소의 ID ( ) 에만 의존 SearchView
하므로 하위 순회 (예 : searchView.getChildAt(0)
내에서 올바른보기를 얻기 위해 사용)보다 SDK 버전에 독립적 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
로컬 드로어 블을 참조하는 대신 아래 표시된 선택기에서 사용할 수 .
참고 : 내가 사용했다 홀로 빛의 기지로 테마를하지만과 동일 할 수 홀로 어둠 . Light 와 Dark 테마 사이 에 선택된 상태 9- 패치 에는 실제 차이가없는 것 같습니다 . 그러나 기본 상태에 대한 9 패치에는 차이가 있습니다 ( Light vs Dark 참조 ). 그래서, 아마 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
텍스트 필드 를 포함하는 뷰의 배경을 설정합니다 . 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 생성자의 하나는 팽창이 레이아웃있는 라인을 찾을 수 있습니다 :
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 패치 중 하나 에서 파란색 선을 인식 하므로 로컬 복사본을 만들고 원하는대로 색상을 변경합니다.