344 lines
11 KiB
Java
344 lines
11 KiB
Java
/*
|
|
* Copyright (C) 2015 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 android.annotation.IdRes;
|
|
import android.annotation.LayoutRes;
|
|
import android.annotation.NonNull;
|
|
import android.annotation.Nullable;
|
|
import android.content.Context;
|
|
import android.content.res.ColorStateList;
|
|
import android.content.res.TypedArray;
|
|
import android.graphics.Rect;
|
|
import android.icu.util.Calendar;
|
|
import android.util.SparseArray;
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.SimpleMonthView.OnDayClickListener;
|
|
|
|
import com.android.internal.widget.PagerAdapter;
|
|
|
|
/**
|
|
* An adapter for a list of {@link android.widget.SimpleMonthView} items.
|
|
*/
|
|
class DayPickerPagerAdapter extends PagerAdapter {
|
|
private static final int MONTHS_IN_YEAR = 12;
|
|
|
|
private final Calendar mMinDate = Calendar.getInstance();
|
|
private final Calendar mMaxDate = Calendar.getInstance();
|
|
|
|
private final SparseArray<ViewHolder> mItems = new SparseArray<>();
|
|
|
|
private final LayoutInflater mInflater;
|
|
private final int mLayoutResId;
|
|
private final int mCalendarViewId;
|
|
|
|
private Calendar mSelectedDay = null;
|
|
|
|
private int mMonthTextAppearance;
|
|
private int mDayOfWeekTextAppearance;
|
|
private int mDayTextAppearance;
|
|
|
|
private ColorStateList mCalendarTextColor;
|
|
private ColorStateList mDaySelectorColor;
|
|
private ColorStateList mDayHighlightColor;
|
|
|
|
private OnDaySelectedListener mOnDaySelectedListener;
|
|
|
|
private int mCount;
|
|
private int mFirstDayOfWeek;
|
|
|
|
public DayPickerPagerAdapter(@NonNull Context context, @LayoutRes int layoutResId,
|
|
@IdRes int calendarViewId) {
|
|
mInflater = LayoutInflater.from(context);
|
|
mLayoutResId = layoutResId;
|
|
mCalendarViewId = calendarViewId;
|
|
|
|
final TypedArray ta = context.obtainStyledAttributes(new int[] {
|
|
com.android.internal.R.attr.colorControlHighlight});
|
|
mDayHighlightColor = ta.getColorStateList(0);
|
|
ta.recycle();
|
|
}
|
|
|
|
public void setRange(@NonNull Calendar min, @NonNull Calendar max) {
|
|
mMinDate.setTimeInMillis(min.getTimeInMillis());
|
|
mMaxDate.setTimeInMillis(max.getTimeInMillis());
|
|
|
|
final int diffYear = mMaxDate.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR);
|
|
final int diffMonth = mMaxDate.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH);
|
|
mCount = diffMonth + MONTHS_IN_YEAR * diffYear + 1;
|
|
|
|
// Positions are now invalid, clear everything and start over.
|
|
notifyDataSetChanged();
|
|
}
|
|
|
|
/**
|
|
* Sets the first day of the week.
|
|
*
|
|
* @param weekStart which day the week should start on, valid values are
|
|
* {@link Calendar#SUNDAY} through {@link Calendar#SATURDAY}
|
|
*/
|
|
public void setFirstDayOfWeek(int weekStart) {
|
|
mFirstDayOfWeek = weekStart;
|
|
|
|
// Update displayed views.
|
|
final int count = mItems.size();
|
|
for (int i = 0; i < count; i++) {
|
|
final SimpleMonthView monthView = mItems.valueAt(i).calendar;
|
|
monthView.setFirstDayOfWeek(weekStart);
|
|
}
|
|
}
|
|
|
|
public int getFirstDayOfWeek() {
|
|
return mFirstDayOfWeek;
|
|
}
|
|
|
|
public boolean getBoundsForDate(Calendar day, Rect outBounds) {
|
|
final int position = getPositionForDay(day);
|
|
final ViewHolder monthView = mItems.get(position, null);
|
|
if (monthView == null) {
|
|
return false;
|
|
} else {
|
|
final int dayOfMonth = day.get(Calendar.DAY_OF_MONTH);
|
|
return monthView.calendar.getBoundsForDay(dayOfMonth, outBounds);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the selected day.
|
|
*
|
|
* @param day the selected day
|
|
*/
|
|
public void setSelectedDay(@Nullable Calendar day) {
|
|
final int oldPosition = getPositionForDay(mSelectedDay);
|
|
final int newPosition = getPositionForDay(day);
|
|
|
|
// Clear the old position if necessary.
|
|
if (oldPosition != newPosition && oldPosition >= 0) {
|
|
final ViewHolder oldMonthView = mItems.get(oldPosition, null);
|
|
if (oldMonthView != null) {
|
|
oldMonthView.calendar.setSelectedDay(-1);
|
|
}
|
|
}
|
|
|
|
// Set the new position.
|
|
if (newPosition >= 0) {
|
|
final ViewHolder newMonthView = mItems.get(newPosition, null);
|
|
if (newMonthView != null) {
|
|
final int dayOfMonth = day.get(Calendar.DAY_OF_MONTH);
|
|
newMonthView.calendar.setSelectedDay(dayOfMonth);
|
|
}
|
|
}
|
|
|
|
mSelectedDay = day;
|
|
}
|
|
|
|
/**
|
|
* 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 calendarTextColor) {
|
|
mCalendarTextColor = calendarTextColor;
|
|
notifyDataSetChanged();
|
|
}
|
|
|
|
void setDaySelectorColor(ColorStateList selectorColor) {
|
|
mDaySelectorColor = selectorColor;
|
|
notifyDataSetChanged();
|
|
}
|
|
|
|
void setMonthTextAppearance(int resId) {
|
|
mMonthTextAppearance = resId;
|
|
notifyDataSetChanged();
|
|
}
|
|
|
|
void setDayOfWeekTextAppearance(int resId) {
|
|
mDayOfWeekTextAppearance = resId;
|
|
notifyDataSetChanged();
|
|
}
|
|
|
|
int getDayOfWeekTextAppearance() {
|
|
return mDayOfWeekTextAppearance;
|
|
}
|
|
|
|
void setDayTextAppearance(int resId) {
|
|
mDayTextAppearance = resId;
|
|
notifyDataSetChanged();
|
|
}
|
|
|
|
int getDayTextAppearance() {
|
|
return mDayTextAppearance;
|
|
}
|
|
|
|
@Override
|
|
public int getCount() {
|
|
return mCount;
|
|
}
|
|
|
|
@Override
|
|
public boolean isViewFromObject(View view, Object object) {
|
|
final ViewHolder holder = (ViewHolder) object;
|
|
return view == holder.container;
|
|
}
|
|
|
|
private int getMonthForPosition(int position) {
|
|
return (position + mMinDate.get(Calendar.MONTH)) % MONTHS_IN_YEAR;
|
|
}
|
|
|
|
private int getYearForPosition(int position) {
|
|
final int yearOffset = (position + mMinDate.get(Calendar.MONTH)) / MONTHS_IN_YEAR;
|
|
return yearOffset + mMinDate.get(Calendar.YEAR);
|
|
}
|
|
|
|
private int getPositionForDay(@Nullable Calendar day) {
|
|
if (day == null) {
|
|
return -1;
|
|
}
|
|
|
|
final int yearOffset = day.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR);
|
|
final int monthOffset = day.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH);
|
|
final int position = yearOffset * MONTHS_IN_YEAR + monthOffset;
|
|
return position;
|
|
}
|
|
|
|
@Override
|
|
public Object instantiateItem(ViewGroup container, int position) {
|
|
final View itemView = mInflater.inflate(mLayoutResId, container, false);
|
|
|
|
final SimpleMonthView v = itemView.findViewById(mCalendarViewId);
|
|
v.setOnDayClickListener(mOnDayClickListener);
|
|
v.setMonthTextAppearance(mMonthTextAppearance);
|
|
v.setDayOfWeekTextAppearance(mDayOfWeekTextAppearance);
|
|
v.setDayTextAppearance(mDayTextAppearance);
|
|
|
|
if (mDaySelectorColor != null) {
|
|
v.setDaySelectorColor(mDaySelectorColor);
|
|
}
|
|
|
|
if (mDayHighlightColor != null) {
|
|
v.setDayHighlightColor(mDayHighlightColor);
|
|
}
|
|
|
|
if (mCalendarTextColor != null) {
|
|
v.setMonthTextColor(mCalendarTextColor);
|
|
v.setDayOfWeekTextColor(mCalendarTextColor);
|
|
v.setDayTextColor(mCalendarTextColor);
|
|
}
|
|
|
|
final int month = getMonthForPosition(position);
|
|
final int year = getYearForPosition(position);
|
|
|
|
final int selectedDay;
|
|
if (mSelectedDay != null && mSelectedDay.get(Calendar.MONTH) == month && mSelectedDay.get(
|
|
Calendar.YEAR) == year) {
|
|
selectedDay = mSelectedDay.get(Calendar.DAY_OF_MONTH);
|
|
} else {
|
|
selectedDay = -1;
|
|
}
|
|
|
|
final int enabledDayRangeStart;
|
|
if (mMinDate.get(Calendar.MONTH) == month && mMinDate.get(Calendar.YEAR) == 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);
|
|
|
|
final ViewHolder holder = new ViewHolder(position, itemView, v);
|
|
mItems.put(position, holder);
|
|
|
|
container.addView(itemView);
|
|
|
|
return holder;
|
|
}
|
|
|
|
@Override
|
|
public void destroyItem(ViewGroup container, int position, Object object) {
|
|
final ViewHolder holder = (ViewHolder) object;
|
|
container.removeView(holder.container);
|
|
|
|
mItems.remove(position);
|
|
}
|
|
|
|
@Override
|
|
public int getItemPosition(Object object) {
|
|
final ViewHolder holder = (ViewHolder) object;
|
|
return holder.position;
|
|
}
|
|
|
|
@Override
|
|
public CharSequence getPageTitle(int position) {
|
|
final SimpleMonthView v = mItems.get(position).calendar;
|
|
if (v != null) {
|
|
return v.getMonthYearLabel();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
SimpleMonthView getView(Object object) {
|
|
if (object == null) {
|
|
return null;
|
|
}
|
|
final ViewHolder holder = (ViewHolder) object;
|
|
return holder.calendar;
|
|
}
|
|
|
|
private final OnDayClickListener mOnDayClickListener = new OnDayClickListener() {
|
|
@Override
|
|
public void onDayClick(SimpleMonthView view, Calendar day) {
|
|
if (day != null) {
|
|
setSelectedDay(day);
|
|
|
|
if (mOnDaySelectedListener != null) {
|
|
mOnDaySelectedListener.onDaySelected(DayPickerPagerAdapter.this, day);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
private static class ViewHolder {
|
|
public final int position;
|
|
public final View container;
|
|
public final SimpleMonthView calendar;
|
|
|
|
public ViewHolder(int position, View container, SimpleMonthView calendar) {
|
|
this.position = position;
|
|
this.container = container;
|
|
this.calendar = calendar;
|
|
}
|
|
}
|
|
|
|
public interface OnDaySelectedListener {
|
|
public void onDaySelected(DayPickerPagerAdapter view, Calendar day);
|
|
}
|
|
}
|