1 /* 2 * Copyright (C) 2007 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.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.Widget; 22 import android.content.Context; 23 import android.content.res.Configuration; 24 import android.content.res.TypedArray; 25 import android.os.Parcel; 26 import android.os.Parcelable; 27 import android.os.Parcelable.Creator; 28 import android.util.AttributeSet; 29 import android.view.View; 30 import android.view.accessibility.AccessibilityEvent; 31 import com.android.internal.R; 32 33 import java.util.Locale; 34 35 import libcore.icu.LocaleData; 36 37 /** 38 * A widget for selecting the time of day, in either 24-hour or AM/PM mode. 39 * <p> 40 * For a dialog using this view, see {@link android.app.TimePickerDialog}. See 41 * the <a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a> 42 * guide for more information. 43 * 44 * @attr ref android.R.styleable#TimePicker_timePickerMode 45 */ 46 @Widget 47 public class TimePicker extends FrameLayout { 48 private static final int MODE_SPINNER = 1; 49 private static final int MODE_CLOCK = 2; 50 51 private final TimePickerDelegate mDelegate; 52 53 /** 54 * The callback interface used to indicate the time has been adjusted. 55 */ 56 public interface OnTimeChangedListener { 57 58 /** 59 * @param view The view associated with this listener. 60 * @param hourOfDay The current hour. 61 * @param minute The current minute. 62 */ onTimeChanged(TimePicker view, int hourOfDay, int minute)63 void onTimeChanged(TimePicker view, int hourOfDay, int minute); 64 } 65 TimePicker(Context context)66 public TimePicker(Context context) { 67 this(context, null); 68 } 69 TimePicker(Context context, AttributeSet attrs)70 public TimePicker(Context context, AttributeSet attrs) { 71 this(context, attrs, R.attr.timePickerStyle); 72 } 73 TimePicker(Context context, AttributeSet attrs, int defStyleAttr)74 public TimePicker(Context context, AttributeSet attrs, int defStyleAttr) { 75 this(context, attrs, defStyleAttr, 0); 76 } 77 TimePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)78 public TimePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 79 super(context, attrs, defStyleAttr, defStyleRes); 80 81 final TypedArray a = context.obtainStyledAttributes( 82 attrs, R.styleable.TimePicker, defStyleAttr, defStyleRes); 83 final int mode = a.getInt(R.styleable.TimePicker_timePickerMode, MODE_SPINNER); 84 a.recycle(); 85 86 switch (mode) { 87 case MODE_CLOCK: 88 mDelegate = new TimePickerClockDelegate( 89 this, context, attrs, defStyleAttr, defStyleRes); 90 break; 91 case MODE_SPINNER: 92 default: 93 mDelegate = new TimePickerSpinnerDelegate( 94 this, context, attrs, defStyleAttr, defStyleRes); 95 break; 96 } 97 } 98 99 /** 100 * Sets the currently selected hour using 24-hour time. 101 * 102 * @param hour the hour to set, in the range (0-23) 103 * @see #getHour() 104 */ setHour(int hour)105 public void setHour(int hour) { 106 mDelegate.setHour(hour); 107 } 108 109 /** 110 * Returns the currently selected hour using 24-hour time. 111 * 112 * @return the currently selected hour, in the range (0-23) 113 * @see #setHour(int) 114 */ getHour()115 public int getHour() { 116 return mDelegate.getHour(); 117 } 118 119 /** 120 * Sets the currently selected minute.. 121 * 122 * @param minute the minute to set, in the range (0-59) 123 * @see #getMinute() 124 */ setMinute(int minute)125 public void setMinute(int minute) { 126 mDelegate.setMinute(minute); 127 } 128 129 /** 130 * Returns the currently selected minute. 131 * 132 * @return the currently selected minute, in the range (0-59) 133 * @see #setMinute(int) 134 */ getMinute()135 public int getMinute() { 136 return mDelegate.getMinute(); 137 } 138 139 /** 140 * Sets the current hour. 141 * 142 * @deprecated Use {@link #setHour(int)} 143 */ 144 @Deprecated setCurrentHour(@onNull Integer currentHour)145 public void setCurrentHour(@NonNull Integer currentHour) { 146 setHour(currentHour); 147 } 148 149 /** 150 * @return the current hour in the range (0-23) 151 * @deprecated Use {@link #getHour()} 152 */ 153 @NonNull 154 @Deprecated getCurrentHour()155 public Integer getCurrentHour() { 156 return mDelegate.getHour(); 157 } 158 159 /** 160 * Set the current minute (0-59). 161 * 162 * @deprecated Use {@link #setMinute(int)} 163 */ 164 @Deprecated setCurrentMinute(@onNull Integer currentMinute)165 public void setCurrentMinute(@NonNull Integer currentMinute) { 166 mDelegate.setMinute(currentMinute); 167 } 168 169 /** 170 * @return the current minute 171 * @deprecated Use {@link #getMinute()} 172 */ 173 @NonNull 174 @Deprecated getCurrentMinute()175 public Integer getCurrentMinute() { 176 return mDelegate.getMinute(); 177 } 178 179 /** 180 * Sets whether this widget displays time in 24-hour mode or 12-hour mode 181 * with an AM/PM picker. 182 * 183 * @param is24HourView {@code true} to display in 24-hour mode, 184 * {@code false} for 12-hour mode with AM/PM 185 * @see #is24HourView() 186 */ setIs24HourView(@onNull Boolean is24HourView)187 public void setIs24HourView(@NonNull Boolean is24HourView) { 188 if (is24HourView == null) { 189 return; 190 } 191 192 mDelegate.setIs24Hour(is24HourView); 193 } 194 195 /** 196 * @return {@code true} if this widget displays time in 24-hour mode, 197 * {@code false} otherwise} 198 * @see #setIs24HourView(Boolean) 199 */ is24HourView()200 public boolean is24HourView() { 201 return mDelegate.is24Hour(); 202 } 203 204 /** 205 * Set the callback that indicates the time has been adjusted by the user. 206 * 207 * @param onTimeChangedListener the callback, should not be null. 208 */ setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener)209 public void setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener) { 210 mDelegate.setOnTimeChangedListener(onTimeChangedListener); 211 } 212 213 @Override setEnabled(boolean enabled)214 public void setEnabled(boolean enabled) { 215 super.setEnabled(enabled); 216 mDelegate.setEnabled(enabled); 217 } 218 219 @Override isEnabled()220 public boolean isEnabled() { 221 return mDelegate.isEnabled(); 222 } 223 224 @Override getBaseline()225 public int getBaseline() { 226 return mDelegate.getBaseline(); 227 } 228 229 @Override onSaveInstanceState()230 protected Parcelable onSaveInstanceState() { 231 Parcelable superState = super.onSaveInstanceState(); 232 return mDelegate.onSaveInstanceState(superState); 233 } 234 235 @Override onRestoreInstanceState(Parcelable state)236 protected void onRestoreInstanceState(Parcelable state) { 237 BaseSavedState ss = (BaseSavedState) state; 238 super.onRestoreInstanceState(ss.getSuperState()); 239 mDelegate.onRestoreInstanceState(ss); 240 } 241 242 @Override getAccessibilityClassName()243 public CharSequence getAccessibilityClassName() { 244 return TimePicker.class.getName(); 245 } 246 247 /** @hide */ 248 @Override dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event)249 public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) { 250 return mDelegate.dispatchPopulateAccessibilityEvent(event); 251 } 252 253 /** 254 * A delegate interface that defined the public API of the TimePicker. Allows different 255 * TimePicker implementations. This would need to be implemented by the TimePicker delegates 256 * for the real behavior. 257 */ 258 interface TimePickerDelegate { setHour(int hour)259 void setHour(int hour); getHour()260 int getHour(); 261 setMinute(int minute)262 void setMinute(int minute); getMinute()263 int getMinute(); 264 setIs24Hour(boolean is24Hour)265 void setIs24Hour(boolean is24Hour); is24Hour()266 boolean is24Hour(); 267 setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener)268 void setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener); 269 setEnabled(boolean enabled)270 void setEnabled(boolean enabled); isEnabled()271 boolean isEnabled(); 272 getBaseline()273 int getBaseline(); 274 onSaveInstanceState(Parcelable superState)275 Parcelable onSaveInstanceState(Parcelable superState); onRestoreInstanceState(Parcelable state)276 void onRestoreInstanceState(Parcelable state); 277 dispatchPopulateAccessibilityEvent(AccessibilityEvent event)278 boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event); onPopulateAccessibilityEvent(AccessibilityEvent event)279 void onPopulateAccessibilityEvent(AccessibilityEvent event); 280 } 281 getAmPmStrings(Context context)282 static String[] getAmPmStrings(Context context) { 283 final Locale locale = context.getResources().getConfiguration().locale; 284 final LocaleData d = LocaleData.get(locale); 285 286 final String[] result = new String[2]; 287 result[0] = d.amPm[0].length() > 4 ? d.narrowAm : d.amPm[0]; 288 result[1] = d.amPm[1].length() > 4 ? d.narrowPm : d.amPm[1]; 289 return result; 290 } 291 292 /** 293 * An abstract class which can be used as a start for TimePicker implementations 294 */ 295 abstract static class AbstractTimePickerDelegate implements TimePickerDelegate { 296 protected final TimePicker mDelegator; 297 protected final Context mContext; 298 protected final Locale mLocale; 299 300 protected OnTimeChangedListener mOnTimeChangedListener; 301 AbstractTimePickerDelegate(@onNull TimePicker delegator, @NonNull Context context)302 public AbstractTimePickerDelegate(@NonNull TimePicker delegator, @NonNull Context context) { 303 mDelegator = delegator; 304 mContext = context; 305 mLocale = context.getResources().getConfiguration().locale; 306 } 307 308 protected static class SavedState extends View.BaseSavedState { 309 private final int mHour; 310 private final int mMinute; 311 private final boolean mIs24HourMode; 312 private final int mCurrentItemShowing; 313 SavedState(Parcelable superState, int hour, int minute, boolean is24HourMode)314 public SavedState(Parcelable superState, int hour, int minute, boolean is24HourMode) { 315 this(superState, hour, minute, is24HourMode, 0); 316 } 317 SavedState(Parcelable superState, int hour, int minute, boolean is24HourMode, int currentItemShowing)318 public SavedState(Parcelable superState, int hour, int minute, boolean is24HourMode, 319 int currentItemShowing) { 320 super(superState); 321 mHour = hour; 322 mMinute = minute; 323 mIs24HourMode = is24HourMode; 324 mCurrentItemShowing = currentItemShowing; 325 } 326 SavedState(Parcel in)327 private SavedState(Parcel in) { 328 super(in); 329 mHour = in.readInt(); 330 mMinute = in.readInt(); 331 mIs24HourMode = (in.readInt() == 1); 332 mCurrentItemShowing = in.readInt(); 333 } 334 getHour()335 public int getHour() { 336 return mHour; 337 } 338 getMinute()339 public int getMinute() { 340 return mMinute; 341 } 342 is24HourMode()343 public boolean is24HourMode() { 344 return mIs24HourMode; 345 } 346 getCurrentItemShowing()347 public int getCurrentItemShowing() { 348 return mCurrentItemShowing; 349 } 350 351 @Override writeToParcel(Parcel dest, int flags)352 public void writeToParcel(Parcel dest, int flags) { 353 super.writeToParcel(dest, flags); 354 dest.writeInt(mHour); 355 dest.writeInt(mMinute); 356 dest.writeInt(mIs24HourMode ? 1 : 0); 357 dest.writeInt(mCurrentItemShowing); 358 } 359 360 @SuppressWarnings({"unused", "hiding"}) 361 public static final Creator<SavedState> CREATOR = new Creator<SavedState>() { 362 public SavedState createFromParcel(Parcel in) { 363 return new SavedState(in); 364 } 365 366 public SavedState[] newArray(int size) { 367 return new SavedState[size]; 368 } 369 }; 370 } 371 } 372 } 373