Skip to content

Commit

Permalink
Add support for "Help" questionnaire item control (#1617)
Browse files Browse the repository at this point in the history
* Implement help button in sdc module.

* Fix instrumentation tests failure.

* Address review comments.

* Code formating.

* spotless apply.

Co-authored-by: Santosh Pingle <[email protected]>
  • Loading branch information
santosh-pingle and Santosh Pingle committed Sep 29, 2022
1 parent a09beb0 commit 6daae6a
Show file tree
Hide file tree
Showing 32 changed files with 803 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2021 Google LLC
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,7 +16,13 @@

package com.google.android.fhir.datacapture

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

/** Only exists so we can use an AppCompatActivity in ActivityScenario tests. */
class TestActivity : AppCompatActivity()
class TestActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setTheme(R.style.Theme_Material3_DayNight)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class QuestionnaireItemPhoneNumberViewHolderFactoryInstrumentedTest {
context =
ContextThemeWrapper(
InstrumentationRegistry.getInstrumentation().targetContext,
R.style.Theme_MaterialComponents
R.style.Theme_Material3_DayNight
)
parent = FrameLayout(context)
viewHolder = QuestionnaireItemPhoneNumberViewHolderFactory.create(parent)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ internal val Questionnaire.QuestionnaireItemComponent.choiceOrientation: ChoiceO
internal enum class DisplayItemControlType(val extensionCode: String) {
FLYOVER("flyover"),
PAGE("page"),
HELP("help")
}

/** Item control to show instruction text */
Expand All @@ -144,6 +145,25 @@ internal val Questionnaire.QuestionnaireItemComponent.displayItemControl: Displa
return DisplayItemControlType.values().firstOrNull { it.extensionCode == code }
}

/** Whether any one of the nested display item has [DisplayItemControlType.HELP] control. */
internal val Questionnaire.QuestionnaireItemComponent.hasHelpButton: Boolean
get() {
return item.any { it.isHelpCode }
}

/** Whether item type is display and [displayItemControl] is [DisplayItemControlType.HELP]. */
internal val Questionnaire.QuestionnaireItemComponent.isHelpCode: Boolean
get() {
return when (type) {
Questionnaire.QuestionnaireItemType.DISPLAY -> {
displayItemControl == DisplayItemControlType.HELP
}
else -> {
false
}
}
}

/**
* Whether the corresponding [QuestionnaireResponse.QuestionnaireResponseItemComponent] should have
* nested items within [QuestionnaireResponse.QuestionnaireResponseItemAnswerComponent](s).
Expand Down Expand Up @@ -197,6 +217,17 @@ internal val Questionnaire.QuestionnaireItemComponent.localizedFlyoverSpanned: S
}
?.localizedTextSpanned

/**
* A nested questionnaire item of type display with displayCategory extension with [INSTRUCTIONS]
* code is used as the instructions of the parent question.
*/
internal val Questionnaire.QuestionnaireItemComponent.localizedHelpSpanned: Spanned?
get() {
return item
.firstOrNull { questionnaireItem -> questionnaireItem.isHelpCode }
?.localizedTextSpanned
}

/**
* Whether the QuestionnaireItem should be hidden according to the hidden extension or lack thereof.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat
questionnaireItemList =
questionnaireItem.item.filterNot {
it.type == Questionnaire.QuestionnaireItemType.DISPLAY &&
(it.isInstructionsCode || it.isFlyoverCode)
(it.isInstructionsCode || it.isFlyoverCode || it.isHelpCode)
},
questionnaireResponseItemList =
if (questionnaireResponseItem.answer.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ internal class QuestionnaireGroupTypeHeaderView(context: Context, attrs: Attribu
val prefix = findViewById<TextView>(R.id.prefix)
val question = findViewById<TextView>(R.id.question)
val hint = findViewById<TextView>(R.id.hint)
initHelpButton(this, questionnaireItem)
prefix.updateTextAndVisibility(questionnaireItem.localizedPrefixSpanned)
question.updateTextAndVisibility(questionnaireItem.localizedTextSpanned)
hint.updateTextAndVisibility(questionnaireItem.localizedInstructionsSpanned)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,19 @@ import android.content.Context
import android.text.Spanned
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.View.GONE
import android.view.View.VISIBLE
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import com.google.android.fhir.datacapture.R
import com.google.android.fhir.datacapture.hasHelpButton
import com.google.android.fhir.datacapture.localizedHelpSpanned
import com.google.android.fhir.datacapture.localizedInstructionsSpanned
import com.google.android.fhir.datacapture.localizedPrefixSpanned
import com.google.android.fhir.datacapture.localizedTextSpanned
import com.google.android.material.card.MaterialCardView
import org.hl7.fhir.r4.model.Questionnaire

/** View for the prefix, question, and hint of a questionnaire item. */
Expand All @@ -46,6 +51,7 @@ internal class QuestionnaireItemHeaderView(context: Context, attrs: AttributeSet
prefix.updateTextAndVisibility(questionnaireItem.localizedPrefixSpanned)
question.updateTextAndVisibility(questionnaireItem.localizedTextSpanned)
hint.updateTextAndVisibility(questionnaireItem.localizedInstructionsSpanned)
initHelpButton(this, questionnaireItem)
// Make the entire view GONE if there is nothing to show. This is to avoid an empty row in the
// questionnaire.
visibility = getViewGroupVisibility(prefix, question, hint)
Expand All @@ -69,3 +75,31 @@ internal fun getViewGroupVisibility(vararg view: TextView): Int {
}
return GONE
}

internal fun initHelpButton(
view: View,
questionnaireItem: Questionnaire.QuestionnaireItemComponent
) {
val helpButton = view.findViewById<Button>(R.id.helpButton)
helpButton.visibility =
if (questionnaireItem.hasHelpButton) {
VISIBLE
} else {
GONE
}
val helpCardView = view.findViewById<MaterialCardView>(R.id.helpCardView)
var isHelpCardViewVisible = false
helpButton.setOnClickListener {
if (isHelpCardViewVisible) {
isHelpCardViewVisible = false
helpCardView.visibility = GONE
} else {
isHelpCardViewVisible = true
helpCardView.visibility = VISIBLE
}
}

view
.findViewById<TextView>(R.id.helpText)
.updateTextAndVisibility(questionnaireItem.localizedHelpSpanned)
}
13 changes: 13 additions & 0 deletions datacapture/src/main/res/drawable/ic_help_48px.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<vector
xmlns:android="https://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="48"
android:viewportHeight="48"
android:tint="?attr/colorControlNormal"
>
<path
android:fillColor="@android:color/white"
android:pathData="M24.2,35.65Q25,35.65 25.55,35.1Q26.1,34.55 26.1,33.75Q26.1,32.95 25.55,32.4Q25,31.85 24.2,31.85Q23.4,31.85 22.85,32.4Q22.3,32.95 22.3,33.75Q22.3,34.55 22.85,35.1Q23.4,35.65 24.2,35.65ZM22.45,28.35H25.4Q25.4,27.05 25.725,25.975Q26.05,24.9 27.75,23.5Q29.3,22.2 29.95,20.95Q30.6,19.7 30.6,18.2Q30.6,15.55 28.875,13.95Q27.15,12.35 24.3,12.35Q21.85,12.35 19.975,13.575Q18.1,14.8 17.25,16.95L19.9,17.95Q20.45,16.55 21.55,15.775Q22.65,15 24.15,15Q25.85,15 26.9,15.925Q27.95,16.85 27.95,18.3Q27.95,19.4 27.3,20.375Q26.65,21.35 25.4,22.4Q23.9,23.7 23.175,24.975Q22.45,26.25 22.45,28.35ZM24,44Q19.9,44 16.25,42.425Q12.6,40.85 9.875,38.125Q7.15,35.4 5.575,31.75Q4,28.1 4,24Q4,19.85 5.575,16.2Q7.15,12.55 9.875,9.85Q12.6,7.15 16.25,5.575Q19.9,4 24,4Q28.15,4 31.8,5.575Q35.45,7.15 38.15,9.85Q40.85,12.55 42.425,16.2Q44,19.85 44,24Q44,28.1 42.425,31.75Q40.85,35.4 38.15,38.125Q35.45,40.85 31.8,42.425Q28.15,44 24,44ZM24,41Q31.1,41 36.05,36.025Q41,31.05 41,24Q41,16.9 36.05,11.95Q31.1,7 24,7Q16.95,7 11.975,11.95Q7,16.9 7,24Q7,31.05 11.975,36.025Q16.95,41 24,41ZM24,24Q24,24 24,24Q24,24 24,24Q24,24 24,24Q24,24 24,24Q24,24 24,24Q24,24 24,24Q24,24 24,24Q24,24 24,24Z"
/>
</vector>
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
Expand All @@ -27,15 +28,72 @@
app:layout_constraintTop_toTopOf="parent"
/>

<TextView
android:id="@+id/hint"
style="?attr/questionnaireSubtitleTextStyle"
android:text="group type"
<LinearLayout
android:id="@+id/helpContainer"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/instructions_top_margin"
android:orientation="horizontal"
app:layout_constraintTop_toBottomOf="@id/question"
app:layout_constraintStart_toStartOf="parent"
>

<TextView
android:id="@+id/hint"
style="?attr/questionnaireSubtitleTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight=".7"
android:layout_gravity="center_vertical"
tools:text="Sample helper text"
/>
<Button
style="?attr/questionnaireHelpButtonStyle"
android:id="@+id/helpButton"
android:layout_width="@dimen/help_button_width"
android:layout_height="@dimen/help_button_height"
android:layout_gravity="center_vertical"
android:layout_weight=".3"
android:layout_marginStart="@dimen/help_button_margin_start"
app:icon="@drawable/ic_help_48px"
/>
</LinearLayout>

<com.google.android.material.card.MaterialCardView
android:id="@+id/helpCardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginTop="@dimen/help_card_view_margin_top"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/question"
/>
app:layout_constraintTop_toBottomOf="@id/helpContainer"
app:layout_constraintStart_toStartOf="parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="?attr/colorSurfaceVariant"
>
<TextView
style="?attr/questionnaireHelpHeaderStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/help_header_horizontal_margin"
android:layout_marginTop="@dimen/help_card_view_margin_top"
android:layout_marginBottom="@dimen/help_header_margin_bottom"
android:text="@string/help"
/>
<TextView
android:id="@+id/helpText"
style="?attr/questionnaireHelpTextStyle"
android:layout_marginHorizontal="@dimen/help_header_horizontal_margin"
android:layout_marginBottom="@dimen/help_margin_bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Sample helper text"
/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>

</androidx.constraintlayout.widget.ConstraintLayout>
69 changes: 64 additions & 5 deletions datacapture/src/main/res/layout/questionnaire_item_header.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
Expand All @@ -27,14 +28,72 @@
app:layout_constraintTop_toTopOf="parent"
/>

<LinearLayout
android:id="@+id/helpContainer"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/instructions_top_margin"
android:orientation="horizontal"
app:layout_constraintTop_toBottomOf="@id/question"
app:layout_constraintStart_toStartOf="parent"
>

<TextView
android:id="@+id/hint"
style="?attr/questionnaireSubtitleTextStyle"
android:id="@+id/hint"
style="?attr/questionnaireSubtitleTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight=".7"
android:layout_gravity="center_vertical"
tools:text="Sample helper text"
/>
<Button
style="?attr/questionnaireHelpButtonStyle"
android:id="@+id/helpButton"
android:layout_width="@dimen/help_button_width"
android:layout_height="@dimen/help_button_height"
android:layout_gravity="center_vertical"
android:layout_weight=".3"
android:layout_marginStart="@dimen/help_button_margin_start"
app:icon="@drawable/ic_help_48px"
/>
</LinearLayout>

<com.google.android.material.card.MaterialCardView
android:id="@+id/helpCardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginTop="@dimen/help_card_view_margin_top"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/question"
/>
app:layout_constraintTop_toBottomOf="@id/helpContainer"
app:layout_constraintStart_toStartOf="parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorSurfaceVariant"
android:orientation="vertical"
>
<TextView
style="?attr/questionnaireHelpHeaderStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/help_header_horizontal_margin"
android:layout_marginTop="@dimen/help_card_view_margin_top"
android:layout_marginBottom="@dimen/help_header_margin_bottom"
android:text="@string/help"
/>
<TextView
android:id="@+id/helpText"
style="?attr/questionnaireHelpTextStyle"
android:layout_marginHorizontal="@dimen/help_header_horizontal_margin"
android:layout_marginBottom="@dimen/help_margin_bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Sample helper text"
/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>

</androidx.constraintlayout.widget.ConstraintLayout>
6 changes: 6 additions & 0 deletions datacapture/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
<attr name="questionnaireQuestionTextStyle" format="reference" />
<!-- Style for subtitle text. -->
<attr name="questionnaireSubtitleTextStyle" format="reference" />
<!-- Style for help header. -->
<attr name="questionnaireHelpHeaderStyle" format="reference" />
<!-- Style for help text. -->
<attr name="questionnaireHelpTextStyle" format="reference" />
<!-- Style for help button -->
<attr name="questionnaireHelpButtonStyle" format="reference" />
<!-- Style for answer text. -->
<attr name="questionnaireAnswerTextStyle" format="reference" />

Expand Down
8 changes: 8 additions & 0 deletions datacapture/src/main/res/values/dimens.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,13 @@
<dimen name="dialog_button_text_size_default">14sp</dimen>
<dimen name="auto_complete_chip_group_margin">10dp</dimen>
<dimen name="auto_complete_chip_group_bottom_margin">50dp</dimen>
<dimen name="instructions_top_margin">4dp</dimen>
<dimen name="help_button_margin_start">4dp</dimen>
<dimen name="help_button_width">24dp</dimen>
<dimen name="help_button_height">24dp</dimen>
<dimen name="help_card_view_margin_top">16dp</dimen>
<dimen name="help_header_horizontal_margin">16dp</dimen>
<dimen name="help_header_margin_bottom">4dp</dimen>
<dimen name="help_margin_bottom">16dp</dimen>
<dimen name="icon_inset">16dp</dimen>
</resources>
1 change: 1 addition & 0 deletions datacapture/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@
<string name="cancel">Cancel</string>
<string name="button_review">Review</string>
<string name="not_answered">"Not Answered"</string>
<string name="help">Help</string>

</resources>
Loading

0 comments on commit 6daae6a

Please sign in to comment.