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