AndroidでSearchViewをcustomizeする

## いきさつ
デザインがiOSに寄せられた結果、AndroidでSearchViewをカスタマイズする必要が出ることは往々にしてよくあることだと思う。

なので、情報はいくらでも転がっていてすんなりいくと思っていたけど、思った以上に詰まったので絶対忘れるから自分向けに備忘録として残す。

1番詰まったのは、`inflate`しているのに何かがダメで、`InflateException`が起きてクラッシュしていた。rootをLinearLayout等にして試行錯誤してるうちに上手くいったので、何が原因だったかははっきりとはわかっていない。

## 完成形
### テキストなし
![no_text.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154832/edaf35e9-f443-875a-19a2-3ee1043f5b27.jpeg)
### テキストあり
![some_text.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154832/0f625674-9818-143f-e3d9-2ef669f5a447.jpeg)


## 構造

```kotlin:CustomSearchView.kt
class CustomSearchView : RelativeLayout {

    constructor(context: Context) : super(context) {
        init(context)
    }

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
        init(context)
    }

    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
        init(context)
    }

    private fun init(context: Context) {
        inflate(context, R.layout.custom_search_view, this)

        hideSearchPlate()
        setupTextView()
    }

    private fun hideSearchPlate() {
        val searchPlateId = searchView.context.resources.getIdentifier("android:id/search_plate", null, null)
        val searchPlateView = searchView.findViewById<View>(searchPlateId) ?: return
        searchPlateView.setBackgroundResource(R.color.clear)
    }

    private fun setupTextView() {
        val searchSrcTextId = searchView.context.resources.getIdentifier("android:id/search_src_text", null, null)
        val textView = searchView.findViewById<AutoCompleteTextView>(searchSrcTextId) ?: return
        val hintColor = ContextCompat.getColor(context, R.color.gray)
        textView.setHintTextColor(hintColor)
        val textColor = ContextCompat.getColor(context, R.color.textBody)
        textView.setTextColor(textColor)
        textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13.0f)
    }

    fun updateHintText(text: String) {
        searchView.queryHint = text
    }
}
```

### hideSearchPlate
SearchViewに標準でついてくる下線を消す処理を行っている。
一部サイトでは、背景色と同色を指定して誤魔化しているが、自分はclearカラー(#00000000)を指定している。

### setupTextView
SearchViewのhintの文字色(placeholderの色)、入力時の文字色、文字サイズの変更を行っている。

---

`CustomSearchView.kt`で指定しているlayoutは、以下の通り。


```xml:view_custom_search.xml
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <RelativeLayout
        android:id="@+id/baseLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/backgroundColor"
        android:orientation="vertical">

        <SearchView
            android:id="@+id/searchView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginStart="16dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="16dp"
            android:layout_marginBottom="8dp"
            android:background="@drawable/search_view_background"
            android:closeIcon="@drawable/icon_button_delete"
            android:iconifiedByDefault="false"
            android:searchIcon="@drawable/icon_search" />
    </RelativeLayout>
</merge>
```

CustomSearchViewを使用する側で高さを任意に扱えるように、marginだけ設定して他は`match_parent`で最大まで広げている。

### android:background="@drawable/search_view_background"
角丸や周囲の枠線を表示するために別途指定。
詳しくは、`search_view_background`参照。

### android:iconifiedByDefault="false"
SearchViewはデフォルトだと虫眼鏡をタップして検索入力欄が表示されるようにな挙動をする。
最初から検索入力欄を表示するために`false`を明示的に指定。

---

`view_custom_search.xml`で指定している`search_view_background`は以下の通り。

```xml:search_view_background.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/white" />
    <corners android:radius="10dp" />
    <stroke
        android:width="1dp"
        android:color="@color/separatorColor" />
    <padding
        android:bottom="0dp"
        android:left="-8dp"
        android:right="0dp"
        android:top="0dp" />
</shape>
```

### solid
背景色

### corners
角丸の丸み具合

### stroke
枠線の太さと色