Skip to content

Commit

Permalink
Show time-picker in input mode. (#1702)
Browse files Browse the repository at this point in the history
* Show timepicker in input mode on clicking end input field icon.

* Address review comment.

* Address review comments.

* Address review comment.

* Address review comments.

Co-authored-by: Santosh Pingle <[email protected]>
  • Loading branch information
santosh-pingle and Santosh Pingle committed Dec 23, 2022
1 parent 0c9987b commit b1c51f2
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,50 @@ class QuestionnaireItemDateTimePickerViewHolderFactoryEspressoTest {
.isNotEmpty()
}

@Test
fun showsTimePickerInInputMode() {
val questionnaireItemView =
QuestionnaireItemViewItem(
Questionnaire.QuestionnaireItemComponent(),
QuestionnaireResponse.QuestionnaireResponseItemComponent(),
validationResult = NotValidated,
answersChangedCallback = { _, _, _ -> },
)

runOnUI { viewHolder.bind(questionnaireItemView) }
onView(withId(R.id.date_input_layout)).perform(clickIcon(true))
onView(allOf(withText("OK")))
.inRoot(isDialog())
.check(matches(isDisplayed()))
.perform(ViewActions.click())
onView(withId(R.id.time_input_edit_text)).perform(ViewActions.click())
// R.id.material_textinput_timepicker is the id for the text input in the time picker.
onView(allOf(withId(R.id.material_textinput_timepicker)))
.inRoot(isDialog())
.check(matches(isDisplayed()))
}

@Test
fun showsTimePickerInClockMode() {
val questionnaireItemView =
QuestionnaireItemViewItem(
Questionnaire.QuestionnaireItemComponent(),
QuestionnaireResponse.QuestionnaireResponseItemComponent(),
validationResult = NotValidated,
answersChangedCallback = { _, _, _ -> },
)

runOnUI { viewHolder.bind(questionnaireItemView) }
onView(withId(R.id.date_input_layout)).perform(clickIcon(true))
onView(allOf(withText("OK")))
.inRoot(isDialog())
.check(matches(isDisplayed()))
.perform(ViewActions.click())
onView(withId(R.id.time_input_layout)).perform(clickIcon(true))
// R.id.material_clock_face is the id for the clock input in the time picker.
onView(allOf(withId(R.id.material_clock_face))).inRoot(isDialog()).check(matches(isDisplayed()))
}

/** Method to run code snippet on UI/main thread */
private fun runOnUI(action: () -> Unit) {
activityScenarioRule.getScenario().onActivity { activity -> action() }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import com.google.android.material.datepicker.MaterialDatePicker
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout
import com.google.android.material.timepicker.MaterialTimePicker
import com.google.android.material.timepicker.MaterialTimePicker.INPUT_MODE_CLOCK
import com.google.android.material.timepicker.MaterialTimePicker.INPUT_MODE_KEYBOARD
import com.google.android.material.timepicker.TimeFormat
import java.text.ParseException
import java.time.Instant
Expand Down Expand Up @@ -108,21 +110,10 @@ internal object QuestionnaireItemDateTimePickerViewHolderFactory :
// necessary to access the base context twice to retrieve the application object
// from the view's context.
val context = itemView.context.tryUnwrapContext()!!
createMaterialTimePicker(context)
.apply {
addOnPositiveButtonClickListener {
with(LocalTime.of(this.hour, this.minute, 0)) {
localTime = this
timeInputEditText.setText(this.toLocalizedString(context))
generateLocalDateTime(localDate, this)?.let {
updateDateTimeInput(it)
updateDateTimeAnswer(it)
}
timeInputEditText.clearFocus()
}
}
}
.show(context.supportFragmentManager, TAG_TIME_PICKER)
showMaterialTimePicker(context, INPUT_MODE_CLOCK)
}
timeInputEditText.setOnClickListener {
showMaterialTimePicker(itemView.context, INPUT_MODE_KEYBOARD)
}
}

Expand Down Expand Up @@ -283,25 +274,6 @@ internal object QuestionnaireItemDateTimePickerViewHolderFactory :
.build()
}

private fun createMaterialTimePicker(context: Context): MaterialTimePicker {
val selectedTime =
questionnaireItemViewItem.answers.singleOrNull()?.valueDateTimeType?.localTime
?: LocalTime.now()

return MaterialTimePicker.Builder()
.apply {
setTitleText(R.string.select_time)
setHour(selectedTime.hour)
setMinute(selectedTime.minute)
if (DateFormat.is24HourFormat(context)) {
setTimeFormat(TimeFormat.CLOCK_24H)
} else {
setTimeFormat(TimeFormat.CLOCK_12H)
}
}
.build()
}

private fun clearPreviousState() {
localDate = null
localTime = null
Expand All @@ -326,6 +298,39 @@ internal object QuestionnaireItemDateTimePickerViewHolderFactory :
if (answer == null || inputDate == null) return true
return answer.toLocalDate() != inputDate.toLocalDate()
}

private fun showMaterialTimePicker(context: Context, inputMode: Int) {
val selectedTime =
questionnaireItemViewItem.answers.singleOrNull()?.valueDateTimeType?.localTime
?: LocalTime.now()
val timeFormat =
if (DateFormat.is24HourFormat(context)) {
TimeFormat.CLOCK_24H
} else {
TimeFormat.CLOCK_12H
}
MaterialTimePicker.Builder()
.setTitleText(R.string.select_time)
.setHour(selectedTime.hour)
.setMinute(selectedTime.minute)
.setTimeFormat(timeFormat)
.setInputMode(inputMode)
.build()
.apply {
addOnPositiveButtonClickListener {
with(LocalTime.of(this.hour, this.minute, 0)) {
localTime = this
timeInputEditText.setText(this.toLocalizedString(context))
generateLocalDateTime(localDate, this)?.let {
updateDateTimeInput(it)
updateDateTimeAnswer(it)
}
timeInputEditText.clearFocus()
}
}
}
.show(context.tryUnwrapContext()!!.supportFragmentManager, TAG_TIME_PICKER)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
android:hint="@string/time"
android:inputType="none"
android:singleLine="true"
android:focusableInTouchMode="false"
/>

</com.google.android.material.textfield.TextInputLayout>
Expand Down

0 comments on commit b1c51f2

Please sign in to comment.