SimpleMonthAdapter.java revision 50eb025c2fea7e364e0be951ce8ba6ca605f901a
1/* 2 * Copyright (C) 2014 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 17package android.widget; 18 19import android.content.Context; 20import android.content.res.ColorStateList; 21import android.view.View; 22import android.view.ViewGroup; 23 24import java.util.Calendar; 25import java.util.HashMap; 26 27/** 28 * An adapter for a list of {@link android.widget.SimpleMonthView} items. 29 */ 30class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayClickListener { 31 private final Calendar mMinDate = Calendar.getInstance(); 32 private final Calendar mMaxDate = Calendar.getInstance(); 33 34 private final Context mContext; 35 private final DatePickerController mController; 36 37 private Calendar mSelectedDay; 38 private ColorStateList mCalendarTextColors; 39 40 public SimpleMonthAdapter(Context context, DatePickerController controller) { 41 mContext = context; 42 mController = controller; 43 44 init(); 45 setSelectedDay(mController.getSelectedDay()); 46 } 47 48 public void setRange(Calendar min, Calendar max) { 49 mMinDate.setTimeInMillis(min.getTimeInMillis()); 50 mMaxDate.setTimeInMillis(max.getTimeInMillis()); 51 52 notifyDataSetInvalidated(); 53 } 54 55 /** 56 * Updates the selected day and related parameters. 57 * 58 * @param day The day to highlight 59 */ 60 public void setSelectedDay(Calendar day) { 61 if (mSelectedDay != day) { 62 mSelectedDay = day; 63 notifyDataSetChanged(); 64 } 65 } 66 67 void setCalendarTextColor(ColorStateList colors) { 68 mCalendarTextColors = colors; 69 } 70 71 /** 72 * Set up the gesture detector and selected time 73 */ 74 protected void init() { 75 mSelectedDay = Calendar.getInstance(); 76 } 77 78 @Override 79 public int getCount() { 80 final int diffYear = mMaxDate.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR); 81 final int diffMonth = mMaxDate.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH); 82 return diffMonth + 12 * diffYear + 1; 83 } 84 85 @Override 86 public Object getItem(int position) { 87 return null; 88 } 89 90 @Override 91 public long getItemId(int position) { 92 return position; 93 } 94 95 @Override 96 public boolean hasStableIds() { 97 return true; 98 } 99 100 @SuppressWarnings("unchecked") 101 @Override 102 public View getView(int position, View convertView, ViewGroup parent) { 103 final SimpleMonthView v; 104 if (convertView != null) { 105 v = (SimpleMonthView) convertView; 106 } else { 107 v = new SimpleMonthView(mContext); 108 109 // Set up the new view 110 final AbsListView.LayoutParams params = new AbsListView.LayoutParams( 111 AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.MATCH_PARENT); 112 v.setLayoutParams(params); 113 v.setClickable(true); 114 v.setOnDayClickListener(this); 115 116 if (mCalendarTextColors != null) { 117 v.setTextColor(mCalendarTextColors); 118 } 119 } 120 121 final int minMonth = mMinDate.get(Calendar.MONTH); 122 final int minYear = mMinDate.get(Calendar.YEAR); 123 final int currentMonth = position + minMonth; 124 final int month = currentMonth % 12; 125 final int year = currentMonth / 12 + minYear; 126 final int selectedDay; 127 if (isSelectedDayInMonth(year, month)) { 128 selectedDay = mSelectedDay.get(Calendar.DAY_OF_MONTH); 129 } else { 130 selectedDay = -1; 131 } 132 133 // Invokes requestLayout() to ensure that the recycled view is set with the appropriate 134 // height/number of weeks before being displayed. 135 v.reuse(); 136 137 final int enabledDayRangeStart; 138 if (minMonth == month && minYear == year) { 139 enabledDayRangeStart = mMinDate.get(Calendar.DAY_OF_MONTH); 140 } else { 141 enabledDayRangeStart = 1; 142 } 143 144 final int enabledDayRangeEnd; 145 if (mMaxDate.get(Calendar.MONTH) == month && mMaxDate.get(Calendar.YEAR) == year) { 146 enabledDayRangeEnd = mMaxDate.get(Calendar.DAY_OF_MONTH); 147 } else { 148 enabledDayRangeEnd = 31; 149 } 150 151 v.setMonthParams(selectedDay, month, year, mController.getFirstDayOfWeek(), 152 enabledDayRangeStart, enabledDayRangeEnd); 153 v.invalidate(); 154 155 return v; 156 } 157 158 private boolean isSelectedDayInMonth(int year, int month) { 159 return mSelectedDay.get(Calendar.YEAR) == year && mSelectedDay.get(Calendar.MONTH) == month; 160 } 161 162 @Override 163 public void onDayClick(SimpleMonthView view, Calendar day) { 164 if (day != null && isCalendarInRange(day)) { 165 onDaySelected(day); 166 } 167 } 168 169 private boolean isCalendarInRange(Calendar value) { 170 return value.compareTo(mMinDate) >= 0 && value.compareTo(mMaxDate) <= 0; 171 } 172 173 /** 174 * Maintains the same hour/min/sec but moves the day to the tapped day. 175 * 176 * @param day The day that was tapped 177 */ 178 private void onDaySelected(Calendar day) { 179 mController.tryVibrate(); 180 mController.onDayOfMonthSelected(day.get(Calendar.YEAR), day.get(Calendar.MONTH), 181 day.get(Calendar.DAY_OF_MONTH)); 182 183 setSelectedDay(day); 184 } 185} 186