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 17package android.app; 18 19import android.content.Context; 20import android.content.DialogInterface; 21import android.content.DialogInterface.OnClickListener; 22import android.os.Bundle; 23import android.text.format.DateUtils; 24import android.util.TypedValue; 25import android.view.LayoutInflater; 26import android.view.View; 27import android.widget.Button; 28import android.widget.DatePicker; 29import android.widget.DatePicker.OnDateChangedListener; 30import android.widget.DatePicker.ValidationCallback; 31 32import com.android.internal.R; 33 34import java.util.Calendar; 35 36/** 37 * A simple dialog containing an {@link android.widget.DatePicker}. 38 * 39 * <p>See the <a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a> 40 * guide.</p> 41 */ 42public class DatePickerDialog extends AlertDialog implements OnClickListener, 43 OnDateChangedListener { 44 45 private static final String YEAR = "year"; 46 private static final String MONTH = "month"; 47 private static final String DAY = "day"; 48 49 private final DatePicker mDatePicker; 50 private final OnDateSetListener mDateSetListener; 51 private final Calendar mCalendar; 52 53 private boolean mTitleNeedsUpdate = true; 54 55 /** 56 * The callback used to indicate the user is done filling in the date. 57 */ 58 public interface OnDateSetListener { 59 60 /** 61 * @param view The view associated with this listener. 62 * @param year The year that was set. 63 * @param monthOfYear The month that was set (0-11) for compatibility 64 * with {@link java.util.Calendar}. 65 * @param dayOfMonth The day of the month that was set. 66 */ 67 void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth); 68 } 69 70 /** 71 * @param context The context the dialog is to run in. 72 * @param callBack How the parent is notified that the date is set. 73 * @param year The initial year of the dialog. 74 * @param monthOfYear The initial month of the dialog. 75 * @param dayOfMonth The initial day of the dialog. 76 */ 77 public DatePickerDialog(Context context, 78 OnDateSetListener callBack, 79 int year, 80 int monthOfYear, 81 int dayOfMonth) { 82 this(context, 0, callBack, year, monthOfYear, dayOfMonth); 83 } 84 85 static int resolveDialogTheme(Context context, int resid) { 86 if (resid == 0) { 87 final TypedValue outValue = new TypedValue(); 88 context.getTheme().resolveAttribute(R.attr.datePickerDialogTheme, outValue, true); 89 return outValue.resourceId; 90 } else { 91 return resid; 92 } 93 } 94 95 /** 96 * @param context The context the dialog is to run in. 97 * @param theme the theme to apply to this dialog 98 * @param listener How the parent is notified that the date is set. 99 * @param year The initial year of the dialog. 100 * @param monthOfYear The initial month of the dialog. 101 * @param dayOfMonth The initial day of the dialog. 102 */ 103 public DatePickerDialog(Context context, int theme, OnDateSetListener listener, int year, 104 int monthOfYear, int dayOfMonth) { 105 super(context, resolveDialogTheme(context, theme)); 106 107 mDateSetListener = listener; 108 mCalendar = Calendar.getInstance(); 109 110 final Context themeContext = getContext(); 111 final LayoutInflater inflater = LayoutInflater.from(themeContext); 112 final View view = inflater.inflate(R.layout.date_picker_dialog, null); 113 setView(view); 114 setButton(BUTTON_POSITIVE, themeContext.getString(R.string.ok), this); 115 setButton(BUTTON_NEGATIVE, themeContext.getString(R.string.cancel), this); 116 setButtonPanelLayoutHint(LAYOUT_HINT_SIDE); 117 118 mDatePicker = (DatePicker) view.findViewById(R.id.datePicker); 119 mDatePicker.init(year, monthOfYear, dayOfMonth, this); 120 mDatePicker.setValidationCallback(mValidationCallback); 121 } 122 123 @Override 124 public void onDateChanged(DatePicker view, int year, int month, int day) { 125 mDatePicker.init(year, month, day, this); 126 updateTitle(year, month, day); 127 } 128 129 @Override 130 public void onClick(DialogInterface dialog, int which) { 131 switch (which) { 132 case BUTTON_POSITIVE: 133 if (mDateSetListener != null) { 134 // Clearing focus forces the dialog to commit any pending 135 // changes, e.g. typed text in a NumberPicker. 136 mDatePicker.clearFocus(); 137 mDateSetListener.onDateSet(mDatePicker, mDatePicker.getYear(), 138 mDatePicker.getMonth(), mDatePicker.getDayOfMonth()); 139 } 140 break; 141 case BUTTON_NEGATIVE: 142 cancel(); 143 break; 144 } 145 } 146 147 /** 148 * Gets the {@link DatePicker} contained in this dialog. 149 * 150 * @return The calendar view. 151 */ 152 public DatePicker getDatePicker() { 153 return mDatePicker; 154 } 155 156 /** 157 * Sets the current date. 158 * 159 * @param year The date year. 160 * @param monthOfYear The date month. 161 * @param dayOfMonth The date day of month. 162 */ 163 public void updateDate(int year, int monthOfYear, int dayOfMonth) { 164 mDatePicker.updateDate(year, monthOfYear, dayOfMonth); 165 } 166 167 private void updateTitle(int year, int month, int day) { 168 if (!mDatePicker.getCalendarViewShown()) { 169 mCalendar.set(Calendar.YEAR, year); 170 mCalendar.set(Calendar.MONTH, month); 171 mCalendar.set(Calendar.DAY_OF_MONTH, day); 172 String title = DateUtils.formatDateTime(mContext, 173 mCalendar.getTimeInMillis(), 174 DateUtils.FORMAT_SHOW_DATE 175 | DateUtils.FORMAT_SHOW_WEEKDAY 176 | DateUtils.FORMAT_SHOW_YEAR 177 | DateUtils.FORMAT_ABBREV_MONTH 178 | DateUtils.FORMAT_ABBREV_WEEKDAY); 179 setTitle(title); 180 mTitleNeedsUpdate = true; 181 } else { 182 if (mTitleNeedsUpdate) { 183 mTitleNeedsUpdate = false; 184 setTitle(R.string.date_picker_dialog_title); 185 } 186 } 187 } 188 189 @Override 190 public Bundle onSaveInstanceState() { 191 final Bundle state = super.onSaveInstanceState(); 192 state.putInt(YEAR, mDatePicker.getYear()); 193 state.putInt(MONTH, mDatePicker.getMonth()); 194 state.putInt(DAY, mDatePicker.getDayOfMonth()); 195 return state; 196 } 197 198 @Override 199 public void onRestoreInstanceState(Bundle savedInstanceState) { 200 super.onRestoreInstanceState(savedInstanceState); 201 final int year = savedInstanceState.getInt(YEAR); 202 final int month = savedInstanceState.getInt(MONTH); 203 final int day = savedInstanceState.getInt(DAY); 204 mDatePicker.init(year, month, day, this); 205 } 206 207 private final ValidationCallback mValidationCallback = new ValidationCallback() { 208 @Override 209 public void onValidationChanged(boolean valid) { 210 final Button positive = getButton(BUTTON_POSITIVE); 211 if (positive != null) { 212 positive.setEnabled(valid); 213 } 214 } 215 }; 216} 217