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 com.android.contacts.datepicker; 18 19 // This is a fork of the standard Android DatePicker that additionally allows toggling the year 20 // on/off. It uses some private API so that not everything has to be copied. 21 22 import android.app.AlertDialog; 23 import android.content.Context; 24 import android.content.DialogInterface; 25 import android.content.DialogInterface.OnClickListener; 26 import android.os.Build; 27 import android.os.Bundle; 28 import android.text.TextUtils.TruncateAt; 29 import android.view.LayoutInflater; 30 import android.view.View; 31 import android.widget.TextView; 32 33 import com.android.contacts.R; 34 import com.android.contacts.common.util.DateUtils; 35 import com.android.contacts.datepicker.DatePicker.OnDateChangedListener; 36 37 import java.text.DateFormat; 38 import java.util.Calendar; 39 40 /** 41 * A simple dialog containing an {@link DatePicker}. 42 * 43 * <p>See the <a href="{@docRoot}resources/tutorials/views/hello-datepicker.html">Date Picker 44 * tutorial</a>.</p> 45 */ 46 public class DatePickerDialog extends AlertDialog implements OnClickListener, 47 OnDateChangedListener { 48 49 /** Magic year that represents "no year" */ 50 public static int NO_YEAR = DatePicker.NO_YEAR; 51 52 private static final String YEAR = "year"; 53 private static final String MONTH = "month"; 54 private static final String DAY = "day"; 55 private static final String YEAR_OPTIONAL = "year_optional"; 56 57 private final DatePicker mDatePicker; 58 private final OnDateSetListener mCallBack; 59 private final DateFormat mTitleDateFormat; 60 private final DateFormat mTitleNoYearDateFormat; 61 62 private int mInitialYear; 63 private int mInitialMonth; 64 private int mInitialDay; 65 66 /** 67 * The callback used to indicate the user is done filling in the date. 68 */ 69 public interface OnDateSetListener { 70 /** 71 * @param view The view associated with this listener. 72 * @param year The year that was set or {@link DatePickerDialog#NO_YEAR} if the user has 73 * not specified a year 74 * @param monthOfYear The month that was set (0-11) for compatibility 75 * with {@link java.util.Calendar}. 76 * @param dayOfMonth The day of the month that was set. 77 */ 78 void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth); 79 } 80 81 /** 82 * @param context The context the dialog is to run in. 83 * @param callBack How the parent is notified that the date is set. 84 * @param year The initial year of the dialog 85 * @param monthOfYear The initial month of the dialog. 86 * @param dayOfMonth The initial day of the dialog. 87 */ 88 public DatePickerDialog(Context context, 89 OnDateSetListener callBack, 90 int year, 91 int monthOfYear, 92 int dayOfMonth) { 93 this(context, callBack, year, monthOfYear, dayOfMonth, false); 94 } 95 96 /** 97 * @param context The context the dialog is to run in. 98 * @param callBack How the parent is notified that the date is set. 99 * @param year The initial year of the dialog or {@link DatePickerDialog#NO_YEAR} if no year 100 * has been specified 101 * @param monthOfYear The initial month of the dialog. 102 * @param dayOfMonth The initial day of the dialog. 103 * @param yearOptional Whether the year can be toggled by the user 104 */ 105 public DatePickerDialog(Context context, 106 OnDateSetListener callBack, 107 int year, 108 int monthOfYear, 109 int dayOfMonth, 110 boolean yearOptional) { 111 this(context, context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB 112 ? com.android.internal.R.style.Theme_Holo_Light_Dialog_Alert 113 : com.android.internal.R.style.Theme_Dialog_Alert, 114 callBack, year, monthOfYear, dayOfMonth, yearOptional); 115 } 116 117 /** 118 * @param context The context the dialog is to run in. 119 * @param theme the theme to apply to this dialog 120 * @param callBack How the parent is notified that the date is set. 121 * @param year The initial year of the dialog or {@link DatePickerDialog#NO_YEAR} if no year 122 * has been specified 123 * @param monthOfYear The initial month of the dialog. 124 * @param dayOfMonth The initial day of the dialog. 125 */ 126 public DatePickerDialog(Context context, 127 int theme, 128 OnDateSetListener callBack, 129 int year, 130 int monthOfYear, 131 int dayOfMonth) { 132 this(context, theme, callBack, year, monthOfYear, dayOfMonth, false); 133 } 134 135 /** 136 * @param context The context the dialog is to run in. 137 * @param theme the theme to apply to this dialog 138 * @param callBack How the parent is notified that the date is set. 139 * @param year The initial year of the dialog or {@link DatePickerDialog#NO_YEAR} if no 140 * year has been specified. 141 * @param monthOfYear The initial month of the dialog. 142 * @param dayOfMonth The initial day of the dialog. 143 * @param yearOptional Whether the year can be toggled by the user 144 */ 145 public DatePickerDialog(Context context, 146 int theme, 147 OnDateSetListener callBack, 148 int year, 149 int monthOfYear, 150 int dayOfMonth, 151 boolean yearOptional) { 152 super(context, theme); 153 154 mCallBack = callBack; 155 mInitialYear = year; 156 mInitialMonth = monthOfYear; 157 mInitialDay = dayOfMonth; 158 159 mTitleDateFormat = DateFormat.getDateInstance(DateFormat.FULL); 160 mTitleNoYearDateFormat = DateUtils.getLocalizedDateFormatWithoutYear(getContext()); 161 updateTitle(mInitialYear, mInitialMonth, mInitialDay); 162 163 setButton(BUTTON_POSITIVE, context.getText(com.android.internal.R.string.date_time_set), 164 this); 165 setButton(BUTTON_NEGATIVE, context.getText(android.R.string.cancel), 166 (OnClickListener) null); 167 168 LayoutInflater inflater = 169 (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 170 View view = inflater.inflate(R.layout.date_picker_dialog, null); 171 setView(view); 172 mDatePicker = (DatePicker) view.findViewById(R.id.datePicker); 173 mDatePicker.init(mInitialYear, mInitialMonth, mInitialDay, yearOptional, this); 174 } 175 176 @Override 177 public void show() { 178 super.show(); 179 180 /* Sometimes the full month is displayed causing the title 181 * to be very long, in those cases ensure it doesn't wrap to 182 * 2 lines (as that looks jumpy) and ensure we ellipsize the end. 183 */ 184 TextView title = (TextView) findViewById(com.android.internal.R.id.alertTitle); 185 title.setSingleLine(); 186 title.setEllipsize(TruncateAt.END); 187 } 188 189 @Override 190 public void onClick(DialogInterface dialog, int which) { 191 if (mCallBack != null) { 192 mDatePicker.clearFocus(); 193 mCallBack.onDateSet(mDatePicker, mDatePicker.getYear(), 194 mDatePicker.getMonth(), mDatePicker.getDayOfMonth()); 195 } 196 } 197 198 @Override 199 public void onDateChanged(DatePicker view, int year, int month, int day) { 200 updateTitle(year, month, day); 201 } 202 203 public void updateDate(int year, int monthOfYear, int dayOfMonth) { 204 mInitialYear = year; 205 mInitialMonth = monthOfYear; 206 mInitialDay = dayOfMonth; 207 mDatePicker.updateDate(year, monthOfYear, dayOfMonth); 208 } 209 210 private void updateTitle(int year, int month, int day) { 211 final Calendar calendar = Calendar.getInstance(); 212 calendar.set(Calendar.YEAR, year); 213 calendar.set(Calendar.MONTH, month); 214 calendar.set(Calendar.DAY_OF_MONTH, day); 215 final DateFormat dateFormat = 216 year == NO_YEAR ? mTitleNoYearDateFormat : mTitleDateFormat; 217 setTitle(dateFormat.format(calendar.getTime())); 218 } 219 220 @Override 221 public Bundle onSaveInstanceState() { 222 Bundle state = super.onSaveInstanceState(); 223 state.putInt(YEAR, mDatePicker.getYear()); 224 state.putInt(MONTH, mDatePicker.getMonth()); 225 state.putInt(DAY, mDatePicker.getDayOfMonth()); 226 state.putBoolean(YEAR_OPTIONAL, mDatePicker.isYearOptional()); 227 return state; 228 } 229 230 @Override 231 public void onRestoreInstanceState(Bundle savedInstanceState) { 232 super.onRestoreInstanceState(savedInstanceState); 233 int year = savedInstanceState.getInt(YEAR); 234 int month = savedInstanceState.getInt(MONTH); 235 int day = savedInstanceState.getInt(DAY); 236 boolean yearOptional = savedInstanceState.getBoolean(YEAR_OPTIONAL); 237 mDatePicker.init(year, month, day, yearOptional, this); 238 updateTitle(year, month, day); 239 } 240 } 241