Skip to content

Commit b13d967

Browse files
Material Design Teamdrchen
authored andcommitted
Automated g4 rollback of changelist 799921970
PiperOrigin-RevId: 799988158
1 parent d2cce65 commit b13d967

File tree

12 files changed

+223
-278
lines changed

12 files changed

+223
-278
lines changed

catalog/java/io/material/catalog/AndroidManifest.xml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222

2323
<uses-sdk />
2424

25-
<uses-permission android:name="android.permission.VIBRATE"/>
26-
2725
<application
2826
android:name="io.material.catalog.application.${application_name}"
2927
android:allowBackup="true"

lib/java/com/google/android/material/timepicker/ChipTextInputComboView.java

Lines changed: 17 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import static com.google.android.material.timepicker.TimePickerView.GENERIC_VIEW_ACCESSIBILITY_CLASS_NAME;
2323

2424
import android.content.Context;
25-
import android.content.res.ColorStateList;
2625
import android.content.res.Configuration;
2726
import android.os.Build.VERSION;
2827
import android.os.Build.VERSION_CODES;
@@ -37,15 +36,13 @@
3736
import android.widget.EditText;
3837
import android.widget.FrameLayout;
3938
import android.widget.TextView;
40-
import androidx.annotation.ColorInt;
4139
import androidx.annotation.NonNull;
4240
import androidx.annotation.Nullable;
4341
import androidx.annotation.VisibleForTesting;
4442
import androidx.core.view.AccessibilityDelegateCompat;
4543
import androidx.core.view.ViewCompat;
4644
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
4745
import com.google.android.material.chip.Chip;
48-
import com.google.android.material.color.MaterialColors;
4946
import com.google.android.material.internal.TextWatcherAdapter;
5047
import com.google.android.material.internal.ViewUtils;
5148
import com.google.android.material.textfield.TextInputLayout;
@@ -62,15 +59,6 @@ class ChipTextInputComboView extends FrameLayout implements Checkable {
6259
private final EditText editText;
6360
private TextWatcher watcher;
6461
private TextView label;
65-
private CharSequence chipText = "";
66-
67-
private boolean hasError = false;
68-
private ColorStateList originalChipBackgroundColor;
69-
private ColorStateList originalChipTextColor;
70-
private ColorStateList originalEditTextColor;
71-
private ColorStateList originalEditTextCursorColor;
72-
private ColorStateList originalLabelColor;
73-
@ColorInt private int originalChipStrokeColor;
7462

7563
public ChipTextInputComboView(@NonNull Context context) {
7664
this(context, null);
@@ -117,14 +105,10 @@ public boolean isChecked() {
117105
@Override
118106
public void setChecked(boolean checked) {
119107
chip.setChecked(checked);
120-
if (checked) {
121-
chip.setText("");
122-
chip.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
123-
} else {
124-
chip.setText(chipText);
125-
chip.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
126-
}
127108
editText.setVisibility(checked ? VISIBLE : INVISIBLE);
109+
// TODO(b/247609386) Should not hide chip, we need the background in M3 (but not M2...).
110+
// Instead, the text in chip should be hidden.
111+
chip.setVisibility(checked ? GONE : VISIBLE);
128112
if (isChecked()) {
129113
ViewUtils.requestFocusAndShowKeyboard(editText, /* useWindowInsetsController= */ false);
130114
}
@@ -137,21 +121,30 @@ public void toggle() {
137121

138122
public void setText(CharSequence text) {
139123
String formattedText = formatText(text);
140-
chipText = formattedText;
141124
chip.setText(formattedText);
142125
if (!isEmpty(formattedText)) {
143126
editText.removeTextChangedListener(watcher);
144127

145128
editText.setText(formattedText);
146-
setAccessibilityDelegate(editText, chipText.toString(), label.getText());
129+
ViewCompat.setAccessibilityDelegate(
130+
editText,
131+
new AccessibilityDelegateCompat() {
132+
@Override
133+
public void onInitializeAccessibilityNodeInfo(
134+
@NonNull View host, @NonNull AccessibilityNodeInfoCompat info) {
135+
super.onInitializeAccessibilityNodeInfo(host, info);
136+
info.setText(formattedText);
137+
info.setHintText(label.getText());
138+
}
139+
});
147140

148141
editText.addTextChangedListener(watcher);
149142
}
150143
}
151144

152145
@VisibleForTesting
153146
CharSequence getChipText() {
154-
return chipText;
147+
return chip.getText();
155148
}
156149

157150
private String formatText(CharSequence text) {
@@ -191,91 +184,21 @@ public void setChipDelegate(AccessibilityDelegateCompat clickActionDelegate) {
191184
ViewCompat.setAccessibilityDelegate(chip, clickActionDelegate);
192185
}
193186

194-
public void setError(boolean hasError) {
195-
if (this.hasError == hasError) {
196-
return;
197-
}
198-
this.hasError = hasError;
199-
200-
if (hasError) {
201-
applyErrorColors();
202-
} else {
203-
clearErrorColors();
204-
}
205-
}
206-
207-
private void applyErrorColors() {
208-
originalChipBackgroundColor = chip.getChipBackgroundColor();
209-
originalChipTextColor = chip.getTextColors();
210-
originalEditTextColor = editText.getTextColors();
211-
originalLabelColor = label.getTextColors();
212-
originalChipStrokeColor = textInputLayout.getBoxStrokeColor();
213-
214-
// TODO(b/394610420): tokens and ColorStateList with error state
215-
ColorStateList colorErrorContainer =
216-
MaterialColors.getColorStateListOrNull(getContext(), R.attr.colorErrorContainer);
217-
ColorStateList colorOnErrorContainer =
218-
MaterialColors.getColorStateListOrNull(getContext(), R.attr.colorOnErrorContainer);
219-
if (colorErrorContainer != null && colorOnErrorContainer != null) {
220-
chip.setChipBackgroundColor(colorErrorContainer);
221-
chip.setTextColor(colorOnErrorContainer);
222-
editText.setTextColor(colorOnErrorContainer);
223-
textInputLayout.setBoxStrokeColor(colorOnErrorContainer.getDefaultColor());
224-
label.setTextColor(colorOnErrorContainer);
225-
if (VERSION.SDK_INT >= VERSION_CODES.Q) {
226-
originalEditTextCursorColor = textInputLayout.getCursorColor();
227-
textInputLayout.setCursorColor(colorOnErrorContainer);
228-
}
229-
}
230-
}
231-
232-
private void clearErrorColors() {
233-
chip.setChipBackgroundColor(originalChipBackgroundColor);
234-
chip.setTextColor(originalChipTextColor);
235-
editText.setTextColor(originalEditTextColor);
236-
textInputLayout.setBoxStrokeColor(originalChipStrokeColor);
237-
label.setTextColor(originalLabelColor);
238-
if (VERSION.SDK_INT >= VERSION_CODES.Q) {
239-
textInputLayout.setCursorColor(originalEditTextCursorColor);
240-
}
241-
}
242-
243-
public boolean hasError() {
244-
return hasError;
245-
}
246-
247187
private class TextFormatter extends TextWatcherAdapter {
248188

249189
private static final String DEFAULT_TEXT = "00";
250190

251191
@Override
252192
public void afterTextChanged(Editable editable) {
253193
if (isEmpty(editable)) {
254-
chipText = formatText(DEFAULT_TEXT);
194+
chip.setText(formatText(DEFAULT_TEXT));
255195
return;
256196
}
257197
String formattedText = formatText(editable);
258-
chipText = isEmpty(formattedText) ? formatText(DEFAULT_TEXT) : formattedText;
259-
setAccessibilityDelegate(editText, editable.toString(), label.getText());
198+
chip.setText(isEmpty(formattedText) ? formatText(DEFAULT_TEXT) : formattedText);
260199
}
261200
}
262201

263-
private void setAccessibilityDelegate(
264-
@NonNull View view, CharSequence text, @Nullable CharSequence hint) {
265-
ViewCompat.setAccessibilityDelegate(
266-
view,
267-
new AccessibilityDelegateCompat() {
268-
@Override
269-
public void onInitializeAccessibilityNodeInfo(
270-
@NonNull View host, @NonNull AccessibilityNodeInfoCompat info) {
271-
super.onInitializeAccessibilityNodeInfo(host, info);
272-
info.setText(text);
273-
info.setHintText(hint);
274-
info.setMaxTextLength(2);
275-
}
276-
});
277-
}
278-
279202
@Override
280203
protected void onConfigurationChanged(Configuration newConfig) {
281204
super.onConfigurationChanged(newConfig);

lib/java/com/google/android/material/timepicker/MaterialTimePicker.java

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ public final class MaterialTimePicker extends DialogFragment implements OnDouble
113113
static final String OVERRIDE_THEME_RES_ID = "TIME_PICKER_OVERRIDE_THEME_RES_ID";
114114

115115
private MaterialButton modeButton;
116-
private Button okButton;
117116
private Button cancelButton;
118117

119118
@InputMode private int inputMode = INPUT_MODE_CLOCK;
@@ -276,8 +275,6 @@ public final View onCreateView(
276275
timePickerView.setOnDoubleTapListener(this);
277276
textInputStub = root.findViewById(R.id.material_textinput_timepicker);
278277
modeButton = root.findViewById(R.id.material_timepicker_mode_button);
279-
okButton = root.findViewById(R.id.material_timepicker_ok_button);
280-
cancelButton = root.findViewById(R.id.material_timepicker_cancel_button);
281278
TextView headerTitle = root.findViewById(R.id.header_title);
282279

283280
if (titleResId != 0) {
@@ -287,26 +284,24 @@ public final View onCreateView(
287284
}
288285

289286
updateInputMode(modeButton);
287+
Button okButton = root.findViewById(R.id.material_timepicker_ok_button);
290288
okButton.setOnClickListener(
291-
v -> {
292-
if (activePresenter instanceof TimePickerTextInputPresenter) {
293-
TimePickerTextInputPresenter presenter = (TimePickerTextInputPresenter) activePresenter;
294-
if (presenter.hasError()) {
295-
presenter.vibrateAndMaybeBeep(root.getContext());
296-
return;
289+
new OnClickListener() {
290+
@Override
291+
public void onClick(View v) {
292+
for (OnClickListener listener : positiveButtonListeners) {
293+
listener.onClick(v);
297294
}
295+
dismiss();
298296
}
299-
for (OnClickListener listener : positiveButtonListeners) {
300-
listener.onClick(v);
301-
}
302-
dismiss();
303297
});
304298
if (positiveButtonTextResId != 0) {
305299
okButton.setText(positiveButtonTextResId);
306300
} else if (!TextUtils.isEmpty(positiveButtonText)) {
307301
okButton.setText(positiveButtonText);
308302
}
309303

304+
cancelButton = root.findViewById(R.id.material_timepicker_cancel_button);
310305
cancelButton.setOnClickListener(
311306
v -> {
312307
for (OnClickListener listener : negativeButtonListeners) {
@@ -435,7 +430,6 @@ private TimePickerPresenter initializeOrRetrieveActivePresenterForMode(
435430
timePickerTextInputPresenter = new TimePickerTextInputPresenter(textInputView, time);
436431
}
437432

438-
timePickerTextInputPresenter.clearError();
439433
timePickerTextInputPresenter.clearCheck();
440434

441435
return timePickerTextInputPresenter;
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright (C) 2020 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.android.material.timepicker;
18+
19+
import android.text.InputFilter;
20+
import android.text.Spanned;
21+
22+
/** A {@link InputFilter} that prevents a value bigger that {@code max} from being entered */
23+
class MaxInputValidator implements InputFilter {
24+
private int max;
25+
26+
public MaxInputValidator(int max) {
27+
this.max = max;
28+
}
29+
30+
public void setMax(int max) {
31+
this.max = max;
32+
}
33+
34+
public int getMax() {
35+
return max;
36+
}
37+
38+
@Override
39+
public CharSequence filter(
40+
CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
41+
try {
42+
StringBuilder builder = new StringBuilder(dest);
43+
builder.replace(dstart, dend, source.subSequence(start, end).toString());
44+
String newVal = builder.toString();
45+
int input = Integer.parseInt(newVal);
46+
if (input <= max) {
47+
return null;
48+
}
49+
} catch (NumberFormatException ok) {
50+
// Just ignored if we couldn't parse the number
51+
}
52+
return "";
53+
}
54+
}

lib/java/com/google/android/material/timepicker/TimeModel.java

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ class TimeModel implements Parcelable {
4040
public static final String ZERO_LEADING_NUMBER_FORMAT = "%02d";
4141
public static final String NUMBER_FORMAT = "%d";
4242

43+
private final MaxInputValidator minuteInputValidator;
44+
private final MaxInputValidator hourInputValidator;
45+
4346
@TimeFormat final int format;
4447

4548
int hour;
@@ -62,6 +65,8 @@ public TimeModel(int hour, int minute, @ActiveSelection int selection, @TimeForm
6265
this.selection = selection;
6366
this.format = format;
6467
period = getPeriod(hour);
68+
minuteInputValidator = new MaxInputValidator(59);
69+
hourInputValidator = new MaxInputValidator(format == CLOCK_24H ? 23 : 12);
6570
}
6671

6772
protected TimeModel(Parcel in) {
@@ -114,6 +119,14 @@ public int getHourContentDescriptionResId() {
114119
return format == CLOCK_24H ? R.string.material_hour_24h_suffix : R.string.material_hour_suffix;
115120
}
116121

122+
public MaxInputValidator getMinuteInputValidator() {
123+
return minuteInputValidator;
124+
}
125+
126+
public MaxInputValidator getHourInputValidator() {
127+
return hourInputValidator;
128+
}
129+
117130
@Override
118131
public int hashCode() {
119132
Object[] hashedFields = {format, hour, minute, selection};
@@ -151,18 +164,17 @@ public void writeToParcel(Parcel dest, int flags) {
151164
}
152165

153166
@SuppressWarnings("unused")
154-
public static final Parcelable.Creator<TimeModel> CREATOR =
155-
new Parcelable.Creator<TimeModel>() {
156-
@Override
157-
public TimeModel createFromParcel(Parcel in) {
158-
return new TimeModel(in);
159-
}
160-
161-
@Override
162-
public TimeModel[] newArray(int size) {
163-
return new TimeModel[size];
164-
}
165-
};
167+
public static final Parcelable.Creator<TimeModel> CREATOR = new Parcelable.Creator<TimeModel>() {
168+
@Override
169+
public TimeModel createFromParcel(Parcel in) {
170+
return new TimeModel(in);
171+
}
172+
173+
@Override
174+
public TimeModel[] newArray(int size) {
175+
return new TimeModel[size];
176+
}
177+
};
166178

167179
public void setPeriod(@ClockPeriod int period) {
168180
if (period != this.period) {

lib/java/com/google/android/material/timepicker/TimePickerTextInputKeyController.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,7 @@ private boolean onHourKeyPress(int keyCode, KeyEvent event, EditText editText) {
131131
&& keyCode <= KeyEvent.KEYCODE_9
132132
&& event.getAction() == KeyEvent.ACTION_UP
133133
&& editText.getSelectionStart() == 2
134-
&& text.length() == 2
135-
&& !hourLayoutComboView.hasError();
134+
&& text.length() == 2;
136135
if (switchFocus) {
137136
moveSelection(MINUTE);
138137
return true;

0 commit comments

Comments
 (0)