Skip to content

Commit 8e81eff

Browse files
Merge pull request #2531 from DataDog/aleksandr-gringauz/rum-8906/improve-statelistdrawable-support
RUM-8906: Improve StateListDrawable support in session replay
2 parents 8c7108d + f9f9395 commit 8e81eff

File tree

7 files changed

+141
-0
lines changed

7 files changed

+141
-0
lines changed

features/dd-sdk-android-session-replay/src/main/kotlin/com/datadog/android/sessionreplay/utils/LegacyDrawableToColorMapper.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import android.graphics.drawable.InsetDrawable
1818
import android.graphics.drawable.LayerDrawable
1919
import android.graphics.drawable.RippleDrawable
2020
import android.graphics.drawable.ShapeDrawable
21+
import android.graphics.drawable.StateListDrawable
2122
import android.graphics.drawable.VectorDrawable
2223
import com.datadog.android.api.InternalLogger
2324

@@ -44,6 +45,7 @@ open class LegacyDrawableToColorMapper(
4445
is InsetDrawable -> resolveInsetDrawable(drawable, internalLogger)
4546
is GradientDrawable -> resolveGradientDrawable(drawable, internalLogger)
4647
is ShapeDrawable -> resolveShapeDrawable(drawable, internalLogger)
48+
is StateListDrawable -> resolveStateListDrawable(drawable, internalLogger)
4749
is BitmapDrawable,
4850
is VectorDrawable -> null // return null without reporting them by telemetry.
4951
else -> {
@@ -191,6 +193,16 @@ open class LegacyDrawableToColorMapper(
191193
return ((color.toLong() and MASK_COLOR) or (alpha.toLong() shl ALPHA_SHIFT_ANDROID)).toInt()
192194
}
193195

196+
/**
197+
* Resolves the color from an [StateListDrawable].
198+
* @param drawable the color drawable
199+
* @param internalLogger the internalLogger to report warnings
200+
* @return the color to map to or null if not applicable
201+
*/
202+
private fun resolveStateListDrawable(drawable: StateListDrawable, internalLogger: InternalLogger): Int? {
203+
return mapDrawableToColor(drawable = drawable.current, internalLogger = internalLogger)
204+
}
205+
194206
companion object {
195207
@SuppressLint("DiscouragedPrivateApi")
196208
@Suppress("PrivateAPI", "SwallowedException", "TooGenericExceptionCaught")

features/dd-sdk-android-session-replay/src/test/kotlin/com/datadog/android/sessionreplay/utils/LegacyDrawableToColorMapperTest.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import android.graphics.drawable.Drawable
1313
import android.graphics.drawable.GradientDrawable
1414
import android.graphics.drawable.LayerDrawable
1515
import android.graphics.drawable.RippleDrawable
16+
import android.graphics.drawable.StateListDrawable
1617
import com.datadog.android.api.InternalLogger
1718
import com.datadog.android.sessionreplay.forge.ForgeConfigurator
1819
import fr.xgouchet.elmyr.annotation.IntForgery
@@ -191,4 +192,24 @@ open class LegacyDrawableToColorMapperTest {
191192
// Then
192193
assertThat(result).isNull()
193194
}
195+
196+
@Test
197+
fun `M map StateListDrawable to the color of its current Drawable W mapDrawableToColor()`(
198+
@IntForgery drawableColor: Int
199+
) {
200+
// Given
201+
val currentStateDrawable = mock<ColorDrawable>().apply {
202+
whenever(this.color) doReturn drawableColor
203+
}
204+
205+
val stateListDrawable = mock<StateListDrawable>().apply {
206+
whenever(this.current) doReturn currentStateDrawable
207+
}
208+
209+
// When
210+
val result = testedMapper.mapDrawableToColor(stateListDrawable, mockInternalLogger)
211+
212+
// Then
213+
assertThat(result).isEqualTo(drawableColor)
214+
}
194215
}

sample/kotlin/src/main/kotlin/com/datadog/android/sample/sessionreplay/ImageComponentsFragment.kt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ import android.widget.Button
1515
import android.widget.ImageButton
1616
import android.widget.ImageView
1717
import android.widget.TextView
18+
import androidx.annotation.DrawableRes
19+
import androidx.annotation.IdRes
1820
import androidx.appcompat.widget.AppCompatImageButton
21+
import androidx.core.content.ContextCompat
1922
import androidx.fragment.app.Fragment
2023
import androidx.lifecycle.ViewModelProvider
2124
import com.datadog.android.rum.ExperimentalRumApi
@@ -48,6 +51,19 @@ internal class ImageComponentsFragment : Fragment() {
4851
imageViewRemote = rootView.findViewById(R.id.imageView_remote)
4952
imageButtonRemote = rootView.findViewById(R.id.imageButtonRemote)
5053
appCompatButtonRemote = rootView.findViewById(R.id.appCompatImageButtonRemote)
54+
55+
setupStateListButton(
56+
rootView = rootView,
57+
buttonId = R.id.button_statelist_shapes,
58+
backgroundId = R.drawable.selector_statelist_shapes
59+
)
60+
61+
setupStateListButton(
62+
rootView = rootView,
63+
buttonId = R.id.button_statelist_images,
64+
backgroundId = R.drawable.selector_statelist_images
65+
)
66+
5167
return rootView
5268
}
5369

@@ -126,6 +142,18 @@ internal class ImageComponentsFragment : Fragment() {
126142
}
127143
}
128144

145+
private fun setupStateListButton(
146+
rootView: View,
147+
@IdRes buttonId: Int,
148+
@DrawableRes backgroundId: Int
149+
) {
150+
val button: Button = rootView.findViewById(buttonId)
151+
val background = ContextCompat.getDrawable(rootView.context, backgroundId)
152+
153+
button.background = background
154+
button.backgroundTintList = null
155+
}
156+
129157
// endregion
130158

131159
companion object {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!--
2+
~ Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
3+
~ This product includes software developed at Datadog (https://www.datadoghq.com/).
4+
~ Copyright 2016-Present Datadog, Inc.
5+
-->
6+
7+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
8+
android:width="800.5dp"
9+
android:height="907.77dp"
10+
android:viewportWidth="800.5"
11+
android:viewportHeight="907.77">
12+
<path
13+
android:pathData="M303.36,238.61c31.36,-21.37 71.76,-12.97 65,-6.53c-12.89,12.28 4.26,8.65 6.11,31.31c1.36,16.69 -4.09,25.88 -8.78,31.11c-9.79,1.28 -21.69,3.67 -36.02,8.33c-8.48,2.76 -15.85,5.82 -22.31,8.9c-1.7,-1.11 -3.55,-2.47 -5.74,-4.36C279.5,288.19 280.24,254.37 303.36,238.61M490.68,370.72c5.69,-4.41 31.55,-12.72 55.49,-15.55c12.57,-1.48 30.49,-2.34 34.31,-0.2c7.59,4.19 7.59,17.16 2.39,29.14c-7.57,17.4 -18.27,36.63 -30.39,38.21c-19.77,2.61 -38.46,-8.09 -59.8,-24.03C485.06,392.56 480.38,378.68 490.68,370.72M526.75,201.27c29.19,13.58 25.37,39.42 26.18,54.6c0.22,4.36 0.15,7.3 -0.22,9.32c-4.04,-2.19 -10.43,-3.8 -20.56,-3.35c-2.96,0.12 -5.84,0.47 -8.63,0.91c-10.77,-5.77 -17.21,-17.06 -23.1,-29.06c-0.54,-1.11 -0.96,-2.1 -1.36,-3.06c-0.17,-0.44 -0.35,-0.91 -0.52,-1.31c-0.07,-0.22 -0.12,-0.39 -0.2,-0.59c-3.23,-10.25 -1.06,-12.3 0.3,-15.46c1.41,-3.23 6.68,-5.89 -1.11,-8.58c-0.67,-0.25 -1.5,-0.39 -2.44,-0.57C500.25,197.72 515.7,196.17 526.75,201.27M367.62,510.22c-31.45,-20.19 -63.99,-49.15 -78.22,-65.18c-2.39,-1.8 -2,-9.79 -2,-9.79c12.84,9.98 66.11,48.04 122.44,65.42c19.87,6.14 50.36,8.46 76.81,-6.53c20.21,-11.46 44.54,-31.43 59.06,-52.01l2.66,4.61c-0.1,3.06 -6.78,17.97 -10.18,23.96c6.14,3.53 10.72,4.49 17.55,6.36l46.64,-7.27c16.74,-27.04 28.74,-70.65 15.95,-112.16c-7.3,-23.81 -45.36,-71.22 -48.09,-73.83c-9.56,-9.19 1.6,-44.69 -17.35,-83.42C532.86,159.41 480.67,116.69 458,98.1c6.68,4.88 47.82,21.47 67,44.62c1.8,-2.39 2.54,-14.82 4.19,-17.97c-16.47,-21.57 -17.75,-59.95 -17.75,-70.21c0,-18.81 -9.56,-40.13 -9.56,-40.13s16.47,13.04 20.73,35.5c5.03,26.6 15.75,47.55 29.93,65.28c26.84,33.43 51.08,50.58 63.33,38.23C630.53,138.58 601,72.2 563.28,35.15C519.25,-8.09 507.74,-2.52 481.91,6.7c-20.61,7.35 -31.75,65.87 -85.47,64.71c-9.1,-1.06 -32.54,-1.63 -44.13,-1.53c6.04,-8.43 11.22,-14.94 11.22,-14.94s-18.02,7.25 -33.38,16.44l-1.18,-1.77c5.18,-10.92 10.75,-17.82 10.75,-17.82s-14.4,8.65 -27.54,19.01c2.39,-13.02 11.44,-21.27 11.44,-21.27s-18.19,3.28 -41.36,28.77c-26.33,7.2 -32.66,11.93 -53.64,21.22c-34.12,-7.44 -50.21,-19.45 -65.55,-41.56c-11.68,-16.89 -32.47,-19.45 -53.71,-10.72c-30.97,12.8 -70.14,30.33 -70.14,30.33s12.77,-0.52 26.08,0.05c-18.22,6.9 -35.72,16.39 -35.72,16.39s8.53,-0.3 19.06,-0.12c-7.27,6.04 -11.29,8.92 -18.22,13.51c-16.66,12.1 -30.17,26.08 -30.17,26.08s11.31,-5.15 21.47,-8.04c-7.1,16.27 -21.18,28.25 -18.59,48.17c2.49,18.19 24.82,55.66 53.64,78.66c2.49,2 41.86,38.43 71.56,23.47c29.68,-14.94 41.39,-28.25 46.27,-48.66c5.74,-23.44 2.47,-41.17 -9.79,-92.05c-4.04,-16.79 -14.57,-51.37 -19.65,-67.91l1.13,-0.81c9.71,20.49 34.56,74.5 44.57,110.78c15.63,56.57 10.75,85.27 3.6,95.79c-21.57,31.73 -76.84,35.92 -101.98,18.34c-3.85,60.91 9.76,87.73 14.37,101.24c-2.29,15.53 7.77,44.37 7.77,44.37s1.13,-13.11 5.74,-20.02c1.23,15.41 9,33.72 9,33.72s-0.47,-11.31 3.06,-21.08c4.98,8.43 8.63,10.43 13.34,16.76c4.71,16.47 14.15,28.5 14.15,28.5s-1.53,-8.83 -0.69,-18.02c23.05,22.14 27.02,54.45 29.31,79.28c6.46,68.26 -107.63,122.54 -129.74,165.24c-16.76,25.29 -26.8,65.3 1.58,88.89c68.6,56.97 42.25,72.65 76.59,97.69c47.11,34.34 106.05,18.96 126.11,-8.97c27.93,-38.92 20.76,-75.63 10.38,-109.97c-8.11,-26.85 -30.15,-71.46 -57.41,-88.72c-27.86,-17.65 -54.95,-20.95 -77.9,-18.59l2.12,-2.44c33.01,-6.56 67.52,-2.96 92.49,13.14c28.35,18.22 54.28,49.47 67.84,97.37c15.38,-2.19 17.55,-3.18 31.63,-5.18l-31.7,-246.76L367.62,510.22zM385.94,819.52l-3.65,-34.22l71.29,-108.74l80.93,23.64l69.59,-116.23L687.52,639l63.38,-132.92l22.53,242.07L385.94,819.52zM774.27,456.51l-254.72,46.17c-6.31,8.13 -21.91,22.41 -29.41,26.13c-32.17,16.2 -53.91,11.51 -72.7,6.63c-12.08,-3.06 -19.08,-4.78 -29.11,-9.29l-62.17,8.53l37.74,314.87l436.35,-78.66L774.27,456.51z"
14+
android:fillColor="#00FF00"/>
15+
</vector>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<selector xmlns:android="http://schemas.android.com/apk/res/android">
3+
<item android:drawable="@drawable/ic_dd_icon_red" android:state_pressed="true"/>
4+
<item android:drawable="@drawable/ic_dd_icon_green" />
5+
</selector>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<selector xmlns:android="http://schemas.android.com/apk/res/android">
3+
4+
<item android:state_pressed="true">
5+
<shape android:shape="rectangle">
6+
<solid android:color="#FF0000"/>
7+
<corners android:radius="8dp"/>
8+
</shape>
9+
</item>
10+
11+
<item android:state_focused="true">
12+
<shape android:shape="rectangle">
13+
<solid android:color="#0000FF"/>
14+
<corners android:radius="8dp"/>
15+
</shape>
16+
</item>
17+
18+
<item android:state_enabled="false">
19+
<shape android:shape="rectangle">
20+
<solid android:color="#808080"/>
21+
<corners android:radius="8dp"/>
22+
</shape>
23+
</item>
24+
25+
<item>
26+
<shape android:shape="rectangle">
27+
<solid android:color="#008000"/>
28+
<corners android:radius="8dp"/>
29+
</shape>
30+
</item>
31+
32+
</selector>

sample/kotlin/src/main/res/layout/fragment_image_components.xml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,34 @@
356356

357357
</LinearLayout>
358358

359+
<LinearLayout
360+
android:layout_width="match_parent"
361+
android:layout_height="wrap_content"
362+
android:orientation="horizontal"
363+
android:gravity="center">
364+
365+
<Button
366+
android:id="@+id/button_statelist_shapes"
367+
style="?android:attr/buttonBarButtonStyle"
368+
android:layout_width="wrap_content"
369+
android:layout_height="wrap_content"
370+
android:clickable="true"
371+
android:focusable="true"
372+
android:contentDescription="@null" />
373+
374+
<Button
375+
android:id="@+id/button_statelist_images"
376+
style="?android:attr/buttonBarButtonStyle"
377+
android:layout_marginStart="48dp"
378+
android:layout_width="48dp"
379+
android:layout_height="48dp"
380+
android:clickable="true"
381+
android:focusable="true"
382+
android:contentDescription="@null"
383+
/>
384+
385+
</LinearLayout>
386+
359387
</LinearLayout>
360388

361389
</ScrollView>

0 commit comments

Comments
 (0)