/* * Copyright (C) 2015 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 android.widget; import com.android.internal.widget.PagerAdapter; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.util.SparseArray; import android.view.View; import android.view.ViewGroup; import android.widget.SimpleMonthView.OnDayClickListener; import java.util.Calendar; /** * An adapter for a list of {@link android.widget.SimpleMonthView} items. */ class DayPickerAdapter extends PagerAdapter { private static final int MONTHS_IN_YEAR = 12; private final Calendar mMinDate = Calendar.getInstance(); private final Calendar mMaxDate = Calendar.getInstance(); private final SparseArray mItems = new SparseArray<>(); private Calendar mSelectedDay = Calendar.getInstance(); private int mMonthTextAppearance; private int mDayOfWeekTextAppearance; private int mDayTextAppearance; private ColorStateList mCalendarTextColor; private ColorStateList mDaySelectorColor; private ColorStateList mDayHighlightColor; private OnDaySelectedListener mOnDaySelectedListener; private int mFirstDayOfWeek; public DayPickerAdapter(Context context) { final TypedArray ta = context.obtainStyledAttributes(new int[] { com.android.internal.R.attr.colorControlHighlight}); mDayHighlightColor = ta.getColorStateList(0); ta.recycle(); } public void setRange(Calendar min, Calendar max) { mMinDate.setTimeInMillis(min.getTimeInMillis()); mMaxDate.setTimeInMillis(max.getTimeInMillis()); // Positions are now invalid, clear everything and start over. notifyDataSetChanged(); } /** * Sets the first day of the week. * * @param weekStart which day the week should start on, valid values are * {@link Calendar#SUNDAY} through {@link Calendar#SATURDAY} */ public void setFirstDayOfWeek(int weekStart) { mFirstDayOfWeek = weekStart; // Update displayed views. final int count = mItems.size(); for (int i = 0; i < count; i++) { final SimpleMonthView monthView = mItems.valueAt(i); monthView.setFirstDayOfWeek(weekStart); } } public int getFirstDayOfWeek() { return mFirstDayOfWeek; } /** * Sets the selected day. * * @param day the selected day */ public void setSelectedDay(Calendar day) { final int oldPosition = getPositionForDay(mSelectedDay); final int newPosition = getPositionForDay(day); // Clear the old position if necessary. if (oldPosition != newPosition) { final SimpleMonthView oldMonthView = mItems.get(oldPosition, null); if (oldMonthView != null) { oldMonthView.setSelectedDay(-1); } } // Set the new position. final SimpleMonthView newMonthView = mItems.get(newPosition, null); if (newMonthView != null) { final int dayOfMonth = day.get(Calendar.DAY_OF_MONTH); newMonthView.setSelectedDay(dayOfMonth); } mSelectedDay = day; } /** * Sets the listener to call when the user selects a day. * * @param listener The listener to call. */ public void setOnDaySelectedListener(OnDaySelectedListener listener) { mOnDaySelectedListener = listener; } void setCalendarTextColor(ColorStateList calendarTextColor) { mCalendarTextColor = calendarTextColor; } void setDaySelectorColor(ColorStateList selectorColor) { mDaySelectorColor = selectorColor; } void setMonthTextAppearance(int resId) { mMonthTextAppearance = resId; } void setDayOfWeekTextAppearance(int resId) { mDayOfWeekTextAppearance = resId; } int getDayOfWeekTextAppearance() { return mDayOfWeekTextAppearance; } void setDayTextAppearance(int resId) { mDayTextAppearance = resId; } int getDayTextAppearance() { return mDayTextAppearance; } @Override public int getCount() { final int diffYear = mMaxDate.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR); final int diffMonth = mMaxDate.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH); return diffMonth + MONTHS_IN_YEAR * diffYear + 1; } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } private int getMonthForPosition(int position) { return position % MONTHS_IN_YEAR + mMinDate.get(Calendar.MONTH); } private int getYearForPosition(int position) { return position / MONTHS_IN_YEAR + mMinDate.get(Calendar.YEAR); } private int getPositionForDay(Calendar day) { final int yearOffset = (day.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR)); final int monthOffset = (day.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH)); return yearOffset * MONTHS_IN_YEAR + monthOffset; } @Override public Object instantiateItem(ViewGroup container, int position) { final SimpleMonthView v = new SimpleMonthView(container.getContext()); v.setOnDayClickListener(mOnDayClickListener); v.setMonthTextAppearance(mMonthTextAppearance); v.setDayOfWeekTextAppearance(mDayOfWeekTextAppearance); v.setDayTextAppearance(mDayTextAppearance); if (mDaySelectorColor != null) { v.setDaySelectorColor(mDaySelectorColor); } if (mDayHighlightColor != null) { v.setDayHighlightColor(mDayHighlightColor); } if (mCalendarTextColor != null) { v.setMonthTextColor(mCalendarTextColor); v.setDayOfWeekTextColor(mCalendarTextColor); v.setDayTextColor(mCalendarTextColor); } final int month = getMonthForPosition(position); final int year = getYearForPosition(position); final int selectedDay; if (mSelectedDay.get(Calendar.MONTH) == month) { selectedDay = mSelectedDay.get(Calendar.DAY_OF_MONTH); } else { selectedDay = -1; } final int enabledDayRangeStart; if (mMinDate.get(Calendar.MONTH) == month && mMinDate.get(Calendar.YEAR) == year) { enabledDayRangeStart = mMinDate.get(Calendar.DAY_OF_MONTH); } else { enabledDayRangeStart = 1; } final int enabledDayRangeEnd; if (mMaxDate.get(Calendar.MONTH) == month && mMaxDate.get(Calendar.YEAR) == year) { enabledDayRangeEnd = mMaxDate.get(Calendar.DAY_OF_MONTH); } else { enabledDayRangeEnd = 31; } v.setMonthParams(selectedDay, month, year, mFirstDayOfWeek, enabledDayRangeStart, enabledDayRangeEnd); mItems.put(position, v); container.addView(v); return v; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView(mItems.get(position)); mItems.remove(position); } @Override public int getItemPosition(Object object) { final int index = mItems.indexOfValue((SimpleMonthView) object); if (index < 0) { return mItems.keyAt(index); } return -1; } @Override public CharSequence getPageTitle(int position) { final SimpleMonthView v = mItems.get(position); if (v != null) { return v.getTitle(); } return null; } private boolean isCalendarInRange(Calendar value) { return value.compareTo(mMinDate) >= 0 && value.compareTo(mMaxDate) <= 0; } private final OnDayClickListener mOnDayClickListener = new OnDayClickListener() { @Override public void onDayClick(SimpleMonthView view, Calendar day) { if (day != null && isCalendarInRange(day)) { setSelectedDay(day); if (mOnDaySelectedListener != null) { mOnDaySelectedListener.onDaySelected(DayPickerAdapter.this, day); } } } }; public interface OnDaySelectedListener { public void onDaySelected(DayPickerAdapter view, Calendar day); } }