OSDN Git Service

Remove unnecessary casts on calls to findViewById
[android-x86/frameworks-base.git] / core / java / android / widget / TextInputTimePickerView.java
1 /*
2  * Copyright (C) 2017 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 android.widget;
18
19 import android.content.Context;
20 import android.text.Editable;
21 import android.text.InputFilter;
22 import android.text.TextWatcher;
23 import android.util.AttributeSet;
24 import android.util.MathUtils;
25 import android.view.View;
26
27 import com.android.internal.R;
28
29 /**
30  * View to show text input based time picker with hour and minute fields and an optional AM/PM
31  * spinner.
32  *
33  * @hide
34  */
35 public class TextInputTimePickerView extends RelativeLayout {
36     public static final int HOURS = 0;
37     public static final int MINUTES = 1;
38     public static final int AMPM = 2;
39
40     private static final int AM = 0;
41     private static final int PM = 1;
42
43     private final EditText mHourEditText;
44     private final EditText mMinuteEditText;
45     private final TextView mInputSeparatorView;
46     private final Spinner mAmPmSpinner;
47     private final TextView mErrorLabel;
48     private final TextView mHourLabel;
49     private final TextView mMinuteLabel;
50
51     private boolean mIs24Hour;
52     private boolean mHourFormatStartsAtZero;
53     private OnValueTypedListener mListener;
54
55     private boolean mErrorShowing;
56
57     interface OnValueTypedListener {
58         void onValueChanged(int inputType, int newValue);
59     }
60
61     public TextInputTimePickerView(Context context) {
62         this(context, null);
63     }
64
65     public TextInputTimePickerView(Context context, AttributeSet attrs) {
66         this(context, attrs, 0);
67     }
68
69     public TextInputTimePickerView(Context context, AttributeSet attrs, int defStyle) {
70         this(context, attrs, defStyle, 0);
71     }
72
73     public TextInputTimePickerView(Context context, AttributeSet attrs, int defStyle,
74             int defStyleRes) {
75         super(context, attrs, defStyle, defStyleRes);
76
77         inflate(context, R.layout.time_picker_text_input_material, this);
78
79         mHourEditText = findViewById(R.id.input_hour);
80         mMinuteEditText = findViewById(R.id.input_minute);
81         mInputSeparatorView = findViewById(R.id.input_separator);
82         mErrorLabel = findViewById(R.id.label_error);
83         mHourLabel = findViewById(R.id.label_hour);
84         mMinuteLabel = findViewById(R.id.label_minute);
85
86         mHourEditText.addTextChangedListener(new TextWatcher() {
87             @Override
88             public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
89
90             @Override
91             public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
92
93             @Override
94             public void afterTextChanged(Editable editable) {
95                 parseAndSetHourInternal(editable.toString());
96             }
97         });
98
99         mMinuteEditText.addTextChangedListener(new TextWatcher() {
100             @Override
101             public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
102
103             @Override
104             public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
105
106             @Override
107             public void afterTextChanged(Editable editable) {
108                 parseAndSetMinuteInternal(editable.toString());
109             }
110         });
111
112         mAmPmSpinner = findViewById(R.id.am_pm_spinner);
113         final String[] amPmStrings = TimePicker.getAmPmStrings(context);
114         ArrayAdapter<CharSequence> adapter =
115                 new ArrayAdapter<CharSequence>(context, R.layout.simple_spinner_dropdown_item);
116         adapter.add(TimePickerClockDelegate.obtainVerbatim(amPmStrings[0]));
117         adapter.add(TimePickerClockDelegate.obtainVerbatim(amPmStrings[1]));
118         mAmPmSpinner.setAdapter(adapter);
119         mAmPmSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
120             @Override
121             public void onItemSelected(AdapterView<?> adapterView, View view, int position,
122                     long id) {
123                 if (position == 0) {
124                     mListener.onValueChanged(AMPM, AM);
125                 } else {
126                     mListener.onValueChanged(AMPM, PM);
127                 }
128             }
129
130             @Override
131             public void onNothingSelected(AdapterView<?> adapterView) {}
132         });
133     }
134
135     void setListener(OnValueTypedListener listener) {
136         mListener = listener;
137     }
138
139     void setHourFormat(int maxCharLength) {
140         mHourEditText.setFilters(new InputFilter[] {
141                 new InputFilter.LengthFilter(maxCharLength)});
142         mMinuteEditText.setFilters(new InputFilter[] {
143                 new InputFilter.LengthFilter(maxCharLength)});
144     }
145
146     boolean validateInput() {
147         final boolean inputValid = parseAndSetHourInternal(mHourEditText.getText().toString())
148                 && parseAndSetMinuteInternal(mMinuteEditText.getText().toString());
149         setError(!inputValid);
150         return inputValid;
151     }
152
153     void updateSeparator(String separatorText) {
154         mInputSeparatorView.setText(separatorText);
155     }
156
157     private void setError(boolean enabled) {
158         mErrorShowing = enabled;
159
160         mErrorLabel.setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
161         mHourLabel.setVisibility(enabled ? View.INVISIBLE : View.VISIBLE);
162         mMinuteLabel.setVisibility(enabled ? View.INVISIBLE : View.VISIBLE);
163     }
164
165     /**
166      * Computes the display value and updates the text of the view.
167      * <p>
168      * This method should be called whenever the current value or display
169      * properties (leading zeroes, max digits) change.
170      */
171     void updateTextInputValues(int localizedHour, int minute, int amOrPm, boolean is24Hour,
172             boolean hourFormatStartsAtZero) {
173         final String format = "%d";
174
175         mIs24Hour = is24Hour;
176         mHourFormatStartsAtZero = hourFormatStartsAtZero;
177
178         mAmPmSpinner.setVisibility(is24Hour ? View.INVISIBLE : View.VISIBLE);
179
180         if (amOrPm == AM) {
181             mAmPmSpinner.setSelection(0);
182         } else {
183             mAmPmSpinner.setSelection(1);
184         }
185
186         mHourEditText.setText(String.format(format, localizedHour));
187         mMinuteEditText.setText(String.format(format, minute));
188
189         if (mErrorShowing) {
190             validateInput();
191         }
192     }
193
194     private boolean parseAndSetHourInternal(String input) {
195         try {
196             final int hour = Integer.parseInt(input);
197             if (!isValidLocalizedHour(hour)) {
198                 final int minHour = mHourFormatStartsAtZero ? 0 : 1;
199                 final int maxHour = mIs24Hour ? 23 : 11 + minHour;
200                 mListener.onValueChanged(HOURS, getHourOfDayFromLocalizedHour(
201                         MathUtils.constrain(hour, minHour, maxHour)));
202                 return false;
203             }
204             mListener.onValueChanged(HOURS, getHourOfDayFromLocalizedHour(hour));
205             return true;
206         } catch (NumberFormatException e) {
207             // Do nothing since we cannot parse the input.
208             return false;
209         }
210     }
211
212     private boolean parseAndSetMinuteInternal(String input) {
213         try {
214             final int minutes = Integer.parseInt(input);
215             if (minutes < 0 || minutes > 59) {
216                 mListener.onValueChanged(MINUTES, MathUtils.constrain(minutes, 0, 59));
217                 return false;
218             }
219             mListener.onValueChanged(MINUTES, minutes);
220             return true;
221         } catch (NumberFormatException e) {
222             // Do nothing since we cannot parse the input.
223             return false;
224         }
225     }
226
227     private boolean isValidLocalizedHour(int localizedHour) {
228         final int minHour = mHourFormatStartsAtZero ? 0 : 1;
229         final int maxHour = (mIs24Hour ? 23 : 11) + minHour;
230         return localizedHour >= minHour && localizedHour <= maxHour;
231     }
232
233     private int getHourOfDayFromLocalizedHour(int localizedHour) {
234         int hourOfDay = localizedHour;
235         if (mIs24Hour) {
236             if (!mHourFormatStartsAtZero && localizedHour == 24) {
237                 hourOfDay = 0;
238             }
239         } else {
240             if (!mHourFormatStartsAtZero && localizedHour == 12) {
241                 hourOfDay = 0;
242             }
243             if (mAmPmSpinner.getSelectedItemPosition() == 1) {
244                 hourOfDay += 12;
245             }
246         }
247         return hourOfDay;
248     }
249 }