├── .gitignore ├── README.md ├── library ├── AndroidManifest.xml ├── build.xml ├── pom.xml ├── res │ ├── layout-sw600dp │ │ └── date_picker_dialog.xml │ ├── layout │ │ ├── activity_samples.xml │ │ ├── date_picker_dialog.xml │ │ └── date_picker_holo.xml │ └── values │ │ ├── attrs.xml │ │ ├── strings.xml │ │ ├── styles.xml │ │ └── themes.xml └── src │ └── net │ └── simonvt │ └── datepicker │ ├── CVArrays.java │ ├── DatePicker.java │ └── DatePickerDialog.java ├── pom.xml └── samples ├── AndroidManifest.xml ├── build.xml ├── pom.xml ├── res ├── drawable-hdpi │ └── ic_launcher.png ├── drawable-ldpi │ └── ic_launcher.png ├── drawable-mdpi │ └── ic_launcher.png ├── layout │ ├── activity_dialog.xml │ ├── activity_layout.xml │ └── activity_samples.xml ├── values-v14 │ └── themes.xml └── values │ ├── strings.xml │ └── themes.xml └── src └── net └── simonvt └── datepicker └── samples ├── DatePickerSamples.java ├── DialogSample.java └── LayoutSample.java /.gitignore: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | !.gitignore 4 | !README.md 5 | !pom.xml 6 | 7 | !library/ 8 | library/* 9 | !library/src/ 10 | !library/res/ 11 | !library/libs/ 12 | !library/AndroidManifest.xml 13 | !library/build.xml 14 | !library/pom.xml 15 | 16 | !samples/ 17 | samples/* 18 | !samples/src/ 19 | !samples/res/ 20 | !samples/AndroidManifest.xml 21 | !samples/build.xml 22 | !samples/pom.xml 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **This library is provided as-is and is not under active development** 2 | 3 | Android 4.0 DatePicker backported to 2.2 4 | 5 | Dependencies: 6 | CalendarView: https://github.com/SimonVT/android-calendarview 7 | NumberPicker: https://github.com/SimonVT/android-numberpicker 8 | -------------------------------------------------------------------------------- /library/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /library/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 29 | 30 | 31 | 40 | 41 | 42 | 43 | 47 | 48 | 60 | 61 | 62 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /library/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | 7 | net.simonvt 8 | android-datepicker-parent 9 | 1.0.1-SNAPSHOT 10 | ../pom.xml 11 | 12 | 13 | android-datepicker 14 | Android DatePicker 15 | apklib 16 | 17 | 18 | 19 | com.google.android 20 | android 21 | provided 22 | 23 | 24 | net.simonvt 25 | android-numberpicker 26 | 1.0.0 27 | apklib 28 | 29 | 30 | net.simonvt 31 | android-calendarview 32 | 1.0.0 33 | apklib 34 | 35 | 36 | 37 | 38 | src 39 | 40 | 41 | 42 | com.jayway.maven.plugins.android.generation2 43 | android-maven-plugin 44 | true 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /library/res/layout-sw600dp/date_picker_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 29 | -------------------------------------------------------------------------------- /library/res/layout/activity_samples.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /library/res/layout/date_picker_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 29 | -------------------------------------------------------------------------------- /library/res/layout/date_picker_holo.xml: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 21 | 22 | 25 | 31 | 32 | 38 | 39 | 40 | 49 | 50 | 51 | 60 | 61 | 62 | 71 | 72 | 73 | 74 | 75 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /library/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /library/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Cancel 6 | 7 | 8 | Set date 9 | 10 | Set 11 | 12 | Done 13 | 14 | 15 | 16 | Increment month 17 | 18 | Decrement month 19 | 20 | Increment day 21 | 22 | Decrement day 23 | 24 | Increment year 25 | 26 | Decrement year 27 | 28 | -------------------------------------------------------------------------------- /library/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 13 | 14 | 18 | 19 | 23 | 24 | 26 | 27 | -------------------------------------------------------------------------------- /library/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /library/src/net/simonvt/datepicker/CVArrays.java: -------------------------------------------------------------------------------- 1 | package net.simonvt.datepicker; 2 | 3 | import java.lang.reflect.Array; 4 | 5 | class CVArrays { 6 | 7 | /** 8 | * Copies elements from {@code original} into a new array, from indexes start (inclusive) to 9 | * end (exclusive). The original order of elements is preserved. 10 | * If {@code end} is greater than {@code original.length}, the result is padded 11 | * with the value {@code null}. 12 | * 13 | * @param original the original array 14 | * @param start the start index, inclusive 15 | * @param end the end index, exclusive 16 | * @return the new array 17 | * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length} 18 | * @throws IllegalArgumentException if {@code start > end} 19 | * @throws NullPointerException if {@code original == null} 20 | * @since 1.6 21 | */ 22 | @SuppressWarnings("unchecked") 23 | public static T[] copyOfRange(T[] original, int start, int end) { 24 | int originalLength = original.length; // For exception priority compatibility. 25 | if (start > end) { 26 | throw new IllegalArgumentException(); 27 | } 28 | if (start < 0 || start > originalLength) { 29 | throw new ArrayIndexOutOfBoundsException(); 30 | } 31 | int resultLength = end - start; 32 | int copyLength = Math.min(resultLength, originalLength - start); 33 | T[] result = (T[]) Array.newInstance(original.getClass().getComponentType(), resultLength); 34 | System.arraycopy(original, start, result, 0, copyLength); 35 | return result; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /library/src/net/simonvt/datepicker/DatePicker.java: -------------------------------------------------------------------------------- 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 net.simonvt.datepicker; 18 | 19 | import net.simonvt.calendarview.CalendarView; 20 | import net.simonvt.numberpicker.NumberPicker; 21 | 22 | import android.content.Context; 23 | import android.content.res.Configuration; 24 | import android.content.res.TypedArray; 25 | import android.os.Build; 26 | import android.os.Parcel; 27 | import android.os.Parcelable; 28 | import android.text.TextUtils; 29 | import android.text.format.DateFormat; 30 | import android.text.format.DateUtils; 31 | import android.util.AttributeSet; 32 | import android.util.Log; 33 | import android.util.SparseArray; 34 | import android.view.LayoutInflater; 35 | import android.view.View; 36 | import android.view.accessibility.AccessibilityEvent; 37 | import android.view.accessibility.AccessibilityNodeInfo; 38 | import android.view.inputmethod.EditorInfo; 39 | import android.view.inputmethod.InputMethodManager; 40 | import android.widget.EditText; 41 | import android.widget.FrameLayout; 42 | import android.widget.LinearLayout; 43 | import android.widget.TextView; 44 | 45 | import java.text.ParseException; 46 | import java.text.SimpleDateFormat; 47 | import java.util.Arrays; 48 | import java.util.Calendar; 49 | import java.util.Locale; 50 | import java.util.TimeZone; 51 | 52 | /** 53 | * This class is a widget for selecting a date. The date can be selected by a 54 | * year, month, and day spinners or a {@link CalendarView}. The set of spinners 55 | * and the calendar view are automatically synchronized. The client can 56 | * customize whether only the spinners, or only the calendar view, or both to be 57 | * displayed. Also the minimal and maximal date from which dates to be selected 58 | * can be customized. 59 | *

60 | * See the Pickers 61 | * guide. 62 | *

63 | *

64 | * For a dialog using this view, see {@link android.app.DatePickerDialog}. 65 | *

66 | * 67 | * @attr ref android.R.styleable#DatePicker_startYear 68 | * @attr ref android.R.styleable#DatePicker_endYear 69 | * @attr ref android.R.styleable#DatePicker_maxDate 70 | * @attr ref android.R.styleable#DatePicker_minDate 71 | * @attr ref android.R.styleable#DatePicker_spinnersShown 72 | * @attr ref android.R.styleable#DatePicker_calendarViewShown 73 | */ 74 | //@Widget 75 | public class DatePicker extends FrameLayout { 76 | 77 | private static final String LOG_TAG = DatePicker.class.getSimpleName(); 78 | 79 | private static final String DATE_FORMAT = "MM/dd/yyyy"; 80 | 81 | private static final int DEFAULT_START_YEAR = 1900; 82 | 83 | private static final int DEFAULT_END_YEAR = 2100; 84 | 85 | private static final boolean DEFAULT_CALENDAR_VIEW_SHOWN = true; 86 | 87 | private static final boolean DEFAULT_SPINNERS_SHOWN = true; 88 | 89 | private static final boolean DEFAULT_ENABLED_STATE = true; 90 | 91 | private final LinearLayout mSpinners; 92 | 93 | private final NumberPicker mDaySpinner; 94 | 95 | private final NumberPicker mMonthSpinner; 96 | 97 | private final NumberPicker mYearSpinner; 98 | 99 | private final EditText mDaySpinnerInput; 100 | 101 | private final EditText mMonthSpinnerInput; 102 | 103 | private final EditText mYearSpinnerInput; 104 | 105 | private final CalendarView mCalendarView; 106 | 107 | private Locale mCurrentLocale; 108 | 109 | private OnDateChangedListener mOnDateChangedListener; 110 | 111 | private String[] mShortMonths; 112 | 113 | private final java.text.DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT); 114 | 115 | private int mNumberOfMonths; 116 | 117 | private Calendar mTempDate; 118 | 119 | private Calendar mMinDate; 120 | 121 | private Calendar mMaxDate; 122 | 123 | private Calendar mCurrentDate; 124 | 125 | private boolean mIsEnabled = DEFAULT_ENABLED_STATE; 126 | 127 | /** 128 | * The callback used to indicate the user changes\d the date. 129 | */ 130 | public interface OnDateChangedListener { 131 | 132 | /** 133 | * Called upon a date change. 134 | * 135 | * @param view The view associated with this listener. 136 | * @param year The year that was set. 137 | * @param monthOfYear The month that was set (0-11) for compatibility 138 | * with {@link java.util.Calendar}. 139 | * @param dayOfMonth The day of the month that was set. 140 | */ 141 | void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth); 142 | } 143 | 144 | public DatePicker(Context context) { 145 | this(context, null); 146 | } 147 | 148 | public DatePicker(Context context, AttributeSet attrs) { 149 | this(context, attrs, R.attr.datePickerStyle); 150 | } 151 | 152 | public DatePicker(Context context, AttributeSet attrs, int defStyle) { 153 | super(context, attrs, defStyle); 154 | 155 | // initialization based on locale 156 | setCurrentLocale(Locale.getDefault()); 157 | 158 | TypedArray attributesArray = context.obtainStyledAttributes(attrs, R.styleable.DatePicker, 159 | defStyle, 0); 160 | boolean spinnersShown = attributesArray.getBoolean(R.styleable.DatePicker_dp_spinnersShown, 161 | DEFAULT_SPINNERS_SHOWN); 162 | boolean calendarViewShown = attributesArray.getBoolean( 163 | R.styleable.DatePicker_dp_calendarViewShown, DEFAULT_CALENDAR_VIEW_SHOWN); 164 | int startYear = attributesArray.getInt(R.styleable.DatePicker_dp_startYear, 165 | DEFAULT_START_YEAR); 166 | int endYear = attributesArray.getInt(R.styleable.DatePicker_dp_endYear, DEFAULT_END_YEAR); 167 | String minDate = attributesArray.getString(R.styleable.DatePicker_dp_minDate); 168 | String maxDate = attributesArray.getString(R.styleable.DatePicker_dp_maxDate); 169 | int layoutResourceId = attributesArray.getResourceId(R.styleable.DatePicker_dp_internalLayout, 170 | R.layout.date_picker_holo); 171 | attributesArray.recycle(); 172 | 173 | LayoutInflater inflater = (LayoutInflater) context 174 | .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 175 | inflater.inflate(layoutResourceId, this, true); 176 | 177 | NumberPicker.OnValueChangeListener onChangeListener = new NumberPicker.OnValueChangeListener() { 178 | public void onValueChange(NumberPicker picker, int oldVal, int newVal) { 179 | updateInputState(); 180 | mTempDate.setTimeInMillis(mCurrentDate.getTimeInMillis()); 181 | // take care of wrapping of days and months to update greater fields 182 | if (picker == mDaySpinner) { 183 | int maxDayOfMonth = mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH); 184 | if (oldVal == maxDayOfMonth && newVal == 1) { 185 | mTempDate.add(Calendar.DAY_OF_MONTH, 1); 186 | } else if (oldVal == 1 && newVal == maxDayOfMonth) { 187 | mTempDate.add(Calendar.DAY_OF_MONTH, -1); 188 | } else { 189 | mTempDate.add(Calendar.DAY_OF_MONTH, newVal - oldVal); 190 | } 191 | } else if (picker == mMonthSpinner) { 192 | if (oldVal == 11 && newVal == 0) { 193 | mTempDate.add(Calendar.MONTH, 1); 194 | } else if (oldVal == 0 && newVal == 11) { 195 | mTempDate.add(Calendar.MONTH, -1); 196 | } else { 197 | mTempDate.add(Calendar.MONTH, newVal - oldVal); 198 | } 199 | } else if (picker == mYearSpinner) { 200 | mTempDate.set(Calendar.YEAR, newVal); 201 | } else { 202 | throw new IllegalArgumentException(); 203 | } 204 | // now set the date to the adjusted one 205 | setDate(mTempDate.get(Calendar.YEAR), mTempDate.get(Calendar.MONTH), 206 | mTempDate.get(Calendar.DAY_OF_MONTH)); 207 | updateSpinners(); 208 | updateCalendarView(); 209 | notifyDateChanged(); 210 | } 211 | }; 212 | 213 | mSpinners = (LinearLayout) findViewById(R.id.pickers); 214 | 215 | // calendar view day-picker 216 | mCalendarView = (CalendarView) findViewById(R.id.calendar_view); 217 | mCalendarView.setOnDateChangeListener(new CalendarView.OnDateChangeListener() { 218 | public void onSelectedDayChange(CalendarView view, int year, int month, int monthDay) { 219 | setDate(year, month, monthDay); 220 | updateSpinners(); 221 | notifyDateChanged(); 222 | } 223 | }); 224 | 225 | // day 226 | mDaySpinner = (NumberPicker) findViewById(R.id.day); 227 | mDaySpinner.setFormatter(NumberPicker.getTwoDigitFormatter()); 228 | mDaySpinner.setOnLongPressUpdateInterval(100); 229 | mDaySpinner.setOnValueChangedListener(onChangeListener); 230 | mDaySpinnerInput = (EditText) mDaySpinner.findViewById(R.id.np__numberpicker_input); 231 | 232 | // month 233 | mMonthSpinner = (NumberPicker) findViewById(R.id.month); 234 | mMonthSpinner.setMinValue(0); 235 | mMonthSpinner.setMaxValue(mNumberOfMonths - 1); 236 | mMonthSpinner.setDisplayedValues(mShortMonths); 237 | mMonthSpinner.setOnLongPressUpdateInterval(200); 238 | mMonthSpinner.setOnValueChangedListener(onChangeListener); 239 | mMonthSpinnerInput = (EditText) mMonthSpinner.findViewById(R.id.np__numberpicker_input); 240 | 241 | // year 242 | mYearSpinner = (NumberPicker) findViewById(R.id.year); 243 | mYearSpinner.setOnLongPressUpdateInterval(100); 244 | mYearSpinner.setOnValueChangedListener(onChangeListener); 245 | mYearSpinnerInput = (EditText) mYearSpinner.findViewById(R.id.np__numberpicker_input); 246 | 247 | // show only what the user required but make sure we 248 | // show something and the spinners have higher priority 249 | if (!spinnersShown && !calendarViewShown) { 250 | setSpinnersShown(true); 251 | } else { 252 | setSpinnersShown(spinnersShown); 253 | setCalendarViewShown(calendarViewShown); 254 | } 255 | 256 | // set the min date giving priority of the minDate over startYear 257 | mTempDate.clear(); 258 | if (!TextUtils.isEmpty(minDate)) { 259 | if (!parseDate(minDate, mTempDate)) { 260 | mTempDate.set(startYear, 0, 1); 261 | } 262 | } else { 263 | mTempDate.set(startYear, 0, 1); 264 | } 265 | setMinDate(mTempDate.getTimeInMillis()); 266 | 267 | // set the max date giving priority of the maxDate over endYear 268 | mTempDate.clear(); 269 | if (!TextUtils.isEmpty(maxDate)) { 270 | if (!parseDate(maxDate, mTempDate)) { 271 | mTempDate.set(endYear, 11, 31); 272 | } 273 | } else { 274 | mTempDate.set(endYear, 11, 31); 275 | } 276 | setMaxDate(mTempDate.getTimeInMillis()); 277 | 278 | // initialize to current date 279 | mCurrentDate.setTimeInMillis(System.currentTimeMillis()); 280 | init(mCurrentDate.get(Calendar.YEAR), mCurrentDate.get(Calendar.MONTH), mCurrentDate 281 | .get(Calendar.DAY_OF_MONTH), null); 282 | 283 | // re-order the number spinners to match the current date format 284 | reorderSpinners(); 285 | 286 | // accessibility 287 | setContentDescriptions(); 288 | 289 | // If not explicitly specified this view is important for accessibility. 290 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { 291 | setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); 292 | } 293 | } 294 | 295 | /** 296 | * Gets the minimal date supported by this {@link DatePicker} in 297 | * milliseconds since January 1, 1970 00:00:00 in 298 | * {@link TimeZone#getDefault()} time zone. 299 | *

300 | * Note: The default minimal date is 01/01/1900. 301 | *

302 | * 303 | * @return The minimal supported date. 304 | */ 305 | public long getMinDate() { 306 | return mCalendarView.getMinDate(); 307 | } 308 | 309 | /** 310 | * Sets the minimal date supported by this {@link NumberPicker} in 311 | * milliseconds since January 1, 1970 00:00:00 in 312 | * {@link TimeZone#getDefault()} time zone. 313 | * 314 | * @param minDate The minimal supported date. 315 | */ 316 | public void setMinDate(long minDate) { 317 | mTempDate.setTimeInMillis(minDate); 318 | if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR) 319 | && mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) { 320 | return; 321 | } 322 | mMinDate.setTimeInMillis(minDate); 323 | mCalendarView.setMinDate(minDate); 324 | if (mCurrentDate.before(mMinDate)) { 325 | mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis()); 326 | updateCalendarView(); 327 | } 328 | updateSpinners(); 329 | } 330 | 331 | /** 332 | * Gets the maximal date supported by this {@link DatePicker} in 333 | * milliseconds since January 1, 1970 00:00:00 in 334 | * {@link TimeZone#getDefault()} time zone. 335 | *

336 | * Note: The default maximal date is 12/31/2100. 337 | *

338 | * 339 | * @return The maximal supported date. 340 | */ 341 | public long getMaxDate() { 342 | return mCalendarView.getMaxDate(); 343 | } 344 | 345 | /** 346 | * Sets the maximal date supported by this {@link DatePicker} in 347 | * milliseconds since January 1, 1970 00:00:00 in 348 | * {@link TimeZone#getDefault()} time zone. 349 | * 350 | * @param maxDate The maximal supported date. 351 | */ 352 | public void setMaxDate(long maxDate) { 353 | mTempDate.setTimeInMillis(maxDate); 354 | if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR) 355 | && mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) { 356 | return; 357 | } 358 | mMaxDate.setTimeInMillis(maxDate); 359 | mCalendarView.setMaxDate(maxDate); 360 | if (mCurrentDate.after(mMaxDate)) { 361 | mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis()); 362 | updateCalendarView(); 363 | } 364 | updateSpinners(); 365 | } 366 | 367 | @Override 368 | public void setEnabled(boolean enabled) { 369 | if (mIsEnabled == enabled) { 370 | return; 371 | } 372 | super.setEnabled(enabled); 373 | mDaySpinner.setEnabled(enabled); 374 | mMonthSpinner.setEnabled(enabled); 375 | mYearSpinner.setEnabled(enabled); 376 | mCalendarView.setEnabled(enabled); 377 | mIsEnabled = enabled; 378 | } 379 | 380 | @Override 381 | public boolean isEnabled() { 382 | return mIsEnabled; 383 | } 384 | 385 | @Override 386 | public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 387 | onPopulateAccessibilityEvent(event); 388 | return true; 389 | } 390 | 391 | @Override 392 | public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 393 | super.onPopulateAccessibilityEvent(event); 394 | 395 | final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR; 396 | String selectedDateUtterance = DateUtils.formatDateTime(getContext(), 397 | mCurrentDate.getTimeInMillis(), flags); 398 | event.getText().add(selectedDateUtterance); 399 | } 400 | 401 | @Override 402 | public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 403 | super.onInitializeAccessibilityEvent(event); 404 | event.setClassName(DatePicker.class.getName()); 405 | } 406 | 407 | @Override 408 | public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 409 | super.onInitializeAccessibilityNodeInfo(info); 410 | info.setClassName(DatePicker.class.getName()); 411 | } 412 | 413 | @Override 414 | protected void onConfigurationChanged(Configuration newConfig) { 415 | super.onConfigurationChanged(newConfig); 416 | setCurrentLocale(newConfig.locale); 417 | } 418 | 419 | /** 420 | * Gets whether the {@link CalendarView} is shown. 421 | * 422 | * @return True if the calendar view is shown. 423 | * @see #getCalendarView() 424 | */ 425 | public boolean getCalendarViewShown() { 426 | return mCalendarView.isShown(); 427 | } 428 | 429 | /** 430 | * Gets the {@link CalendarView}. 431 | * 432 | * @return The calendar view. 433 | * @see #getCalendarViewShown() 434 | */ 435 | public CalendarView getCalendarView () { 436 | return mCalendarView; 437 | } 438 | 439 | /** 440 | * Sets whether the {@link CalendarView} is shown. 441 | * 442 | * @param shown True if the calendar view is to be shown. 443 | */ 444 | public void setCalendarViewShown(boolean shown) { 445 | mCalendarView.setVisibility(shown ? VISIBLE : GONE); 446 | } 447 | 448 | /** 449 | * Gets whether the spinners are shown. 450 | * 451 | * @return True if the spinners are shown. 452 | */ 453 | public boolean getSpinnersShown() { 454 | return mSpinners.isShown(); 455 | } 456 | 457 | /** 458 | * Sets whether the spinners are shown. 459 | * 460 | * @param shown True if the spinners are to be shown. 461 | */ 462 | public void setSpinnersShown(boolean shown) { 463 | mSpinners.setVisibility(shown ? VISIBLE : GONE); 464 | } 465 | 466 | /** 467 | * Sets the current locale. 468 | * 469 | * @param locale The current locale. 470 | */ 471 | private void setCurrentLocale(Locale locale) { 472 | if (locale.equals(mCurrentLocale)) { 473 | return; 474 | } 475 | 476 | mCurrentLocale = locale; 477 | 478 | mTempDate = getCalendarForLocale(mTempDate, locale); 479 | mMinDate = getCalendarForLocale(mMinDate, locale); 480 | mMaxDate = getCalendarForLocale(mMaxDate, locale); 481 | mCurrentDate = getCalendarForLocale(mCurrentDate, locale); 482 | 483 | mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1; 484 | mShortMonths = new String[mNumberOfMonths]; 485 | for (int i = 0; i < mNumberOfMonths; i++) { 486 | mShortMonths[i] = DateUtils.getMonthString(Calendar.JANUARY + i, 487 | DateUtils.LENGTH_MEDIUM); 488 | } 489 | } 490 | 491 | /** 492 | * Gets a calendar for locale bootstrapped with the value of a given calendar. 493 | * 494 | * @param oldCalendar The old calendar. 495 | * @param locale The locale. 496 | */ 497 | private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) { 498 | if (oldCalendar == null) { 499 | return Calendar.getInstance(locale); 500 | } else { 501 | final long currentTimeMillis = oldCalendar.getTimeInMillis(); 502 | Calendar newCalendar = Calendar.getInstance(locale); 503 | newCalendar.setTimeInMillis(currentTimeMillis); 504 | return newCalendar; 505 | } 506 | } 507 | 508 | /** 509 | * Reorders the spinners according to the date format that is 510 | * explicitly set by the user and if no such is set fall back 511 | * to the current locale's default format. 512 | */ 513 | private void reorderSpinners() { 514 | mSpinners.removeAllViews(); 515 | char[] order = DateFormat.getDateFormatOrder(getContext()); 516 | final int spinnerCount = order.length; 517 | for (int i = 0; i < spinnerCount; i++) { 518 | switch (order[i]) { 519 | case DateFormat.DATE: 520 | mSpinners.addView(mDaySpinner); 521 | setImeOptions(mDaySpinner, spinnerCount, i); 522 | break; 523 | case DateFormat.MONTH: 524 | mSpinners.addView(mMonthSpinner); 525 | setImeOptions(mMonthSpinner, spinnerCount, i); 526 | break; 527 | case DateFormat.YEAR: 528 | mSpinners.addView(mYearSpinner); 529 | setImeOptions(mYearSpinner, spinnerCount, i); 530 | break; 531 | default: 532 | throw new IllegalArgumentException(); 533 | } 534 | } 535 | } 536 | 537 | /** 538 | * Updates the current date. 539 | * 540 | * @param year The year. 541 | * @param month The month which is starting from zero. 542 | * @param dayOfMonth The day of the month. 543 | */ 544 | public void updateDate(int year, int month, int dayOfMonth) { 545 | if (!isNewDate(year, month, dayOfMonth)) { 546 | return; 547 | } 548 | setDate(year, month, dayOfMonth); 549 | updateSpinners(); 550 | updateCalendarView(); 551 | notifyDateChanged(); 552 | } 553 | 554 | // Override so we are in complete control of save / restore for this widget. 555 | @Override 556 | protected void dispatchRestoreInstanceState(SparseArray container) { 557 | dispatchThawSelfOnly(container); 558 | } 559 | 560 | @Override 561 | protected Parcelable onSaveInstanceState() { 562 | Parcelable superState = super.onSaveInstanceState(); 563 | return new SavedState(superState, getYear(), getMonth(), getDayOfMonth()); 564 | } 565 | 566 | @Override 567 | protected void onRestoreInstanceState(Parcelable state) { 568 | SavedState ss = (SavedState) state; 569 | super.onRestoreInstanceState(ss.getSuperState()); 570 | setDate(ss.mYear, ss.mMonth, ss.mDay); 571 | updateSpinners(); 572 | updateCalendarView(); 573 | } 574 | 575 | /** 576 | * Initialize the state. If the provided values designate an inconsistent 577 | * date the values are normalized before updating the spinners. 578 | * 579 | * @param year The initial year. 580 | * @param monthOfYear The initial month starting from zero. 581 | * @param dayOfMonth The initial day of the month. 582 | * @param onDateChangedListener How user is notified date is changed by 583 | * user, can be null. 584 | */ 585 | public void init(int year, int monthOfYear, int dayOfMonth, 586 | OnDateChangedListener onDateChangedListener) { 587 | setDate(year, monthOfYear, dayOfMonth); 588 | updateSpinners(); 589 | updateCalendarView(); 590 | mOnDateChangedListener = onDateChangedListener; 591 | } 592 | 593 | /** 594 | * Parses the given date and in case of success sets the result 595 | * to the outDate. 596 | * 597 | * @return True if the date was parsed. 598 | */ 599 | private boolean parseDate(String date, Calendar outDate) { 600 | try { 601 | outDate.setTime(mDateFormat.parse(date)); 602 | return true; 603 | } catch (ParseException e) { 604 | Log.w(LOG_TAG, "Date: " + date + " not in format: " + DATE_FORMAT); 605 | return false; 606 | } 607 | } 608 | 609 | private boolean isNewDate(int year, int month, int dayOfMonth) { 610 | return (mCurrentDate.get(Calendar.YEAR) != year 611 | || mCurrentDate.get(Calendar.MONTH) != dayOfMonth 612 | || mCurrentDate.get(Calendar.DAY_OF_MONTH) != month); 613 | } 614 | 615 | private void setDate(int year, int month, int dayOfMonth) { 616 | mCurrentDate.set(year, month, dayOfMonth); 617 | if (mCurrentDate.before(mMinDate)) { 618 | mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis()); 619 | } else if (mCurrentDate.after(mMaxDate)) { 620 | mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis()); 621 | } 622 | } 623 | 624 | private void updateSpinners() { 625 | // set the spinner ranges respecting the min and max dates 626 | if (mCurrentDate.equals(mMinDate)) { 627 | mDaySpinner.setMinValue(mCurrentDate.get(Calendar.DAY_OF_MONTH)); 628 | mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH)); 629 | mDaySpinner.setWrapSelectorWheel(false); 630 | mMonthSpinner.setDisplayedValues(null); 631 | mMonthSpinner.setMinValue(mCurrentDate.get(Calendar.MONTH)); 632 | mMonthSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.MONTH)); 633 | mMonthSpinner.setWrapSelectorWheel(false); 634 | } else if (mCurrentDate.equals(mMaxDate)) { 635 | mDaySpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH)); 636 | mDaySpinner.setMaxValue(mCurrentDate.get(Calendar.DAY_OF_MONTH)); 637 | mDaySpinner.setWrapSelectorWheel(false); 638 | mMonthSpinner.setDisplayedValues(null); 639 | mMonthSpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.MONTH)); 640 | mMonthSpinner.setMaxValue(mCurrentDate.get(Calendar.MONTH)); 641 | mMonthSpinner.setWrapSelectorWheel(false); 642 | } else { 643 | mDaySpinner.setMinValue(1); 644 | mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH)); 645 | mDaySpinner.setWrapSelectorWheel(true); 646 | mMonthSpinner.setDisplayedValues(null); 647 | mMonthSpinner.setMinValue(0); 648 | mMonthSpinner.setMaxValue(11); 649 | mMonthSpinner.setWrapSelectorWheel(true); 650 | } 651 | 652 | // make sure the month names are a zero based array 653 | // with the months in the month spinner 654 | String[] displayedValues = CVArrays.copyOfRange(mShortMonths, 655 | mMonthSpinner.getMinValue(), mMonthSpinner.getMaxValue() + 1); 656 | mMonthSpinner.setDisplayedValues(displayedValues); 657 | 658 | // year spinner range does not change based on the current date 659 | mYearSpinner.setMinValue(mMinDate.get(Calendar.YEAR)); 660 | mYearSpinner.setMaxValue(mMaxDate.get(Calendar.YEAR)); 661 | mYearSpinner.setWrapSelectorWheel(false); 662 | 663 | // set the spinner values 664 | mYearSpinner.setValue(mCurrentDate.get(Calendar.YEAR)); 665 | mMonthSpinner.setValue(mCurrentDate.get(Calendar.MONTH)); 666 | mDaySpinner.setValue(mCurrentDate.get(Calendar.DAY_OF_MONTH)); 667 | } 668 | 669 | /** 670 | * Updates the calendar view with the current date. 671 | */ 672 | private void updateCalendarView() { 673 | mCalendarView.setDate(mCurrentDate.getTimeInMillis(), false, false); 674 | } 675 | 676 | /** 677 | * @return The selected year. 678 | */ 679 | public int getYear() { 680 | return mCurrentDate.get(Calendar.YEAR); 681 | } 682 | 683 | /** 684 | * @return The selected month. 685 | */ 686 | public int getMonth() { 687 | return mCurrentDate.get(Calendar.MONTH); 688 | } 689 | 690 | /** 691 | * @return The selected day of month. 692 | */ 693 | public int getDayOfMonth() { 694 | return mCurrentDate.get(Calendar.DAY_OF_MONTH); 695 | } 696 | 697 | /** 698 | * Notifies the listener, if such, for a change in the selected date. 699 | */ 700 | private void notifyDateChanged() { 701 | sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); 702 | if (mOnDateChangedListener != null) { 703 | mOnDateChangedListener.onDateChanged(this, getYear(), getMonth(), getDayOfMonth()); 704 | } 705 | } 706 | 707 | /** 708 | * Sets the IME options for a spinner based on its ordering. 709 | * 710 | * @param spinner The spinner. 711 | * @param spinnerCount The total spinner count. 712 | * @param spinnerIndex The index of the given spinner. 713 | */ 714 | private void setImeOptions(NumberPicker spinner, int spinnerCount, int spinnerIndex) { 715 | final int imeOptions; 716 | if (spinnerIndex < spinnerCount - 1) { 717 | imeOptions = EditorInfo.IME_ACTION_NEXT; 718 | } else { 719 | imeOptions = EditorInfo.IME_ACTION_DONE; 720 | } 721 | TextView input = (TextView) spinner.findViewById(R.id.np__numberpicker_input); 722 | input.setImeOptions(imeOptions); 723 | } 724 | 725 | private void setContentDescriptions() { 726 | if (true) return; // increment/decrement buttons don't exist in backport 727 | // Day 728 | trySetContentDescription(mDaySpinner, R.id.np__increment, 729 | R.string.date_picker_increment_day_button); 730 | trySetContentDescription(mDaySpinner, R.id.np__decrement, 731 | R.string.date_picker_decrement_day_button); 732 | // Month 733 | trySetContentDescription(mMonthSpinner, R.id.np__increment, 734 | R.string.date_picker_increment_month_button); 735 | trySetContentDescription(mMonthSpinner, R.id.np__decrement, 736 | R.string.date_picker_decrement_month_button); 737 | // Year 738 | trySetContentDescription(mYearSpinner, R.id.np__increment, 739 | R.string.date_picker_increment_year_button); 740 | trySetContentDescription(mYearSpinner, R.id.np__decrement, 741 | R.string.date_picker_decrement_year_button); 742 | } 743 | 744 | private void trySetContentDescription(View root, int viewId, int contDescResId) { 745 | View target = root.findViewById(viewId); 746 | if (target != null) { 747 | target.setContentDescription(getContext().getString(contDescResId)); 748 | } 749 | } 750 | 751 | private void updateInputState() { 752 | // Make sure that if the user changes the value and the IME is active 753 | // for one of the inputs if this widget, the IME is closed. If the user 754 | // changed the value via the IME and there is a next input the IME will 755 | // be shown, otherwise the user chose another means of changing the 756 | // value and having the IME up makes no sense. 757 | //InputMethodManager inputMethodManager = InputMethodManager.peekInstance(); 758 | InputMethodManager inputMethodManager = 759 | (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 760 | if (inputMethodManager != null) { 761 | if (inputMethodManager.isActive(mYearSpinnerInput)) { 762 | mYearSpinnerInput.clearFocus(); 763 | inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); 764 | } else if (inputMethodManager.isActive(mMonthSpinnerInput)) { 765 | mMonthSpinnerInput.clearFocus(); 766 | inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); 767 | } else if (inputMethodManager.isActive(mDaySpinnerInput)) { 768 | mDaySpinnerInput.clearFocus(); 769 | inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); 770 | } 771 | } 772 | } 773 | 774 | /** 775 | * Class for managing state storing/restoring. 776 | */ 777 | private static class SavedState extends BaseSavedState { 778 | 779 | private final int mYear; 780 | 781 | private final int mMonth; 782 | 783 | private final int mDay; 784 | 785 | /** 786 | * Constructor called from {@link DatePicker#onSaveInstanceState()} 787 | */ 788 | private SavedState(Parcelable superState, int year, int month, int day) { 789 | super(superState); 790 | mYear = year; 791 | mMonth = month; 792 | mDay = day; 793 | } 794 | 795 | /** 796 | * Constructor called from {@link #CREATOR} 797 | */ 798 | private SavedState(Parcel in) { 799 | super(in); 800 | mYear = in.readInt(); 801 | mMonth = in.readInt(); 802 | mDay = in.readInt(); 803 | } 804 | 805 | @Override 806 | public void writeToParcel(Parcel dest, int flags) { 807 | super.writeToParcel(dest, flags); 808 | dest.writeInt(mYear); 809 | dest.writeInt(mMonth); 810 | dest.writeInt(mDay); 811 | } 812 | 813 | @SuppressWarnings("all") 814 | // suppress unused and hiding 815 | public static final Parcelable.Creator CREATOR = new Creator() { 816 | 817 | public SavedState createFromParcel(Parcel in) { 818 | return new SavedState(in); 819 | } 820 | 821 | public SavedState[] newArray(int size) { 822 | return new SavedState[size]; 823 | } 824 | }; 825 | } 826 | } 827 | -------------------------------------------------------------------------------- /library/src/net/simonvt/datepicker/DatePickerDialog.java: -------------------------------------------------------------------------------- 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 net.simonvt.datepicker; 18 | 19 | import android.app.AlertDialog; 20 | import android.content.Context; 21 | import android.content.DialogInterface; 22 | import android.content.DialogInterface.OnClickListener; 23 | import android.os.Build; 24 | import android.os.Bundle; 25 | import android.text.format.DateUtils; 26 | import android.view.LayoutInflater; 27 | import android.view.View; 28 | 29 | import java.util.Calendar; 30 | 31 | /** 32 | * A simple dialog containing an {@link android.widget.DatePicker}. 33 | * 34 | *

See the Pickers 35 | * guide.

36 | */ 37 | public class DatePickerDialog extends AlertDialog implements OnClickListener, 38 | DatePicker.OnDateChangedListener { 39 | 40 | private static final String YEAR = "year"; 41 | private static final String MONTH = "month"; 42 | private static final String DAY = "day"; 43 | 44 | private final DatePicker mDatePicker; 45 | private final OnDateSetListener mCallBack; 46 | private final Calendar mCalendar; 47 | 48 | private boolean mTitleNeedsUpdate = true; 49 | 50 | /** 51 | * The callback used to indicate the user is done filling in the date. 52 | */ 53 | public interface OnDateSetListener { 54 | 55 | /** 56 | * @param view The view associated with this listener. 57 | * @param year The year that was set. 58 | * @param monthOfYear The month that was set (0-11) for compatibility 59 | * with {@link java.util.Calendar}. 60 | * @param dayOfMonth The day of the month that was set. 61 | */ 62 | void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth); 63 | } 64 | 65 | /** 66 | * @param context The context the dialog is to run in. 67 | * @param callBack How the parent is notified that the date is set. 68 | * @param year The initial year of the dialog. 69 | * @param monthOfYear The initial month of the dialog. 70 | * @param dayOfMonth The initial day of the dialog. 71 | */ 72 | public DatePickerDialog(Context context, 73 | OnDateSetListener callBack, 74 | int year, 75 | int monthOfYear, 76 | int dayOfMonth) { 77 | this(context, Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB ? R.style.Theme_Dialog_Alert : 0, callBack, year, monthOfYear, dayOfMonth); 78 | } 79 | 80 | /** 81 | * @param context The context the dialog is to run in. 82 | * @param theme the theme to apply to this dialog 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 | int theme, 90 | OnDateSetListener callBack, 91 | int year, 92 | int monthOfYear, 93 | int dayOfMonth) { 94 | super(context, theme); 95 | 96 | mCallBack = callBack; 97 | 98 | mCalendar = Calendar.getInstance(); 99 | 100 | Context themeContext = getContext(); 101 | setButton(BUTTON_POSITIVE, themeContext.getText(R.string.date_time_done), this); 102 | setIcon(0); 103 | 104 | LayoutInflater inflater = 105 | (LayoutInflater) themeContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 106 | View view = inflater.inflate(R.layout.date_picker_dialog, null); 107 | setView(view); 108 | mDatePicker = (DatePicker) view.findViewById(R.id.datePicker); 109 | mDatePicker.init(year, monthOfYear, dayOfMonth, this); 110 | updateTitle(year, monthOfYear, dayOfMonth); 111 | } 112 | 113 | public void onClick(DialogInterface dialog, int which) { 114 | tryNotifyDateSet(); 115 | } 116 | 117 | public void onDateChanged(DatePicker view, int year, 118 | int month, int day) { 119 | mDatePicker.init(year, month, day, this); 120 | updateTitle(year, month, day); 121 | } 122 | 123 | /** 124 | * Gets the {@link DatePicker} contained in this dialog. 125 | * 126 | * @return The calendar view. 127 | */ 128 | public DatePicker getDatePicker() { 129 | return mDatePicker; 130 | } 131 | 132 | /** 133 | * Sets the current date. 134 | * 135 | * @param year The date year. 136 | * @param monthOfYear The date month. 137 | * @param dayOfMonth The date day of month. 138 | */ 139 | public void updateDate(int year, int monthOfYear, int dayOfMonth) { 140 | mDatePicker.updateDate(year, monthOfYear, dayOfMonth); 141 | } 142 | 143 | private void tryNotifyDateSet() { 144 | if (mCallBack != null) { 145 | mDatePicker.clearFocus(); 146 | mCallBack.onDateSet(mDatePicker, mDatePicker.getYear(), 147 | mDatePicker.getMonth(), mDatePicker.getDayOfMonth()); 148 | } 149 | } 150 | 151 | private void updateTitle(int year, int month, int day) { 152 | if (!mDatePicker.getCalendarViewShown()) { 153 | mCalendar.set(Calendar.YEAR, year); 154 | mCalendar.set(Calendar.MONTH, month); 155 | mCalendar.set(Calendar.DAY_OF_MONTH, day); 156 | String title = DateUtils.formatDateTime(getContext(), 157 | mCalendar.getTimeInMillis(), 158 | DateUtils.FORMAT_SHOW_DATE 159 | | DateUtils.FORMAT_SHOW_WEEKDAY 160 | | DateUtils.FORMAT_SHOW_YEAR 161 | | DateUtils.FORMAT_ABBREV_MONTH 162 | | DateUtils.FORMAT_ABBREV_WEEKDAY); 163 | setTitle(title); 164 | mTitleNeedsUpdate = true; 165 | } else { 166 | if (mTitleNeedsUpdate) { 167 | mTitleNeedsUpdate = false; 168 | setTitle(R.string.date_picker_dialog_title); 169 | } 170 | } 171 | } 172 | 173 | @Override 174 | public Bundle onSaveInstanceState() { 175 | Bundle state = super.onSaveInstanceState(); 176 | state.putInt(YEAR, mDatePicker.getYear()); 177 | state.putInt(MONTH, mDatePicker.getMonth()); 178 | state.putInt(DAY, mDatePicker.getDayOfMonth()); 179 | return state; 180 | } 181 | 182 | @Override 183 | public void onRestoreInstanceState(Bundle savedInstanceState) { 184 | super.onRestoreInstanceState(savedInstanceState); 185 | int year = savedInstanceState.getInt(YEAR); 186 | int month = savedInstanceState.getInt(MONTH); 187 | int day = savedInstanceState.getInt(DAY); 188 | mDatePicker.init(year, month, day, this); 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | 7 | org.sonatype.oss 8 | oss-parent 9 | 7 10 | 11 | 12 | net.simonvt 13 | android-datepicker-parent 14 | pom 15 | 1.0.1-SNAPSHOT 16 | 17 | Android DatePicker (Parent) 18 | A backport of the Android 4.2 DatePicker. 19 | https://github.com/SimonVT/android-datepicker 20 | 2012 21 | 22 | 23 | library 24 | samples 25 | 26 | 27 | 28 | http://github.com/SimonVT/android-datepicker/ 29 | scm:git:git://github.com/SimonVT/android-datepicker.git 30 | scm:git:git@github.com:SimonVT/android-datepicker.git 31 | HEAD 32 | 33 | 34 | 35 | 36 | Apache License Version 2.0 37 | http://www.apache.org/licenses/LICENSE-2.0.txt 38 | repo 39 | 40 | 41 | 42 | 43 | GitHub Issues 44 | https://github.com/SimonVT/android-datepicker/issues 45 | 46 | 47 | 48 | UTF-8 49 | UTF-8 50 | 51 | 1.6 52 | 4.1.1.4 53 | 16 54 | 55 | 56 | 57 | 58 | 59 | com.google.android 60 | android 61 | ${android.version} 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | org.apache.maven.plugins 71 | maven-compiler-plugin 72 | 3.0 73 | 74 | ${java.version} 75 | ${java.version} 76 | 77 | 78 | 79 | 80 | com.jayway.maven.plugins.android.generation2 81 | android-maven-plugin 82 | 3.5.1 83 | 84 | 85 | ${android.platform} 86 | 87 | 88 | true 89 | 90 | 91 | 92 | 93 | 94 | 95 | org.apache.maven.plugins 96 | maven-release-plugin 97 | 2.4 98 | 99 | true 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /samples/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 12 | 13 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /samples/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 29 | 30 | 31 | 40 | 41 | 42 | 43 | 47 | 48 | 60 | 61 | 62 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /samples/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | 7 | net.simonvt 8 | android-datepicker-parent 9 | 1.0.1-SNAPSHOT 10 | ../pom.xml 11 | 12 | 13 | android-datepicker-sample 14 | Android DatePicker Sample 15 | apk 16 | 17 | 18 | 19 | com.google.android 20 | android 21 | provided 22 | 23 | 24 | net.simonvt 25 | android-datepicker 26 | ${project.version} 27 | apklib 28 | 29 | 30 | 31 | 32 | src 33 | 34 | 35 | 36 | com.jayway.maven.plugins.android.generation2 37 | android-maven-plugin 38 | true 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /samples/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonVT/android-datepicker/HEAD/samples/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /samples/res/drawable-ldpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonVT/android-datepicker/HEAD/samples/res/drawable-ldpi/ic_launcher.png -------------------------------------------------------------------------------- /samples/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimonVT/android-datepicker/HEAD/samples/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /samples/res/layout/activity_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 12 |