Android
Library that implements questionnaire flow
Getting Started
- Example
- Installing
- Readme
- Changelog
- Register activity result launcher:
private val questionnaireLauncher = QuestionnaireActivity.registerForResult(this) {
it.ifOk { questionnaireViewData -> }
it.ifError { errorCode -> }
}
- Start questionnaire activity:
questionnaireLauncher.launch(QuestionnaireActivity.getLauncherIntent(
context = this,
getQuestionnaireParams = GetQuestionnaireParams.QuestionnaireId("id"), // will use QuestionnaireSourceRepository
// or GetQuestionnaireParams.QuestionnaireForm(TestForm.get()),
title = "Title",
useBackButton = true,
welcomeBundle = WelcomeBundle(
R.drawable.ic_baseline_image_24,
R.string.welcome_to_huma,
R.string.common_action_next,
R.string.welcome_to_huma,
true,
WelcomeBundle.BackNavigation.DeviceBackButton
)
))
Customization
- QuestionnaireSourceRepository - questionnaire source provider, returns proper
ItemSource. To add:
HumaQuestionnaireManager.getInstance().addQuestionnaireSource(questionnaireId: String, source: ItemSource)
- RegisterQuestionParams - used to extend questionnaires with custom questions
data class RegisterQuestionParams(
val questionType: QuestionType, // defines question type
val identifyViewDataDelegate: (QuestionnaireStepViewData) -> Boolean, // determines whether view data belongs is of this question type
val createViewHolderDelegate: CreateViewHolderDelegate, // used to create a view holder
val pageToViewDataConverter: (
FormPage, FormPageToQuestionnaireStepViewDataConverter.LoopFormData?
) -> QuestionnaireStepViewData // converts FormPage to QuestionnaireStepViewData
)
typealias CreateViewHolderDelegate = (
parent: ViewGroup,
editQuestionListener: (question: QuestionViewData<*>) -> Unit,
answerChangeListener: () -> Unit,
launchFlowListener: (LaunchFlowParams) -> Unit,
orientation: Int
) -> QuestionViewHolder
- CommonValidator - defines default questions validation, which is used unless custom
AnswerValidationis provided (such as validatinglowerBound,upperBoundinNumberQuestionViewData:
fun isValid(question: QuestionViewData<*>): Boolean
Preferred units
You can declare a question answer converter which will transform it into a proper QuestionAnswerViewData for a default measurement unit, see:
HumaQuestionnaireManager.getInstance().setQuestionAnswerConverter(/*..*/)`
Preferred unit page builder extension function sample:
fun Pages.height(
preferredUnitsContainer: PreferredUnitsContainer,
pageId: String,
titleStringResId: Int = R.string.onboarding_questionnaire_height,
minHeightInCm: Int = MIN_HEIGHT_CM,
maxHeightInCm: Int = MAX_HEIGHT_CM
) {
val manager = HumaQuestionnaireManager.getInstance()
val unitType = HeightMeasurementUnitType()
val defaultUnit = unitType.getDefaultUnit()
when (val unit = preferredUnitsContainer.getPreferredUnit(unitType)) {
HeightMeasurementUnit.Cm -> {
numeric { /*..*/ }
manager.setQuestionAnswerConverter(pageId) { answerViewData ->
answerViewData as NumberQuestionAnswerViewData
val convertedValue = unitType.convert(answerViewData.value, from = unit, to = defaultUnit)
NumberQuestionAnswerViewData(convertedValue)
}
}
HeightMeasurementUnit.FtIn -> {
twoPickerChoice { /*..*/ }
manager.setQuestionAnswerConverter(pageId) { answerViewData ->
answerViewData as TwoPickerSelectionQuestionAnswerViewData
val feet = FtAndInches.fromPair(answerViewData.value).toFeet()
val convertedValue = unitType.convert(feet, from = unit, to = defaultUnit)
NumberQuestionAnswerViewData(convertedValue)
}
}
}
}
- Add the dependency in your local build.gradle file:
implementation("com.huma.sdk:questionnaire:<latest-version>")
- Initialize
HumaQuestionnaireManagerin your Application class:
HumaQuestionnaireManager.init(
questions: List<RegisterQuestionParams> = emptyList(),
commonValidator: CommonValidator? = null
)
Questionnaire — component which is made of pages (steps) and used for gathering certain user data (such as pregnancy status, quality of life etc.).
Questionnaire page — one of steps in questionnaire which can be either a question or an info page. The last page is called a submission page.
Form — app component which is used to define a questionnaire using FormBuilder extension functions.
ItemSource - app component which manages the questionnaire flow (determining proper next question, validating defined Rule and Condition etc).
Notes and guidelines
Question answers
To get a proper question answer, make sure you're using getAnswerForSubmission() function which applies required conversions if any (answer property contains the original answer)
Questionnaire pages
There is different types of pages such as info, text, numeric, date etc. See the subclasses of BasePage. Pages share common fields such as id, isRequired etc. Avoid using these classes directly, instead use PageBuilder extension functions.
Pages can contain branching logic which changes further questionnaire flow (jumps to proper questions) depending on your answers. Use LogicBuilder and LogicExt extensions functions to add branching logic.
Pages can contain looping logic for cases when we need to repeat the same question multiple times. Use LoopBuilder extension functions to add looping logic.
Pages can contain validation which is defined by AnswerValidation subclasses. Use ValidationBuilder to add validation. See how ValidationStatus can be handled for the best UX in TextQuestionViewHolder.
If you want to declare a submission page you can either use SubmissionPage or set isSubmissionpage to true. The latter is useful when you want to finish a questionnaire from a custom page type
Documentation
Dependencies
[0.1.29]
- #108 Medications module, questionnaire refactoring unit tests;
- #94 Medications module; questionnaire module refactoring; improvements
- #87 Fixed crash on questionnaire submission
- #85 Fixed questionnaire button bugs
- #75 Pref. units / questionnaires fixes and improvements
- #74 Questionnaire module test coverage; minor refactoring and fixes
- #41 Preferred units support in questionnaires
- #35 Huma Questionnaire code docs
- #30 Huma Questionnaire module