/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.tencent.tws.assistant.widget;
import java.text.DateFormatSymbols;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;
import android.annotation.Widget;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.CalendarView;
import android.widget.CalendarView.OnDateChangeListener;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.TextView;
import com.tencent.tws.assistant.utils.ChineseCalendar;
import com.tencent.tws.assistant.widget.NumberPicker.Formatter;
import com.tencent.tws.assistant.widget.NumberPicker.OnValueChangeListener;
import com.tencent.tws.sharelib.R;
@Widget
public class DatePicker extends FrameLayout {
private static final String LOG_TAG = DatePicker.class.getSimpleName();
private static final String DATE_FORMAT = "MM/dd/yyyy";
private static final int DEFAULT_START_YEAR = 1970;
private static final int DEFAULT_END_YEAR = 2036;
private static final boolean DEFAULT_ENABLED_STATE = true;
// tws-start lunar calendar::2014-10-9
private final NumberPicker mLunarSpinner;
private String[] mLunarCalendars;
private boolean mIsLunar = false;
private String[] mChineseDateNames = null;
private String mYearName = "";
private String mMonthName = "";
private String mDayName = "";
// tws-end lunar calendar::2014-10-9
private final NumberPicker mDaySpinner;
private final NumberPicker mMonthSpinner;
private final NumberPicker mYearSpinner;
private final EditText mDaySpinnerInput;
private final EditText mMonthSpinnerInput;
private final EditText mYearSpinnerInput;
private Locale mCurrentLocale;
private OnDateChangedListener mOnDateChangedListener;
private String[] mShortMonths;
private final java.text.DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT);
private int mNumberOfMonths;
private Calendar mCalendar;
private ChineseCalendar mMinDate;
private ChineseCalendar mMaxDate;
private ChineseCalendar mCurrentDate;
private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
private Context mContext;
// default is false
private boolean mUnitShown = false;
private boolean mLunarShown = false;
/**
* The callback used to indicate the user changes\d the date.
*/
public interface OnDateChangedListener {
/**
* Called upon a date change.
*
* @param view
* The view associated with this listener.
* @param year
* The year that was set.
* @param monthOfYear
* The month that was set (0-11) for compatibility with
* {@link java.util.Calendar}.
* @param dayOfMonth
* The day of the month that was set.
*/
void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth);
}
public DatePicker(Context context) {
this(context, null);
}
public DatePicker(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.datePickerStyle);
}
public DatePicker(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
mChineseDateNames = context.getResources().getStringArray(R.array.lunar_day_names);
mLunarCalendars = context.getResources().getStringArray(R.array.tws_calendar_type);
mYearName = getContext().getString(R.string.calendar_year);
mMonthName = getContext().getString(R.string.calendar_month);
mDayName = getContext().getString(R.string.calendar_day);
// initialization based on locale
setCurrentLocale(Locale.getDefault());
TypedArray attributesArray = context.obtainStyledAttributes(attrs, R.styleable.DatePicker, defStyle, 0);
mUnitShown = attributesArray.getBoolean(R.styleable.DatePicker_unitShown, false);
mLunarShown = attributesArray.getBoolean(R.styleable.DatePicker_lunarShown, false);
int startYear = attributesArray.getInt(R.styleable.DatePicker_startYear, DEFAULT_START_YEAR);
int endYear = attributesArray.getInt(R.styleable.DatePicker_endYear, DEFAULT_END_YEAR);
String minDate = attributesArray.getString(R.styleable.DatePicker_minDate);
String maxDate = attributesArray.getString(R.styleable.DatePicker_maxDate);
int layoutResourceId = attributesArray.getResourceId(R.styleable.DatePicker_layout, R.layout.date_picker);
attributesArray.recycle();
// Log.d(LOG_TAG,"layoutResourceId = "+layoutResourceId);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(layoutResourceId, this, true);
OnValueChangeListener onChangeListener = new OnValueChangeListener() {
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
updateInputState();
mCalendar.setTimeInMillis(mCurrentDate.getTimeInMillis());
// take care of wrapping of days and months to update greater
// fields
if (picker == mLunarSpinner) {
if (newVal == ChineseCalendar.CALENDAR_TYPE_LUNAR) {
setIsLunar(true);
} else {
setIsLunar(false);
}
}
if (mIsLunar) {
if (picker == mDaySpinner) {
mCurrentDate.add(ChineseCalendar.CHINESE_DATE, newVal - oldVal);
} else if (picker == mMonthSpinner) {
mCurrentDate.add(ChineseCalendar.CHINESE_MONTH, newVal - oldVal);
} else if (picker == mYearSpinner) {
mCurrentDate.set(ChineseCalendar.CHINESE_YEAR, newVal);
}
} else {
if (picker == mDaySpinner) {
mCalendar.add(Calendar.DAY_OF_MONTH, newVal - oldVal);
} else if (picker == mMonthSpinner) {
mCalendar.add(Calendar.MONTH, newVal - oldVal);
} else if (picker == mYearSpinner) {
mCalendar.set(Calendar.YEAR, newVal);
}
// now set the date to the adjusted one
setDate(mCalendar.get(Calendar.YEAR), mCalendar.get(Calendar.MONTH),
mCalendar.get(Calendar.DAY_OF_MONTH));
}
updateSpinners();
updateCalendarView();
notifyDateChanged();
}
};
// tws-start lunar calendar::2014-10-9
mLunarSpinner = (NumberPicker) findViewById(R.id.lunar);
mLunarSpinner.setTextAlignType(NumberPicker.ALIGN_CENTER_TYPE);
mLunarSpinner.setOnLongPressUpdateInterval(100);
mLunarSpinner.setOnValueChangedListener(onChangeListener);
mLunarSpinner.setMinValue(0);
mLunarSpinner.setMaxValue(1);
mLunarSpinner.setValue(ChineseCalendar.CALENDAR_TYPE_GREGORIAN);
mLunarSpinner.setDisplayedValues(mLunarCalendars);
mLunarSpinner.setSlowScroller(true);
// tws-end lunar calendar::2014-10-9
// day
mDaySpinner = (NumberPicker) findViewById(R.id.day);
mDaySpinner.setTextAlignType(NumberPicker.ALIGN_LEFT_TYPE);
mDaySpinner.setOnLongPressUpdateInterval(100);
mDaySpinner.setOnValueChangedListener(onChangeListener);
mDaySpinnerInput = (EditText) mDaySpinner.findViewById(R.id.numberpicker_input);
// month
mMonthSpinner = (NumberPicker) findViewById(R.id.month);
mMonthSpinner.setOnLongPressUpdateInterval(100);
mMonthSpinner.setOnValueChangedListener(onChangeListener);
mMonthSpinnerInput = (EditText) mMonthSpinner.findViewById(R.id.numberpicker_input);
// year
mYearSpinner = (NumberPicker) findViewById(R.id.year);
mYearSpinner.setTextAlignType(NumberPicker.ALIGN_RIGHT_TYPE);
mYearSpinner.setOnLongPressUpdateInterval(100);
mYearSpinner.setOnValueChangedListener(onChangeListener);
mYearSpinnerInput = (EditText) mYearSpinner.findViewById(R.id.numberpicker_input);
if (mUnitShown) {
mYearSpinner.setFormatter(mYearFormatter);
mMonthSpinner.setFormatter(mMonthFormatter);
mDaySpinner.setFormatter(mDayFormatter);
} else {
mMonthSpinner.setFormatter(mMonthNoUnitFormatter);
mDaySpinner.setFormatter(mDayNoUnitFormatter);
}
// set the min date giving priority of the minDate over startYear
mCalendar.clear();
if (!TextUtils.isEmpty(minDate)) {
if (!parseDate(minDate, mCalendar)) {
mCalendar.set(startYear, 0, 1);
}
} else {
mCalendar.set(startYear, 0, 1);
}
setMinDate(mCalendar.getTimeInMillis());
// set the max date giving priority of the maxDate over endYear
mCalendar.clear();
if (!TextUtils.isEmpty(maxDate)) {
if (!parseDate(maxDate, mCalendar)) {
mCalendar.set(endYear, 11, 31);
}
} else {
mCalendar.set(endYear, 11, 31);
}
setMaxDate(mCalendar.getTimeInMillis());
// initialize to current date
mCurrentDate.setTimeInMillis(System.currentTimeMillis());
init(mCurrentDate.get(Calendar.YEAR), mCurrentDate.get(Calendar.MONTH),
mCurrentDate.get(Calendar.DAY_OF_MONTH), null);
// set content descriptions
if (AccessibilityManager.getInstance(mContext).isEnabled()) {
setContentDescriptions();
}
}
public void setLunarShown(boolean lunarShown) {
if (mLunarSpinner == null || lunarShown == mLunarShown)
return;
mLunarShown = lunarShown;
mLunarSpinner.setEnabled(mLunarShown);
if (mLunarShown) {
mLunarSpinner.setVisibility(View.VISIBLE);
} else {
mLunarSpinner.setVisibility(View.GONE);
}
invalidate();
}
public void setUnitShown(boolean unitShown) {
if (mUnitShown == unitShown)
return;
mUnitShown = unitShown;
if (mUnitShown) {
mYearSpinner.setFormatter(mYearFormatter);
if (mIsLunar) {
mDaySpinner.setFormatter(mLunarDayFormatter);
mMonthSpinner.setFormatter(null);
} else {
mMonthSpinner.setFormatter(mMonthFormatter);
mDaySpinner.setFormatter(mDayFormatter);
}
} else {
mYearSpinner.setFormatter(null);
mMonthSpinner.setFormatter(mMonthNoUnitFormatter);
mDaySpinner.setFormatter(mDayNoUnitFormatter);
}
mYearSpinner.invalidate();
mMonthSpinner.invalidate();
mDaySpinner.invalidate();
}
/**
* Gets the minimal date supported by this {@link DatePicker} in
* milliseconds since January 1, 1970 00:00:00 in
* {@link TimeZone#getDefault()} time zone.
* <p>
* Note: The default minimal date is 01/01/1900.
* <p>
*
* @return The minimal supported date.
*/
public long getMinDate() {
return mMinDate.getTimeInMillis();
// return mCalendarView.getMinDate();
}
/**
* Sets the minimal date supported by this {@link NumberPicker} in
* milliseconds since January 1, 1970 00:00:00 in
* {@link TimeZone#getDefault()} time zone.
*
* @param minDate
* The minimal supported date.
*/
public void setMinDate(long minDate) {
mCalendar.setTimeInMillis(minDate);
if (mCalendar.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
&& mCalendar.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) {
return;
}
mMinDate.setTimeInMillis(minDate);
// mCalendarView.setMinDate(minDate);
if (mCurrentDate.before(mMinDate)) {
mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
updateCalendarView();
}
updateSpinners();
}
/**
* Gets the maximal date supported by this {@link DatePicker} in
* milliseconds since January 1, 1970 00:00:00 in
* {@link TimeZone#getDefault()} time zone.
* <p>
* Note: The default maximal date is 12/31/2100.
* <p>
*
* @return The maximal supported date.
*/
public long getMaxDate() {
return mMaxDate.getTimeInMillis();
// return mCalendarView.getMaxDate();
}
/**
* Sets the maximal date supported by this {@link DatePicker} in
* milliseconds since January 1, 1970 00:00:00 in
* {@link TimeZone#getDefault()} time zone.
*
* @param maxDate
* The maximal supported date.
*/
public void setMaxDate(long maxDate) {
mCalendar.setTimeInMillis(maxDate);
if (mCalendar.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
&& mCalendar.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) {
return;
}
mMaxDate.setTimeInMillis(maxDate);
// mCalendarView.setMaxDate(maxDate);
if (mCurrentDate.after(mMaxDate)) {
mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
updateCalendarView();
}
updateSpinners();
}
@Override
public void setEnabled(boolean enabled) {
if (mIsEnabled == enabled) {
return;
}
super.setEnabled(enabled);
mDaySpinner.setEnabled(enabled);
mMonthSpinner.setEnabled(enabled);
mYearSpinner.setEnabled(enabled);
// mCalendarView.setEnabled(enabled);
mIsEnabled = enabled;
}
@Override
public boolean isEnabled() {
return mIsEnabled;
}
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
onPopulateAccessibilityEvent(event);
return true;
}
@Override
public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
super.onPopulateAccessibilityEvent(event);
final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR;
String selectedDateUtterance = DateUtils.formatDateTime(mContext, mCurrentDate.getTimeInMillis(), flags);
event.getText().add(selectedDateUtterance);
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setCurrentLocale(newConfig.locale);
}
/**
* Gets whether the {@link CalendarView} is shown.
*
* @return True if the calendar view is shown.
* @see #getCalendarView()
*/
public boolean getCalendarViewShown() {
return false;
// return mCalendarView.isShown();
}
/**
* Gets the {@link CalendarView}.
*
* @return The calendar view.
* @see #getCalendarViewShown()
*/
public CalendarView getCalendarView() {
return null;
// return mCalendarView;
}
/**
* Sets whether the {@link CalendarView} is shown.
*
* @param shown
* True if the calendar view is to be shown.
*/
public void setCalendarViewShown(boolean shown) {
// mCalendarView.setVisibility(shown ? VISIBLE : GONE);
// if (shown) {
// mCalendarView.setOnDateChangeListener(mCalendarChange);
// } else {
// mCalendarView.setOnDateChangeListener(null);
// }
}
/**
* Sets the current locale.
*
* @param locale
* The current locale.
*/
private void setCurrentLocale(Locale locale) {
if (locale.equals(mCurrentLocale)) {
return;
}
mCurrentLocale = locale;
mCalendar = getCalendarForLocale(mCalendar, locale);
// mMinDate = getCalendarForLocale(mMinDate, locale);
// mMaxDate = getCalendarForLocale(mMaxDate, locale);
// mCurrentDate = (ChineseCalendar) getCalendarForLocale(mCurrentDate,
// locale);
mMinDate = new ChineseCalendar(getContext());
mMaxDate = new ChineseCalendar(getContext());
mCurrentDate = new ChineseCalendar(getContext());
mNumberOfMonths = mCalendar.getActualMaximum(Calendar.MONTH) + 1;
mShortMonths = new DateFormatSymbols().getShortMonths();
if (usingNumericMonths()) {
// We're in a locale where a date should either be all-numeric, or
// all-text.
// All-text would require custom NumberPicker formatters for day and
// year.
mShortMonths = new String[mNumberOfMonths];
for (int i = 0; i < mNumberOfMonths; ++i) {
mShortMonths[i] = String.format("%d", i + 1);
}
}
}
/**
* Tests whether the current locale is one where there are no real month
* names, such as Chinese, Japanese, or Korean locales.
*/
private boolean usingNumericMonths() {
// tws-start using NumericMonth::2014-8-22
// return Character.isDigit(mShortMonths[Calendar.JANUARY].charAt(0));
return true;
// tws-end using NumericMonth::2014-8-22
}
/**
* Gets a calendar for locale bootstrapped with the value of a given
* calendar.
*
* @param oldCalendar
* The old calendar.
* @param locale
* The locale.
*/
private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
if (oldCalendar == null) {
return Calendar.getInstance(locale);
} else {
final long currentTimeMillis = oldCalendar.getTimeInMillis();
Calendar newCalendar = Calendar.getInstance(locale);
newCalendar.setTimeInMillis(currentTimeMillis);
return newCalendar;
}
}
/**
* Updates the current date.
*
* @param year
* The year.
* @param month
* The month which is <strong>starting from zero</strong>.
* @param dayOfMonth
* The day of the month.
*/
public void updateDate(int year, int month, int dayOfMonth) {
if (!isNewDate(year, month, dayOfMonth)) {
return;
}
setDate(year, month, dayOfMonth);
updateSpinners();
updateCalendarView();
notifyDateChanged();
}
// Override so we are in complete control of save / restore for this widget.
@Override
protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
dispatchThawSelfOnly(container);
}
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
return new SavedState(superState, getYear(), getMonth(), getDayOfMonth());
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
setDate(ss.mYear, ss.mMonth, ss.mDay);
updateSpinners();
updateCalendarView();
}
/**
* Initialize the state. If the provided values designate an inconsistent
* date the values are normalized before updating the spinners.
*
* @param year
* The initial year.
* @param monthOfYear
* The initial month <strong>starting from zero</strong>.
* @param dayOfMonth
* The initial day of the month.
* @param onDateChangedListener
* How user is notified date is changed by user, can be null.
*/
public void init(int year, int monthOfYear, int dayOfMonth, OnDateChangedListener onDateChangedListener) {
setDate(year, monthOfYear, dayOfMonth);
updateSpinners();
updateCalendarView();
mOnDateChangedListener = onDateChangedListener;
}
/**
* Parses the given <code>date</code> and in case of success sets the result
* to the <code>outDate</code>.
*
* @return True if the date was parsed.
*/
private boolean parseDate(String date, Calendar outDate) {
try {
outDate.setTime(mDateFormat.parse(date));
return true;
} catch (ParseException e) {
Log.w(LOG_TAG, "Date: " + date + " not in format: " + DATE_FORMAT);
return false;
}
}
private boolean isNewDate(int year, int month, int dayOfMonth) {
return (mCurrentDate.get(Calendar.YEAR) != year || mCurrentDate.get(Calendar.MONTH) != dayOfMonth || mCurrentDate
.get(Calendar.DAY_OF_MONTH) != month);
}
private void setDate(int year, int month, int dayOfMonth) {
mCurrentDate.set(year, month, dayOfMonth);
if (mCurrentDate.before(mMinDate)) {
mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
} else if (mCurrentDate.after(mMaxDate)) {
mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
}
}
private void updateSpinners() {
// year spinner range does not change based on the current date
mYearSpinner.setMinValue(mMinDate.get(Calendar.YEAR));
mYearSpinner.setMaxValue(mMaxDate.get(Calendar.YEAR));
mYearSpinner.setWrapSelectorWheel(true);
if (mUnitShown) {
mYearSpinner.setFormatter(mYearFormatter);
}
if (mIsLunar) {
mDaySpinner.setFormatter(mLunarDayFormatter);
mMonthSpinner.setFormatter(null);
mMonthSpinner.setDisplayedValues(null);
String[] months = mCurrentDate.getChinesMonths(mCurrentDate.get(ChineseCalendar.CHINESE_YEAR));
if (mCurrentDate.get(ChineseCalendar.CHINESE_YEAR) == mMinDate.get(ChineseCalendar.CHINESE_YEAR)) {
int minMonth = mMinDate.get(ChineseCalendar.CHINESE_MONTH) - 1;
int maxMonth = mMinDate.getActualMaximum(ChineseCalendar.CHINESE_MONTH);
int monthCount = maxMonth - minMonth + 1;
String[] tempMonths = new String[monthCount];
for (int i = 0; i < tempMonths.length; i++) {
tempMonths[i] = months[minMonth + i];
}
months = tempMonths;
mMonthSpinner.setMinValue(minMonth);
mMonthSpinner.setMaxValue(maxMonth);
mMonthSpinner.setWrapSelectorWheel(false);
if (mCurrentDate.get(ChineseCalendar.CHINESE_MONTH) == mMinDate.get(ChineseCalendar.CHINESE_MONTH)) {
mDaySpinner.setMinValue(mMinDate.get(ChineseCalendar.CHINESE_DATE));
mDaySpinner.setMaxValue(mMinDate.getActualMaximum(ChineseCalendar.CHINESE_DATE));
mDaySpinner.setWrapSelectorWheel(false);
} else {
mDaySpinner.setMinValue(1);
mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(ChineseCalendar.CHINESE_DATE));
mDaySpinner.setWrapSelectorWheel(true);
}
} else if (mCurrentDate.get(ChineseCalendar.CHINESE_YEAR) == mMaxDate.get(ChineseCalendar.CHINESE_YEAR)) {
mMonthSpinner.setMinValue(0);
mMonthSpinner.setMaxValue(mMaxDate.get(ChineseCalendar.CHINESE_MONTH));
mMonthSpinner.setWrapSelectorWheel(false);
if (mCurrentDate.get(ChineseCalendar.CHINESE_MONTH) == mMaxDate.get(ChineseCalendar.CHINESE_MONTH)) {
mDaySpinner.setMinValue(1);
mDaySpinner.setMaxValue(mMaxDate.get(ChineseCalendar.CHINESE_DATE));
mDaySpinner.setWrapSelectorWheel(false);
} else {
mDaySpinner.setMinValue(1);
mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(ChineseCalendar.CHINESE_DATE));
mDaySpinner.setWrapSelectorWheel(true);
}
} else {
mDaySpinner.setMinValue(1);
mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(ChineseCalendar.CHINESE_DATE));
mDaySpinner.setWrapSelectorWheel(true);
mMonthSpinner.setMinValue(0);
mMonthSpinner.setMaxValue(mCurrentDate.getActualMaximum(ChineseCalendar.CHINESE_MONTH));
mMonthSpinner.setWrapSelectorWheel(true);
}
mMonthSpinner.setDisplayedValues(months);
int leapMonth = ChineseCalendar.getChineseLeapMonth(mCurrentDate.get(ChineseCalendar.CHINESE_YEAR));
int lunarMonth = mCurrentDate.get(ChineseCalendar.CHINESE_MONTH);
int index = lunarMonth;
if (leapMonth > 0) {
if (lunarMonth < 0 || lunarMonth > leapMonth) {
index = Math.abs(lunarMonth) + 1;
}
}
mMonthSpinner.setValue(index - 1);
mYearSpinner.setValue(mCurrentDate.get(ChineseCalendar.CHINESE_YEAR));
mDaySpinner.setValue(mCurrentDate.get(ChineseCalendar.CHINESE_DATE));
} else {
mMonthSpinner.setDisplayedValues(null);
if (mUnitShown) {
mMonthSpinner.setFormatter(mMonthFormatter);
mDaySpinner.setFormatter(mDayFormatter);
} else {
mMonthSpinner.setFormatter(mMonthNoUnitFormatter);
mDaySpinner.setFormatter(mDayNoUnitFormatter);
}
mDaySpinner.setMinValue(1);
mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
mDaySpinner.setWrapSelectorWheel(true);
mMonthSpinner.setMinValue(0);
mMonthSpinner.setMaxValue(11);
mMonthSpinner.setWrapSelectorWheel(true);
mMonthSpinner.setValue(mCurrentDate.get(Calendar.MONTH));
mDaySpinner.setValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
mYearSpinner.setValue(mCurrentDate.get(Calendar.YEAR));
}
}
/**
* Updates the calendar view with the current date.
*/
private void updateCalendarView() {
// mCalendarView.setDate(mCurrentDate.getTimeInMillis(), false, false);
}
/**
* @return The selected year.
*/
public int getYear() {
return mCurrentDate.get(Calendar.YEAR);
}
/**
* @return The selected month.
*/
public int getMonth() {
return mCurrentDate.get(Calendar.MONTH);
}
/**
* @return The selected day of month.
*/
public int getDayOfMonth() {
return mCurrentDate.get(Calendar.DAY_OF_MONTH);
}
/**
* Notifies the listener, if such, for a change in the selected date.
*/
private void notifyDateChanged() {
// sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
if (mOnDateChangedListener != null) {
mOnDateChangedListener.onDateChanged(this, getYear(), getMonth(), getDayOfMonth());
}
}
/**
* Sets the IME options for a spinner based on its ordering.
*
* @param spinner
* The spinner.
* @param spinnerCount
* The total spinner count.
* @param spinnerIndex
* The index of the given spinner.
*/
private void setImeOptions(NumberPicker spinner, int spinnerCount, int spinnerIndex) {
final int imeOptions;
if (spinnerIndex < spinnerCount - 1) {
imeOptions = EditorInfo.IME_ACTION_NEXT;
} else {
imeOptions = EditorInfo.IME_ACTION_DONE;
}
TextView input = (TextView) spinner.findViewById(R.id.numberpicker_input);
input.setImeOptions(imeOptions);
}
private void setContentDescriptions() {
// Day
trySetContentDescription(mDaySpinner, R.id.increment, R.string.date_picker_increment_day_button);
trySetContentDescription(mDaySpinner, R.id.decrement, R.string.date_picker_decrement_day_button);
// Month
trySetContentDescription(mMonthSpinner, R.id.increment, R.string.date_picker_increment_month_button);
trySetContentDescription(mMonthSpinner, R.id.decrement, R.string.date_picker_decrement_month_button);
// Year
trySetContentDescription(mYearSpinner, R.id.increment, R.string.date_picker_increment_year_button);
trySetContentDescription(mYearSpinner, R.id.decrement, R.string.date_picker_decrement_year_button);
}
private void trySetContentDescription(View root, int viewId, int contDescResId) {
View target = root.findViewById(viewId);
if (target != null) {
target.setContentDescription(mContext.getString(contDescResId));
}
}
private void updateInputState() {
// Make sure that if the user changes the value and the IME is active
// for one of the inputs if this widget, the IME is closed. If the user
// changed the value via the IME and there is a next input the IME will
// be shown, otherwise the user chose another means of changing the
// value and having the IME up makes no sense.
InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
if (inputMethodManager != null) {
if (inputMethodManager.isActive(mYearSpinnerInput)) {
mYearSpinnerInput.clearFocus();
inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
} else if (inputMethodManager.isActive(mMonthSpinnerInput)) {
mMonthSpinnerInput.clearFocus();
inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
} else if (inputMethodManager.isActive(mDaySpinnerInput)) {
mDaySpinnerInput.clearFocus();
inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
}
}
}
/**
* Class for managing state storing/restoring.
*/
private static class SavedState extends BaseSavedState {
private final int mYear;
private final int mMonth;
private final int mDay;
/**
* Constructor called from {@link DatePicker#onSaveInstanceState()}
*/
private SavedState(Parcelable superState, int year, int month, int day) {
super(superState);
mYear = year;
mMonth = month;
mDay = day;
}
/**
* Constructor called from {@link #CREATOR}
*/
private SavedState(Parcel in) {
super(in);
mYear = in.readInt();
mMonth = in.readInt();
mDay = in.readInt();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(mYear);
dest.writeInt(mMonth);
dest.writeInt(mDay);
}
@SuppressWarnings("all")
// suppress unused and hiding
public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
OnDateChangeListener mCalendarChange = new CalendarView.OnDateChangeListener() {
public void onSelectedDayChange(CalendarView view, int year, int month, int monthDay) {
setDate(year, month, monthDay);
updateSpinners();
notifyDateChanged();
}
};
public void setIsLunar(boolean isLunar) {
mIsLunar = isLunar;
updateSpinners();
mLunarSpinner.setValue(isLunar ? ChineseCalendar.CALENDAR_TYPE_LUNAR : ChineseCalendar.CALENDAR_TYPE_GREGORIAN);
// Log.d(LOG_TAG,
// "setIsLunar=" + isLunar + ",lunarYear=" +
// mCurrentDate.get(ChineseCalendar.CHINESE_YEAR)
// + ",Year=" + mCurrentDate.get(Calendar.YEAR));
}
public boolean isLunar() {
return mIsLunar;
}
public void setLunarSpinnerVisibility(boolean isLunar) {
mLunarSpinner.setVisibility(isLunar ? View.VISIBLE : View.GONE);
if (!isLunar) {
mLunarSpinner.setValue(ChineseCalendar.CALENDAR_TYPE_GREGORIAN);
setIsLunar(isLunar);
}
invalidate();
}
public void setYearSpinnerVisibility(boolean isShow) {
mYearSpinner.setVisibility(isShow ? View.VISIBLE : View.GONE);
invalidate();
}
Formatter mYearFormatter = new Formatter() {
@Override
public String format(int value) {
return value + mYearName;
}
};
Formatter mMonthFormatter = new Formatter() {
@Override
public String format(int value) {
if (value < 9) {
return "0" + (value + 1) + mMonthName;
}
return (value + 1) + mMonthName;
}
};
Formatter mMonthNoUnitFormatter = new Formatter() {
@Override
public String format(int value) {
if (value < 9) {
return "0" + (value + 1);
}
return (value + 1) + "";
}
};
Formatter mDayFormatter = new Formatter() {
@Override
public String format(int value) {
if (value < 10) {
return "0" + value + mDayName;
}
return value + mDayName;
}
};
Formatter mDayNoUnitFormatter = new Formatter() {
@Override
public String format(int value) {
if (value < 10) {
return "0" + value;
}
return value + "";
}
};
Formatter mLunarDayFormatter = new Formatter() {
@Override
public String format(int value) {
return mChineseDateNames[value];
}
};
}