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