Home | History | Annotate | Download | only in widget
      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          */
     63         void onTimeChanged(TimePicker view, int hourOfDay, int minute);
     64     }
     65 
     66     public TimePicker(Context context) {
     67         this(context, null);
     68     }
     69 
     70     public TimePicker(Context context, AttributeSet attrs) {
     71         this(context, attrs, R.attr.timePickerStyle);
     72     }
     73 
     74     public TimePicker(Context context, AttributeSet attrs, int defStyleAttr) {
     75         this(context, attrs, defStyleAttr, 0);
     76     }
     77 
     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      */
    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      */
    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      */
    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      */
    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
    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
    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
    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
    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      */
    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      */
    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      */
    209     public void setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener) {
    210         mDelegate.setOnTimeChangedListener(onTimeChangedListener);
    211     }
    212 
    213     @Override
    214     public void setEnabled(boolean enabled) {
    215         super.setEnabled(enabled);
    216         mDelegate.setEnabled(enabled);
    217     }
    218 
    219     @Override
    220     public boolean isEnabled() {
    221         return mDelegate.isEnabled();
    222     }
    223 
    224     @Override
    225     public int getBaseline() {
    226         return mDelegate.getBaseline();
    227     }
    228 
    229     @Override
    230     protected Parcelable onSaveInstanceState() {
    231         Parcelable superState = super.onSaveInstanceState();
    232         return mDelegate.onSaveInstanceState(superState);
    233     }
    234 
    235     @Override
    236     protected void onRestoreInstanceState(Parcelable state) {
    237         BaseSavedState ss = (BaseSavedState) state;
    238         super.onRestoreInstanceState(ss.getSuperState());
    239         mDelegate.onRestoreInstanceState(ss);
    240     }
    241 
    242     @Override
    243     public CharSequence getAccessibilityClassName() {
    244         return TimePicker.class.getName();
    245     }
    246 
    247     /** @hide */
    248     @Override
    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 {
    259         void setHour(int hour);
    260         int getHour();
    261 
    262         void setMinute(int minute);
    263         int getMinute();
    264 
    265         void setIs24Hour(boolean is24Hour);
    266         boolean is24Hour();
    267 
    268         void setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener);
    269 
    270         void setEnabled(boolean enabled);
    271         boolean isEnabled();
    272 
    273         int getBaseline();
    274 
    275         Parcelable onSaveInstanceState(Parcelable superState);
    276         void onRestoreInstanceState(Parcelable state);
    277 
    278         boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event);
    279         void onPopulateAccessibilityEvent(AccessibilityEvent event);
    280     }
    281 
    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 
    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 
    314             public SavedState(Parcelable superState, int hour, int minute, boolean is24HourMode) {
    315                 this(superState, hour, minute, is24HourMode, 0);
    316             }
    317 
    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 
    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 
    335             public int getHour() {
    336                 return mHour;
    337             }
    338 
    339             public int getMinute() {
    340                 return mMinute;
    341             }
    342 
    343             public boolean is24HourMode() {
    344                 return mIs24HourMode;
    345             }
    346 
    347             public int getCurrentItemShowing() {
    348                 return mCurrentItemShowing;
    349             }
    350 
    351             @Override
    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