Android 14からRippleEffectの色計算方法が変わる？

<font color="red">**Android 14 Beta4にて、この挙動は修正されました。仕様変更ではなくバグだったようです**</font>

一時期こういう動作があったという記録として記事は残しておきます

---

Android 14 Beta2を触っているとRippleEffectがかなり薄く表示されているなという印象を受けます。
バグかな？と思っていましたが、挙動を調べると、むしろ指定通りに動作するように修正されたのでは？というのが私の印象です。

※このネタはBeta版の動作からの推測でしかないのでご注意を

## selectableItemBackgroundの定義

はじめは`?attr/selectableItemBackground`の定義が変わったのかな？とも思いましたが、調べて見ると
`Theme.Material3.DayNight.NoActionBar`の場合、[`res/drawable/item_background_material.xml`](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/res/res/drawable/item_background_material.xml)を参照していて、特に定義に違いはなさそうです。

## RippleDrawableの色の扱い

次に以下のようなRippleDrawableを定義して、`@color/ripple`を変化させてどう表示されるか確認してみます。
```xml
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/ripple">
    <item android:id="@android:id/mask" android:drawable="@android:color/white"/>
</ripple>
```

### #C0000000の場合
|Android 14 Beta2.1|Android 13|
|--|--|
|![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155171/0ba1e654-e98f-b372-77d1-a24356351356.png)|![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155171/5e970128-bfa9-9888-ecad-e02ebdbeb26b.png)|

14と13で違いはなく、指定の色より薄く表示されるのがRippleEffectの色ですね。

### #80000000の場合
|Android 14 Beta2.1|Android 13|
|--|--|
|![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155171/87acd02d-6360-ebb7-cdc1-b4f782f281de.png)|![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155171/bf2c5615-099b-9e9e-cc99-364cc79e3fc6.png)|

これも14と13で違いはなさそうです。

### #40000000の場合
|Android 14 Beta2.1|Android 13|
|--|--|
|![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155171/54f34117-ecab-dc96-1a0c-e1bb82d07228.png)|![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155171/dfea0404-f615-ccd7-0efb-980969fbb4fc.png)|

ここで違いが出てきましたね。14の方が薄いですが、どちらかというと13の方が濃いというか、#80000000の場合と同じ色になっているようです。

### #20000000の場合
Lightテーマの`?attr/selectableItemBackground`は#1F000000 になっているみたいなので一番近い色ですね

|Android 14 Beta2.1|Android 13|
|--|--|
|![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155171/18828041-3442-26b3-dd4a-2e9576b95fa1.png)|![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155171/c011c771-a758-9249-0144-51fda6f231d1.png)|

明確に違いがあります。やはりAndroid 13 は#80000000の場合と同じ色になっているようです。#20000000より明らかに濃い色がでていますね。Android 14は順当に指定した色を、さらに薄くした色になっています。

## Alphaを制限している処理

さらにRippleDrawableのソースコードを調べると以下のように、アルファが128以下なら128にするという処理が入っていますね。この処理が Android 14で変更されたのではないかというのが推測です。

https://cs.android.com/android/platform/superproject/+/refs/heads/master:frameworks/base/graphics/java/android/graphics/drawable/RippleDrawable.java;l=1011-1016

```java
    private int clampAlpha(@ColorInt int color) {
        if (Color.alpha(color) < 128) {
            return  (color & 0x00FFFFFF) | 0x80000000;
        }
        return color;
    }
```


## まとめ

以上より、Android 14が薄いというより、Android 13まではRippleの色が一定以上薄くならないようになっていたのが、指定通りに計算されるようになった結果、と言えそうな変化ですね。

今までRippleを薄くできなかったのが、ちゃんと指定に比例して薄くできるように修正された。今まで通りの色で出したければアルファを0x80指定に変更する必要がある（対応の方法はある）

まだBeta2.1ですので、最終的に以前と同様の動作に戻るのか、これが最終的な動作になるのかは不明ですが、もしこれが意図した変化だとしたら、RippleEffectの色指定を全面的に見直す必要がありそうですね。
その場合、`selectableItemBackground`の定義が変わるのかどうかも気になります。