Skip to content

Custom UI Sample Android

Hudson_BuildService edited this page Jan 9, 2026 · 1 revision
class MySurveyFragment : Fragment(), SurveyFrameLifecycleListener, ProgramCallback, View.OnClickListener {

    private lateinit var surveyFrame: SurveyFrame
    private lateinit var pageLayout: LinearLayout
    private lateinit var nextButton: Button
    private lateinit var backButton: Button
    private lateinit var quitButton: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Binding Program Lifecycle Listener
        val serverId = ConfirmitServer.UK.serverId
        val programKey = "<Program Key>"
        TriggerSDK.setCallback(serverId, programKey, this)

        // Initialize Survey Frame
        surveyFrame = SurveyFrame()
        // Binding Survey Lifecycle Listener to be notified events
        surveyFrame.surveyFrameLifeCycleListener = this
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        val root = LinearLayout(context)
        root.orientation = LinearLayout.VERTICAL

        // This layout will contain questions view
        pageLayout = LinearLayout(context)
        pageLayout.orientation = LinearLayout.VERTICAL

        val buttons = LinearLayout(context)
        buttons.orientation = LinearLayout.HORIZONTAL

        backButton = Button(context)
        backButton.text = "Back"
        backButton.setOnClickListener(this)

        quitButton = Button(context)
        quitButton.text = "Quit"
        quitButton.setOnClickListener(this)

        nextButton = Button(context)
        nextButton.text = "Next"
        nextButton.setOnClickListener(this)

        buttons.addView(backButton)
        buttons.addView(quitButton)
        buttons.addView(nextButton)

        root.addView(pageLayout)
        root.addView(buttons)

        return root
    }

    override fun onClick(v: View) {
        // Perform survey navigation
        if (v.equals(nextButton)) {
            surveyFrame.next()
        } else if (v.equals(backButton)) {
            surveyFrame.back()
        } else if (v.equals(quitButton)) {
            surveyFrame.quit(false)
        }
    }

    override fun onScenarioLoad(triggerInfo: TriggerInfo, exception: Exception?) {
        // On scenario script starts
    }

    override fun onWebSurveyStart(fragment: SurveyWebViewFragment) {
        // Show web survey
    }

    override fun onScenarioError(triggerInfo: TriggerInfo, exception: Exception) {
        // When scenario scripting contains error
    }

    override fun onSurveyDownloadCompleted(triggerInfo: TriggerInfo, surveyId: String, exception: Exception?) {
        // Survey download completed
    }

    override fun onSurveyStart(config: SurveyFrameConfig) {
        surveyFrame.load(config)
        surveyFrame.start()
    } 

    override fun onAppFeedback(triggerInfo: TriggerInfo, data: Map<String, String?>) {
        // When AppFeedback action triggered
    }

    override fun onSurveyErrored(values: Map<String, String?>, exception: Exception) {
        showAlert("Survey contains error")
    }

    override fun onSurveyFinished(values: Map<String, String?>) {
        showAlert("Survey completed")
    }

    override fun onSurveyQuit(values: Map<String, String?>) {
        showAlert("Survey quit by user")
    }

    override fun onSurveyPageReady(page: SurveyPage) {
        // Clear question views
        pageLayout.removeAllViews()

        // Set visibilities for navigation buttons
        if (page.showForward) {
            nextButton.visibility = View.VISIBLE
        } else {
            nextButton.visibility = View.INVISIBLE
        }

        if (page.showBackward) {
            backButton.visibility = View.VISIBLE
        } else {
            backButton.visibility = View.INVISIBLE
        }

        val questions = page.questions
        // Loop through question in current survey page, and generate Views
        for (question in questions) {
            // If question type is TEXT
            if (question.nodeType == QuestionType.TEXT) {
                // Question model is passed to view for:
                // 1. To display the question
                // 2. Interaction like answering question
                val layout = TextQuestionLayout(activity!!, question as TextQuestion)
                pageLayout.addView(layout)
            }
            // ... More question type integrations
        }
    }

    private fun showAlert(message: String) {
        AlertDialog.Builder(this.activity!!).setMessage(message).create().show()
    }

    internal inner class TextQuestionLayout(context: Context, private val question: TextQuestion) :
        LinearLayout(context), TextWatcher {

        private val editText: EditText

        init {
            orientation = LinearLayout.VERTICAL

            // Retrieve question information from model
            val title = TextView(context)
            title.text = question.title.get()

            editText = EditText(context)
            editText.addTextChangedListener(this)
            editText.setText(question.getValue())

            this.addView(title)
            this.addView(editText)
        }

        override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}

        override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}

        override fun afterTextChanged(s: Editable) {
            // Update question value when there is update from UI
            question.setValue(s.toString())
        }
    }
}

Clone this wiki locally