blob: 24ebb2cd7e664b3a00bf68fc08625c29a6d32dae [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.widget;
import com.android.internal.R;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SimpleMonthView.OnDayClickListener;
import java.util.Calendar;
/**
* An adapter for a list of {@link android.widget.SimpleMonthView} items.
*/
class SimpleMonthAdapter extends BaseAdapter {
private final Calendar mMinDate = Calendar.getInstance();
private final Calendar mMaxDate = Calendar.getInstance();
private final Context mContext;
private Calendar mSelectedDay = Calendar.getInstance();
private ColorStateList mCalendarTextColors = ColorStateList.valueOf(Color.BLACK);
private OnDaySelectedListener mOnDaySelectedListener;
private int mFirstDayOfWeek;
public SimpleMonthAdapter(Context context) {
mContext = context;
}
public void setRange(Calendar min, Calendar max) {
mMinDate.setTimeInMillis(min.getTimeInMillis());
mMaxDate.setTimeInMillis(max.getTimeInMillis());
notifyDataSetInvalidated();
}
public void setFirstDayOfWeek(int firstDayOfWeek) {
mFirstDayOfWeek = firstDayOfWeek;
notifyDataSetInvalidated();
}
public int getFirstDayOfWeek() {
return mFirstDayOfWeek;
}
/**
* Updates the selected day and related parameters.
*
* @param day The day to highlight
*/
public void setSelectedDay(Calendar day) {
mSelectedDay = day;
notifyDataSetChanged();
}
/**
* Sets the listener to call when the user selects a day.
*
* @param listener The listener to call.
*/
public void setOnDaySelectedListener(OnDaySelectedListener listener) {
mOnDaySelectedListener = listener;
}
void setCalendarTextColor(ColorStateList colors) {
mCalendarTextColors = colors;
}
/**
* Sets the text color, size, style, hint color, and highlight color from
* the specified TextAppearance resource. This is mostly copied from
* {@link TextView#setTextAppearance(Context, int)}.
*/
void setCalendarTextAppearance(int resId) {
final TypedArray a = mContext.obtainStyledAttributes(resId, R.styleable.TextAppearance);
final ColorStateList textColor = a.getColorStateList(R.styleable.TextAppearance_textColor);
if (textColor != null) {
mCalendarTextColors = textColor;
}
// TODO: Support font size, etc.
a.recycle();
}
@Override
public int getCount() {
final int diffYear = mMaxDate.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR);
final int diffMonth = mMaxDate.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH);
return diffMonth + 12 * diffYear + 1;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public boolean hasStableIds() {
return true;
}
@SuppressWarnings("unchecked")
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final SimpleMonthView v;
if (convertView != null) {
v = (SimpleMonthView) convertView;
} else {
v = new SimpleMonthView(mContext);
// Set up the new view
final AbsListView.LayoutParams params = new AbsListView.LayoutParams(
AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.MATCH_PARENT);
v.setLayoutParams(params);
v.setClickable(true);
v.setOnDayClickListener(mOnDayClickListener);
if (mCalendarTextColors != null) {
v.setTextColor(mCalendarTextColors);
}
}
final int minMonth = mMinDate.get(Calendar.MONTH);
final int minYear = mMinDate.get(Calendar.YEAR);
final int currentMonth = position + minMonth;
final int month = currentMonth % 12;
final int year = currentMonth / 12 + minYear;
final int selectedDay;
if (isSelectedDayInMonth(year, month)) {
selectedDay = mSelectedDay.get(Calendar.DAY_OF_MONTH);
} else {
selectedDay = -1;
}
// Invokes requestLayout() to ensure that the recycled view is set with the appropriate
// height/number of weeks before being displayed.
v.reuse();
final int enabledDayRangeStart;
if (minMonth == month && minYear == year) {
enabledDayRangeStart = mMinDate.get(Calendar.DAY_OF_MONTH);
} else {
enabledDayRangeStart = 1;
}
final int enabledDayRangeEnd;
if (mMaxDate.get(Calendar.MONTH) == month && mMaxDate.get(Calendar.YEAR) == year) {
enabledDayRangeEnd = mMaxDate.get(Calendar.DAY_OF_MONTH);
} else {
enabledDayRangeEnd = 31;
}
v.setMonthParams(selectedDay, month, year, mFirstDayOfWeek,
enabledDayRangeStart, enabledDayRangeEnd);
v.invalidate();
return v;
}
private boolean isSelectedDayInMonth(int year, int month) {
return mSelectedDay.get(Calendar.YEAR) == year && mSelectedDay.get(Calendar.MONTH) == month;
}
private boolean isCalendarInRange(Calendar value) {
return value.compareTo(mMinDate) >= 0 && value.compareTo(mMaxDate) <= 0;
}
private final OnDayClickListener mOnDayClickListener = new OnDayClickListener() {
@Override
public void onDayClick(SimpleMonthView view, Calendar day) {
if (day != null && isCalendarInRange(day)) {
setSelectedDay(day);
if (mOnDaySelectedListener != null) {
mOnDaySelectedListener.onDaySelected(SimpleMonthAdapter.this, day);
}
}
}
};
public interface OnDaySelectedListener {
public void onDaySelected(SimpleMonthAdapter view, Calendar day);
}
}