diff --git a/datacapture/src/androidTest/java/com/google/android/fhir/datacapture/views/QuestionnaireItemSliderViewHolderFactoryInstrumentedTest.kt b/datacapture/src/androidTest/java/com/google/android/fhir/datacapture/views/QuestionnaireItemSliderViewHolderFactoryInstrumentedTest.kt new file mode 100644 index 0000000000..5d15d32768 --- /dev/null +++ b/datacapture/src/androidTest/java/com/google/android/fhir/datacapture/views/QuestionnaireItemSliderViewHolderFactoryInstrumentedTest.kt @@ -0,0 +1,172 @@ +/* + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.fhir.datacapture.views + +import android.widget.FrameLayout +import android.widget.TextView +import androidx.appcompat.view.ContextThemeWrapper +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import com.google.android.fhir.datacapture.R +import com.google.android.material.slider.Slider +import com.google.common.truth.Truth.assertThat +import com.google.fhir.r4.core.Integer +import com.google.fhir.r4.core.Questionnaire +import com.google.fhir.r4.core.QuestionnaireResponse +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class QuestionnaireItemSliderViewHolderFactoryInstrumentedTest { + private lateinit var context: ContextThemeWrapper + private lateinit var parent: FrameLayout + private lateinit var viewHolder: QuestionnaireItemViewHolder + + @Before + fun setUp() { + context = + ContextThemeWrapper( + InstrumentationRegistry.getInstrumentation().targetContext, + R.style.Theme_MaterialComponents + ) + parent = FrameLayout(context) + viewHolder = QuestionnaireItemSliderViewHolderFactory.create(parent) + } + + @Test + fun shouldSetHeaderTextViewText() { + viewHolder.bind( + QuestionnaireItemViewItem( + Questionnaire.Item.newBuilder() + .apply { + text = com.google.fhir.r4.core.String.newBuilder().setValue("Question?").build() + } + .build(), + QuestionnaireResponse.Item.newBuilder() + ) {} + ) + + assertThat(viewHolder.itemView.findViewById(R.id.slider_header).text) + .isEqualTo("Question?") + } + + @Test + fun singleAnswerOrNull_noAnswer_shouldReturnNull() { + val questionnaireItemViewItem = + QuestionnaireItemViewItem( + Questionnaire.Item.getDefaultInstance(), + QuestionnaireResponse.Item.newBuilder() + ) {} + + assertThat(questionnaireItemViewItem.singleAnswerOrNull).isNull() + } + + @Test + fun shouldSetSliderValue() { + viewHolder.bind( + QuestionnaireItemViewItem( + Questionnaire.Item.getDefaultInstance(), + QuestionnaireResponse.Item.newBuilder().apply { + addAnswer( + QuestionnaireResponse.Item.Answer.newBuilder().apply { + value = + QuestionnaireResponse.Item.Answer.ValueX.newBuilder() + .setInteger(Integer.newBuilder().setValue(10).build()) + .build() + } + ) + } + ) {} + ) + + assertThat(viewHolder.itemView.findViewById(R.id.slider).value).isEqualTo(10) + } + + @Test + fun shouldSetQuestionnaireResponseSliderAnswer() { + val questionnaireItemViewItem = + QuestionnaireItemViewItem( + Questionnaire.Item.getDefaultInstance(), + QuestionnaireResponse.Item.newBuilder() + ) {} + + viewHolder.bind(questionnaireItemViewItem) + viewHolder.itemView.findViewById(R.id.slider).value = 10.0F + + val answer = questionnaireItemViewItem.questionnaireResponseItemBuilder.answerBuilderList + assertThat(answer.size).isEqualTo(1) + assertThat(answer[0].value.integer.value).isEqualTo(10) + } + + @Test + fun shouldSetAnswerToNull() { + val questionnaireItemViewItem = + QuestionnaireItemViewItem( + Questionnaire.Item.getDefaultInstance(), + QuestionnaireResponse.Item.newBuilder().apply { + addAnswer( + QuestionnaireResponse.Item.Answer.newBuilder().apply { + value = + QuestionnaireResponse.Item.Answer.ValueX.newBuilder() + .setInteger(Integer.newBuilder().setValue(10).build()) + .build() + } + ) + addAnswer( + QuestionnaireResponse.Item.Answer.newBuilder().apply { + value = + QuestionnaireResponse.Item.Answer.ValueX.newBuilder() + .setInteger(Integer.newBuilder().setValue(10).build()) + .build() + } + ) + } + ) {} + + assertThat(questionnaireItemViewItem.singleAnswerOrNull).isNull() + } + + @Test + fun shouldSetSliderValueToDefault() { + viewHolder.bind( + QuestionnaireItemViewItem( + Questionnaire.Item.getDefaultInstance(), + QuestionnaireResponse.Item.newBuilder().apply { + addAnswer( + QuestionnaireResponse.Item.Answer.newBuilder().apply { + value = + QuestionnaireResponse.Item.Answer.ValueX.newBuilder() + .setInteger(Integer.newBuilder().setValue(10).build()) + .build() + } + ) + addAnswer( + QuestionnaireResponse.Item.Answer.newBuilder().apply { + value = + QuestionnaireResponse.Item.Answer.ValueX.newBuilder() + .setInteger(Integer.newBuilder().setValue(10).build()) + .build() + } + ) + } + ) {} + ) + + assertThat(viewHolder.itemView.findViewById(R.id.slider).value).isEqualTo(0.0F) + } +} diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/views/QuestionnaireItemSliderViewHolderFactory.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/views/QuestionnaireItemSliderViewHolderFactory.kt new file mode 100644 index 0000000000..56184899bc --- /dev/null +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/views/QuestionnaireItemSliderViewHolderFactory.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.fhir.datacapture.views + +import android.view.View +import android.widget.TextView +import com.google.android.fhir.datacapture.R +import com.google.android.material.slider.Slider +import com.google.fhir.r4.core.Integer +import com.google.fhir.r4.core.QuestionnaireResponse + +internal object QuestionnaireItemSliderViewHolderFactory : + QuestionnaireItemViewHolderFactory(R.layout.questionnaire_item_slider) { + override fun getQuestionnaireItemViewHolderDelegate(): QuestionnaireItemViewHolderDelegate = + object : QuestionnaireItemViewHolderDelegate { + private lateinit var sliderHeader: TextView + private lateinit var slider: Slider + private lateinit var questionnaireItemViewItem: QuestionnaireItemViewItem + + override fun init(itemView: View) { + sliderHeader = itemView.findViewById(R.id.slider_header) + slider = itemView.findViewById(R.id.slider) + } + + override fun bind(questionnaireItemViewItem: QuestionnaireItemViewItem) { + this.questionnaireItemViewItem = questionnaireItemViewItem + val questionnaireItem = questionnaireItemViewItem.questionnaireItem + val answer = questionnaireItemViewItem.singleAnswerOrNull + sliderHeader.text = questionnaireItem.text.value + slider.valueFrom = 0.0F + slider.valueTo = 100.0F + slider.stepSize = 10.0F + val sliderValue = answer?.value?.integer?.value?.toString() ?: "0.0" + slider.value = sliderValue.toFloat() + + slider.addOnChangeListener { _, newValue, _ -> + // Responds to when slider's value is changed + questionnaireItemViewItem.singleAnswerOrNull = + QuestionnaireResponse.Item.Answer.newBuilder().apply { + value = + QuestionnaireResponse.Item.Answer.ValueX.newBuilder() + .setInteger(Integer.newBuilder().setValue(newValue.toInt()).build()) + .build() + } + questionnaireItemViewItem.questionnaireResponseItemChangedCallback() + } + } + } +} diff --git a/datacapture/src/main/res/layout/questionnaire_item_slider.xml b/datacapture/src/main/res/layout/questionnaire_item_slider.xml new file mode 100644 index 0000000000..135b2b6690 --- /dev/null +++ b/datacapture/src/main/res/layout/questionnaire_item_slider.xml @@ -0,0 +1,18 @@ + + + + + + + \ No newline at end of file diff --git a/deps.gradle b/deps.gradle index 38b79f676e..bbf77bd43f 100644 --- a/deps.gradle +++ b/deps.gradle @@ -33,7 +33,7 @@ versions.hapi_r4 = '5.3.0' versions.junit = '4.13' versions.kotlin = '1.4.30' versions.lifecycle = '2.2.0' -versions.material = '1.1.0' +versions.material = '1.3.0' versions.okhttp_logging_interceptor = '4.0.0' versions.recyclerview = '1.1.0' versions.retrofit = '2.7.2'