1e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung/* 2e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * Copyright (C) 2013 The Android Open Source Project 3e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * 4e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * Licensed under the Apache License, Version 2.0 (the "License"); 5e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * you may not use this file except in compliance with the License. 6e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * You may obtain a copy of the License at 7e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * 8e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * http://www.apache.org/licenses/LICENSE-2.0 9e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * 10e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * Unless required by applicable law or agreed to in writing, software 11e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * distributed under the License is distributed on an "AS IS" BASIS, 12e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * See the License for the specific language governing permissions and 14e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * limitations under the License. 15e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung */ 16e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 17e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kungpackage com.android.datetimepicker.date; 18e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 19e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kungimport android.annotation.SuppressLint; 20e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kungimport android.content.Context; 21e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kungimport android.text.format.Time; 22e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kungimport android.view.View; 23e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kungimport android.view.ViewGroup; 24e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kungimport android.widget.AbsListView.LayoutParams; 25e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kungimport android.widget.BaseAdapter; 26e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 27e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kungimport com.android.datetimepicker.date.MonthView.OnDayClickListener; 28e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 29e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kungimport java.util.Calendar; 30e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kungimport java.util.HashMap; 31e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 32e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung/** 33e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * An adapter for a list of {@link MonthView} items. 34e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung */ 35e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kungpublic abstract class MonthAdapter extends BaseAdapter implements OnDayClickListener { 36e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 37e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung private static final String TAG = "SimpleMonthAdapter"; 38e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 39e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung private final Context mContext; 407c597aee285f2fe4a13a24334493c6eadddd7939Sam Blitzstein protected final DatePickerController mController; 41e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 42e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung private CalendarDay mSelectedDay; 43e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 44e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung protected static int WEEK_7_OVERHANG_HEIGHT = 7; 45e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung protected static final int MONTHS_IN_YEAR = 12; 46e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 47e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung /** 48e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * A convenience class to represent a specific date. 49e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung */ 50e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung public static class CalendarDay { 51e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung private Calendar calendar; 52e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung private Time time; 53e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung int year; 54e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung int month; 55e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung int day; 56e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 57e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung public CalendarDay() { 58e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung setTime(System.currentTimeMillis()); 59e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 60e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 61e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung public CalendarDay(long timeInMillis) { 62e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung setTime(timeInMillis); 63e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 64e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 65e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung public CalendarDay(Calendar calendar) { 66e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung year = calendar.get(Calendar.YEAR); 67e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung month = calendar.get(Calendar.MONTH); 68e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung day = calendar.get(Calendar.DAY_OF_MONTH); 69e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 70e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 71e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung public CalendarDay(int year, int month, int day) { 72e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung setDay(year, month, day); 73e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 74e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 75e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung public void set(CalendarDay date) { 76e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung year = date.year; 77e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung month = date.month; 78e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung day = date.day; 79e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 80e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 81e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung public void setDay(int year, int month, int day) { 82e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung this.year = year; 83e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung this.month = month; 84e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung this.day = day; 85e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 86e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 87e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung public synchronized void setJulianDay(int julianDay) { 88e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung if (time == null) { 89e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung time = new Time(); 90e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 91e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung time.setJulianDay(julianDay); 92e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung setTime(time.toMillis(false)); 93e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 94e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 95e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung private void setTime(long timeInMillis) { 96e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung if (calendar == null) { 97e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung calendar = Calendar.getInstance(); 98e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 99e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung calendar.setTimeInMillis(timeInMillis); 100e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung month = calendar.get(Calendar.MONTH); 101e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung year = calendar.get(Calendar.YEAR); 102e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung day = calendar.get(Calendar.DAY_OF_MONTH); 103e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 1045cfe197091de6e7b5550fc2503e00fe554bef5cdSam Blitzstein 1055cfe197091de6e7b5550fc2503e00fe554bef5cdSam Blitzstein public int getYear() { 1065cfe197091de6e7b5550fc2503e00fe554bef5cdSam Blitzstein return year; 1075cfe197091de6e7b5550fc2503e00fe554bef5cdSam Blitzstein } 1085cfe197091de6e7b5550fc2503e00fe554bef5cdSam Blitzstein 1095cfe197091de6e7b5550fc2503e00fe554bef5cdSam Blitzstein public int getMonth() { 1105cfe197091de6e7b5550fc2503e00fe554bef5cdSam Blitzstein return month; 1115cfe197091de6e7b5550fc2503e00fe554bef5cdSam Blitzstein } 1125cfe197091de6e7b5550fc2503e00fe554bef5cdSam Blitzstein 1135cfe197091de6e7b5550fc2503e00fe554bef5cdSam Blitzstein public int getDay() { 1145cfe197091de6e7b5550fc2503e00fe554bef5cdSam Blitzstein return day; 1155cfe197091de6e7b5550fc2503e00fe554bef5cdSam Blitzstein } 116e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 117e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 118e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung public MonthAdapter(Context context, 119e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung DatePickerController controller) { 120e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung mContext = context; 121e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung mController = controller; 122e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung init(); 123e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung setSelectedDay(mController.getSelectedDay()); 124e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 125e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 126e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung /** 127e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * Updates the selected day and related parameters. 128e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * 129e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * @param day The day to highlight 130e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung */ 131e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung public void setSelectedDay(CalendarDay day) { 132e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung mSelectedDay = day; 133e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung notifyDataSetChanged(); 134e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 135e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 136e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung public CalendarDay getSelectedDay() { 137e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung return mSelectedDay; 138e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 139e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 140e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung /** 141e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * Set up the gesture detector and selected time 142e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung */ 143e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung protected void init() { 144e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung mSelectedDay = new CalendarDay(System.currentTimeMillis()); 145e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 146e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 147e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung @Override 148e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung public int getCount() { 149e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung return ((mController.getMaxYear() - mController.getMinYear()) + 1) * MONTHS_IN_YEAR; 150e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 151e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 152e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung @Override 153e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung public Object getItem(int position) { 154e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung return null; 155e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 156e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 157e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung @Override 158e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung public long getItemId(int position) { 159e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung return position; 160e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 161e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 162e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung @Override 163e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung public boolean hasStableIds() { 164e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung return true; 165e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 166e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 167e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung @SuppressLint("NewApi") 168e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung @SuppressWarnings("unchecked") 169e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung @Override 170e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung public View getView(int position, View convertView, ViewGroup parent) { 171e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung MonthView v; 172e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung HashMap<String, Integer> drawingParams = null; 173e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung if (convertView != null) { 174e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung v = (MonthView) convertView; 175e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung // We store the drawing parameters in the view so it can be recycled 176e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung drawingParams = (HashMap<String, Integer>) v.getTag(); 177e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } else { 178e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung v = createMonthView(mContext); 179e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung // Set up the new view 180e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung LayoutParams params = new LayoutParams( 181e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); 182e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung v.setLayoutParams(params); 183e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung v.setClickable(true); 184e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung v.setOnDayClickListener(this); 185e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 186e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung if (drawingParams == null) { 187e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung drawingParams = new HashMap<String, Integer>(); 188e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 189e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung drawingParams.clear(); 190e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 191e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung final int month = position % MONTHS_IN_YEAR; 192e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung final int year = position / MONTHS_IN_YEAR + mController.getMinYear(); 193e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 194e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung int selectedDay = -1; 195e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung if (isSelectedDayInMonth(year, month)) { 196e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung selectedDay = mSelectedDay.day; 197e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 198e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 199e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung // Invokes requestLayout() to ensure that the recycled view is set with the appropriate 200e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung // height/number of weeks before being displayed. 201e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung v.reuse(); 202e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 203e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung drawingParams.put(MonthView.VIEW_PARAMS_SELECTED_DAY, selectedDay); 204e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung drawingParams.put(MonthView.VIEW_PARAMS_YEAR, year); 205e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung drawingParams.put(MonthView.VIEW_PARAMS_MONTH, month); 206e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung drawingParams.put(MonthView.VIEW_PARAMS_WEEK_START, mController.getFirstDayOfWeek()); 207e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung v.setMonthParams(drawingParams); 208e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung v.invalidate(); 209e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung return v; 210e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 211e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 212e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung public abstract MonthView createMonthView(Context context); 213e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 214e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung private boolean isSelectedDayInMonth(int year, int month) { 215e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung return mSelectedDay.year == year && mSelectedDay.month == month; 216e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 217e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 218e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 219e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung @Override 220e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung public void onDayClick(MonthView view, CalendarDay day) { 221e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung if (day != null) { 222e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung onDayTapped(day); 223e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 224e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 225e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung 226e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung /** 227e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * Maintains the same hour/min/sec but moves the day to the tapped day. 228e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * 229e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung * @param day The day that was tapped 230e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung */ 231e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung protected void onDayTapped(CalendarDay day) { 232e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung mController.tryVibrate(); 233e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung mController.onDayOfMonthSelected(day.year, day.month, day.day); 234e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung setSelectedDay(day); 235e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung } 236e668d6b1b77ac4b127f961150e0d0a8a088143d9James Kung} 237