Reputation: 83
How can I perform actions on slider (move cursor) ?
How can I check slider value ?
Are there any existing functions for this ?
Slider look like that:
<com.google.android.material.slider.Slider
android:id="@+id/sliderRating"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:stepSize="1"
android:valueFrom="1.0"
android:valueTo="5.0" />
And Espresso check: onView(withId(R.id.sliderRating)).check( -> TODO <- )
Upvotes: 7
Views: 1796
Reputation: 87
If you are using OnSliderTouchListener
, here is the solution.
fun Slider.setValueAndClick(value: Float) {
this.value = value
//Slider extends BaseSlider
val baseSliderClass = this.javaClass.superclass
//BaseSlider contains "List<T> touchListeners"
val touchListenersField: Field = baseSliderClass.getDeclaredField("touchListeners")
touchListenersField.isAccessible = true
val listeners = touchListenersField.get(this) as? List<*>
val listener = listeners?.find { it is Slider.OnSliderTouchListener }
if (listener == null) throw Exception("${Slider.OnSliderTouchListener::class.simpleName} not found")
for (method in listener.javaClass.declaredMethods) {
if (method.name == "onStopTrackingTouch") {
method.isAccessible = true
method.invoke(listener, this)
break
}
}
}
You can call onStartTrackingTouch
simply by replacing "onStopTrackingTouch"
with it. I couldn't come up with a better way; I searched for ready-made solutions online, but they involved questionable calculations with "magic" numbers for correcting deviations. At least the reflection will work reliably.
Upvotes: 0
Reputation: 18012
It's easy to create a couple of methods to do that.
Here is what I have:
fun withValue(expectedValue: Float): Matcher<View?> {
return object : BoundedMatcher<View?, Slider>(Slider::class.java) {
override fun describeTo(description: Description) {
description.appendText("expected: $expectedValue")
}
override fun matchesSafely(slider: Slider?): Boolean {
return slider?.value == expectedValue
}
}
}
fun setValue(value: Float): ViewAction {
return object : ViewAction {
override fun getDescription(): String {
return "Set Slider value to $value"
}
override fun getConstraints(): Matcher<View> {
return ViewMatchers.isAssignableFrom(Slider::class.java)
}
override fun perform(uiController: UiController?, view: View) {
val seekBar = view as Slider
seekBar.value = value
}
}
}
The first one, the custom view matcher, is to test that the Slider
has a specific value and the second one, the custom view action, is to set a new value.
A simple test example using them just to get the idea of how they work:
@Test
fun testSlider() {
onView(withId(R.id.sliderRating)).check(matches(withValue(1.0F)))
onView(withId(R.id.sliderRating)).perform(setValue(2.0F))
onView(withId(R.id.sliderRating)).check(matches(withValue(2.0F)))
}
This test checks first of all if the slider has value 1.0, then changes its value to 2.0 and uses the matcher to check that the value is now 2.0.
I have the code in kotlin but if you need it in java it can be easily transformed (android studio can do that). As the question is not tagged with the language I don't know which one do you need, tag it next time.
Upvotes: 11