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