From 770e519ff2be1b3cbd71064f16f71f8585efe795 Mon Sep 17 00:00:00 2001 From: pubiqq Date: Wed, 10 Sep 2025 21:29:52 +0300 Subject: [PATCH] [TimePicker] Fix default title for text input mode --- .../timepicker/MaterialTimePicker.java | 124 ++++++++++++------ .../res/layout/material_timepicker_dialog.xml | 2 - .../timepicker/res/values/strings.xml | 3 +- 3 files changed, 85 insertions(+), 44 deletions(-) diff --git a/lib/java/com/google/android/material/timepicker/MaterialTimePicker.java b/lib/java/com/google/android/material/timepicker/MaterialTimePicker.java index 69f06dd8e9f..9a96aad4bff 100644 --- a/lib/java/com/google/android/material/timepicker/MaterialTimePicker.java +++ b/lib/java/com/google/android/material/timepicker/MaterialTimePicker.java @@ -29,6 +29,7 @@ import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.os.Bundle; +import androidx.core.view.ViewCompat; import androidx.fragment.app.DialogFragment; import androidx.appcompat.widget.TooltipCompat; import android.text.TextUtils; @@ -112,9 +113,11 @@ public final class MaterialTimePicker extends DialogFragment implements OnDouble static final String NEGATIVE_BUTTON_TEXT_EXTRA = "TIME_PICKER_NEGATIVE_BUTTON_TEXT"; static final String OVERRIDE_THEME_RES_ID = "TIME_PICKER_OVERRIDE_THEME_RES_ID"; + private ViewGroup root; private MaterialButton modeButton; private Button okButton; private Button cancelButton; + private TextView headerTitle; @InputMode private int inputMode = INPUT_MODE_CLOCK; @@ -270,23 +273,16 @@ public final View onCreateView( @NonNull LayoutInflater layoutInflater, @Nullable ViewGroup viewGroup, @Nullable Bundle bundle) { - ViewGroup root = - (ViewGroup) layoutInflater.inflate(R.layout.material_timepicker_dialog, viewGroup); + root = (ViewGroup) layoutInflater.inflate(R.layout.material_timepicker_dialog, viewGroup); timePickerView = root.findViewById(R.id.material_timepicker_view); timePickerView.setOnDoubleTapListener(this); textInputStub = root.findViewById(R.id.material_textinput_timepicker); modeButton = root.findViewById(R.id.material_timepicker_mode_button); okButton = root.findViewById(R.id.material_timepicker_ok_button); cancelButton = root.findViewById(R.id.material_timepicker_cancel_button); - TextView headerTitle = root.findViewById(R.id.header_title); + headerTitle = root.findViewById(R.id.header_title); - if (titleResId != 0) { - headerTitle.setText(titleResId); - } else if (!TextUtils.isEmpty(titleText)) { - headerTitle.setText(titleText); - } - - updateInputMode(modeButton); + updateInputMode(inputMode, /* force= */ true); okButton.setOnClickListener( v -> { if (activePresenter instanceof TimePickerTextInputPresenter) { @@ -323,10 +319,7 @@ public final View onCreateView( updateCancelButtonVisibility(); modeButton.setOnClickListener( - v -> { - inputMode = (inputMode == INPUT_MODE_CLOCK) ? INPUT_MODE_KEYBOARD : INPUT_MODE_CLOCK; - updateInputMode(modeButton); - }); + v -> updateInputMode(inputMode == INPUT_MODE_CLOCK ? INPUT_MODE_KEYBOARD : INPUT_MODE_CLOCK)); return root; } @@ -385,13 +378,28 @@ public void setCancelable(boolean cancelable) { @RestrictTo(LIBRARY_GROUP) @Override public void onDoubleTap() { - inputMode = INPUT_MODE_KEYBOARD; - updateInputMode(modeButton); + updateInputMode(INPUT_MODE_KEYBOARD); timePickerTextInputPresenter.resetChecked(); } - private void updateInputMode(MaterialButton modeButton) { - if (modeButton == null || timePickerView == null || textInputStub == null) { + private void updateInputMode(@InputMode int inputMode) { + updateInputMode(inputMode, /* force= */ false); + } + + private void updateInputMode(@InputMode int inputMode, boolean force) { + if (!force && this.inputMode == inputMode) { + return; + } + + this.inputMode = inputMode; + + updateActivePresenter(inputMode); + updateModeButton(inputMode); + updateHeader(inputMode); + } + + private void updateActivePresenter(@InputMode int inputMode) { + if (timePickerView == null || textInputStub == null) { return; } @@ -403,16 +411,67 @@ private void updateInputMode(MaterialButton modeButton) { initializeOrRetrieveActivePresenterForMode(inputMode, timePickerView, textInputStub); activePresenter.show(); activePresenter.invalidate(); - ModeButtonData modeButtonData = getModeButtonData(inputMode); - modeButton.setIconResource(modeButtonData.iconResId); - modeButton.setContentDescription( - getResources().getString(modeButtonData.contentDescriptionResId)); - TooltipCompat.setTooltipText( - modeButton, getResources().getString(modeButtonData.tooltipTextResId)); + } + + private void updateModeButton(@InputMode int inputMode) { + if (modeButton == null) { + return; + } + + @DrawableRes final int iconResId; + @StringRes final int contentDescriptionResId; + @StringRes final int tooltipTextResId; + + switch (inputMode) { + case INPUT_MODE_KEYBOARD: + iconResId = clockIcon; + contentDescriptionResId = R.string.material_timepicker_clock_mode_description; + tooltipTextResId = R.string.material_timepicker_clock_mode_tooltip; + break; + case INPUT_MODE_CLOCK: + iconResId = keyboardIcon; + contentDescriptionResId = R.string.material_timepicker_text_input_mode_description; + tooltipTextResId = R.string.material_timepicker_text_input_mode_tooltip; + break; + default: + throw new IllegalArgumentException("Unexpected input mode: " + inputMode); + } + + modeButton.setIconResource(iconResId); + modeButton.setContentDescription(getString(contentDescriptionResId)); + TooltipCompat.setTooltipText(modeButton, getString(tooltipTextResId)); modeButton.sendAccessibilityEvent( AccessibilityEventCompat.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION); } + private void updateHeader(int inputMode) { + if (root == null || headerTitle == null) { + return; + } + + final CharSequence title; + + if (titleResId != 0) { + title = getString(titleResId); + } else if (!TextUtils.isEmpty(titleText)) { + title = titleText; + } else { + switch (inputMode) { + case INPUT_MODE_KEYBOARD: + title = getString(R.string.material_timepicker_enter_time); + break; + case INPUT_MODE_CLOCK: + title = getString(R.string.material_timepicker_select_time); + break; + default: + throw new IllegalArgumentException("Unexpected input mode: " + inputMode); + } + } + + headerTitle.setText(title); + ViewCompat.setAccessibilityPaneTitle(root, title); + } + private void updateCancelButtonVisibility() { if (cancelButton != null) { cancelButton.setVisibility(isCancelable() ? View.VISIBLE : View.GONE); @@ -441,23 +500,6 @@ private TimePickerPresenter initializeOrRetrieveActivePresenterForMode( return timePickerTextInputPresenter; } - private ModeButtonData getModeButtonData(@InputMode int mode) { - switch (mode) { - case INPUT_MODE_KEYBOARD: - return new ModeButtonData( - clockIcon, - R.string.material_timepicker_clock_mode_description, - R.string.material_timepicker_clock_mode_tooltip); - case INPUT_MODE_CLOCK: - return new ModeButtonData( - keyboardIcon, - R.string.material_timepicker_text_input_mode_description, - R.string.material_timepicker_text_input_mode_tooltip); - default: - throw new IllegalArgumentException("no button data for mode: " + mode); - } - } - @Nullable TimePickerClockPresenter getTimePickerClockPresenter() { return timePickerClockPresenter; diff --git a/lib/java/com/google/android/material/timepicker/res/layout/material_timepicker_dialog.xml b/lib/java/com/google/android/material/timepicker/res/layout/material_timepicker_dialog.xml index 49acb091aa8..65322bd5f23 100644 --- a/lib/java/com/google/android/material/timepicker/res/layout/material_timepicker_dialog.xml +++ b/lib/java/com/google/android/material/timepicker/res/layout/material_timepicker_dialog.xml @@ -20,7 +20,6 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:accessibilityPaneTitle="@string/material_timepicker_select_time" android:paddingBottom="2dp"> diff --git a/lib/java/com/google/android/material/timepicker/res/values/strings.xml b/lib/java/com/google/android/material/timepicker/res/values/strings.xml index 19439e81cbf..a8e04324dc7 100644 --- a/lib/java/com/google/android/material/timepicker/res/values/strings.xml +++ b/lib/java/com/google/android/material/timepicker/res/values/strings.xml @@ -18,7 +18,8 @@ PM AM - Select time + Select time + Enter time Minute Hour Minute must be 0–59