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