【Android】項目をタップしたときに色を変える

備忘録。

AndroidのTextViewなどはデフォルトだとタップしたときに色が変わらないので若干味気ない感じ。

<img width="250" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472695/f5385a48-c7a5-6f42-7e0f-bfad6bea175f.gif"/>

TextViewなどの項目をタップしたときだけ、背景色（前景色）を変える。

### 方法

押下したときだけ色を変えたい要素のbackgroud(foreground)に
`?attr/selectableItemBackgroundBorderless`を指定する。

```xml
<TextView
    android:id="@+id/sc_abt_tv_oss_license"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginTop="32dp"
    android:foreground="?attr/selectableItemBackgroundBorderless"
    android:paddingStart="16dp"
    android:paddingTop="10dp"
    android:paddingEnd="16dp"
    android:paddingBottom="10dp"
    android:text="@string/oss_license"
    android:textColor="@android:color/black"
    android:textSize="18sp"
    app:layout_constraintEnd_toEndOf="@+id/sc_abt_tv_app_name"
    app:layout_constraintStart_toStartOf="@+id/sc_abt_tv_app_name"
    app:layout_constraintTop_toBottomOf="@+id/sc_abt_tv_app_version" />
```


これを適用すると…

<img width="250" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472695/13975892-b6e0-3fc3-9f3e-271ea2f5ca76.gif"/>

適用前と比べて、**タップしたときにその要素全体が濃い灰色になっていますね**。


### ?attr/selectableItemBackgroundBorderless

公式情報によると、

>?android:attr/selectableItemBackground: 範囲が限定された波紋。
>?android:attr/selectableItemBackgroundBorderless: ビューの範囲外まで広がる波紋。これは、背景が null ではない最も近くにある親ビュー上に表示されますが、その外側にはみ出ることはありません。

[カスタム アニメーションの定義](https://developer.android.com/training/material/animations?hl=ja)

要するに、要素を押した時にその要素内で波紋（一般的にはリップルと呼ばれるもの）が
広がるものが`selectableItemBackground`でその外まで波紋が広がるものが`selectableItemBackgroundBorderless`みたいな感じですかね。

どちらもAndroidで既存で定義されているアトリビュートになります。

```xml:values.xml
<!-- A style that may be applied to buttons or other selectable items
     that should react to pressed and focus states, but that do not
     have a clear visual border along the edges. -->
<attr format="reference" name="selectableItemBackground"/>
<!-- Background drawable for borderless standalone items that need focus/pressed states. -->
<attr format="reference" name="selectableItemBackgroundBorderless"/>
```

で、これが結局なんなのか、というと

```xml:values.xml
<style name="Base.V7.Theme.AppCompat" parent="Platform.AppCompat">
    <item name="selectableItemBackground">@drawable/abc_item_background_holo_dark</item>
    <item name="selectableItemBackgroundBorderless">?attr/selectableItemBackground</item>
```

アプリテーマ(AppTheme)をたどっていくとたどり着くテーマ
(この場合は`Base.V7.Theme.AppCompat`）には上記みたいに定義されていました。

この場合、`selectableItemBackground`と`selectableItemBackgroundBorderless`は
実質同じみたいですね。

で、中身は↓

```xml:abc_item_background_holo_dark
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
    <item android:state_focused="true"  android:state_enabled="false" android:state_pressed="true" android:drawable="@drawable/abc_list_selector_disabled_holo_dark" />
    <item android:state_focused="true"  android:state_enabled="false"                              android:drawable="@drawable/abc_list_selector_disabled_holo_dark" />
    <item android:state_focused="true"                                android:state_pressed="true" android:drawable="@drawable/abc_list_selector_background_transition_holo_dark" />
    <item android:state_focused="false"                               android:state_pressed="true" android:drawable="@drawable/abc_list_selector_background_transition_holo_dark" />
    <item android:state_focused="true"                                                             android:drawable="@drawable/abc_list_focused_holo" />
    <item                                                                                          android:drawable="@android:color/transparent" />
</selector>
```

割と複雑な`selector`でした。


ちなみに、これ以外にも色々と方法はありますが
（自前でselector作ったり、ripple作ったり etc）これが一番簡単では？と思います。（持論）