Java tutorial
/* * 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 com.miuhouse.yourcompany.student.view.widget.date.datepicker; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.support.annotation.IdRes; import android.support.annotation.LayoutRes; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.view.PagerAdapter; import android.util.Log; import android.util.SparseArray; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.miuhouse.yourcompany.student.R; import com.miuhouse.yourcompany.student.view.widget.date.utilities.Config; import com.miuhouse.yourcompany.student.view.widget.date.utilities.SUtils; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * An adapter for a list of {@link SimpleMonthView} items. */ class DayPickerPagerAdapter extends PagerAdapter implements SimpleMonthView.OnRangeClickListener, DayPickerView.OnPageClickListener { private static final String TAG = DayPickerPagerAdapter.class.getSimpleName(); private LinkedHashMap<Integer, List<Integer>> countDate; private List<Integer> monthCount = new ArrayList<>(); 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 SelectedDate mSelectedDay = null; private int mMonthTextAppearance; private int mDayOfWeekTextAppearance; private int mDayTextAppearance; private ColorStateList mCalendarTextColor; private ColorStateList mDaySelectorColor; private final ColorStateList mDayHighlightColor; private DaySelectionEventListener mDaySelectionEventListener; private int mCount; private int mFirstDayOfWeek; private int position; private boolean isFill; // used in resolving start/end dates during range selection private final SelectedDate mTempSelectedDay = new SelectedDate(Calendar.getInstance()); public DayPickerPagerAdapter(@NonNull Context context, @LayoutRes int layoutResId, @IdRes int calendarViewId, DayPickerView mDayPickerView) { mDayPickerView.setOnPageClickListener(this); mInflater = LayoutInflater.from(context); mLayoutResId = layoutResId; mCalendarViewId = calendarViewId; final TypedArray ta = context.obtainStyledAttributes(new int[] { 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; } /** * Sets the selected day. * * @param day the selected day */ public void setSelectedDay(@Nullable SelectedDate day, boolean isReset) { final int[] oldPosition = getPositionsForDay(mSelectedDay); final int[] newPosition = getPositionsForDay(day); boolean shouldClearOldPosition = oldPosition != null; if (isReset) { rangeHashMap.clear(); } // Clear the old position if necessary. if (shouldClearOldPosition) { for (int i = oldPosition[0]; i <= oldPosition[oldPosition.length - 1]; i++) { final ViewHolder oldMonthView = mItems.get(i, null); if (oldMonthView != null && (day.getType() == SelectedDate.Type.SINGLE || day.getType() == SelectedDate.Type.RANGE)) { oldMonthView.calendar.setSelectedDays(-1, -1, SelectedDate.Type.SINGLE, isReset); } } } // Set the new position. if (newPosition != null) { if (newPosition.length == 1) { position = newPosition[0]; final ViewHolder newMonthView = mItems.get(newPosition[0], null); if (newMonthView != null) { final int dayOfMonth = day.getFirstDate().get(Calendar.DAY_OF_MONTH); newMonthView.calendar.setSelectedDays(dayOfMonth, dayOfMonth, SelectedDate.Type.SINGLE, isReset); } } else if (newPosition.length == 2) { position = newPosition[0]; //?? boolean rangeIsInSameMonth = newPosition[0] == newPosition[1]; if (rangeIsInSameMonth) { final ViewHolder newMonthView = mItems.get(newPosition[0], null); if (newMonthView != null) { final int startDayOfMonth = day.getFirstDate().get(Calendar.DAY_OF_MONTH); final int endDayOfMonth = day.getSecondDate().get(Calendar.DAY_OF_MONTH); if (day.getSelecteCalendar() != null) { newMonthView.calendar.setSelectedDays(startDayOfMonth, endDayOfMonth, day.getSelecteCalendar().get(Calendar.DAY_OF_MONTH), SelectedDate.Type.TOGETHER); } else { newMonthView.calendar.setSelectedDays(startDayOfMonth, endDayOfMonth, SelectedDate.Type.RANGE, isReset); } } } else { // Deal with starting month final ViewHolder newMonthViewStart = mItems.get(newPosition[0], null); if (newMonthViewStart != null) { final int startDayOfMonth = day.getFirstDate().get(Calendar.DAY_OF_MONTH); final int endDayOfMonth = day.getFirstDate().getActualMaximum(Calendar.DATE); if (day.getSelecteCalendar() != null) { if (day.getSelecteCalendar().get(Calendar.MONTH) == day.getFirstDate() .get(Calendar.MONTH)) newMonthViewStart.calendar.setSelectedDays(startDayOfMonth, endDayOfMonth, day.getSelecteCalendar().get(Calendar.DAY_OF_MONTH), SelectedDate.Type.TOGETHER); else newMonthViewStart.calendar.setSelectedDays(startDayOfMonth, endDayOfMonth, SelectedDate.Type.RANGE, isReset); } else { newMonthViewStart.calendar.setSelectedDays(startDayOfMonth, endDayOfMonth, SelectedDate.Type.RANGE, isReset); } } for (int i = newPosition[0] + 1; i < newPosition[1]; i++) { final ViewHolder newMonthView = mItems.get(i, null); if (newMonthView != null) { newMonthView.calendar.selectAllDays(); } } // Deal with ending month final ViewHolder newMonthViewEnd = mItems.get(newPosition[1], null); if (newMonthViewEnd != null) { final int startDayOfMonth = day.getSecondDate().getMinimum(Calendar.DATE); final int endDayOfMonth = day.getSecondDate().get(Calendar.DAY_OF_MONTH); // newMonthViewEnd.calendar.setSelectedDays(startDayOfMonth, endDayOfMonth, SelectedDate.Type.RANGE); if (day.getSelecteCalendar() != null) { if (day.getSelecteCalendar().get(Calendar.MONTH) == day.getEndDate() .get(Calendar.MONTH)) newMonthViewEnd.calendar.setSelectedDays(startDayOfMonth, endDayOfMonth, day.getSelecteCalendar().get(Calendar.DAY_OF_MONTH), SelectedDate.Type.TOGETHER); else newMonthViewEnd.calendar.setSelectedDays(startDayOfMonth, endDayOfMonth, SelectedDate.Type.RANGE, isReset); } else { newMonthViewEnd.calendar.setSelectedDays(startDayOfMonth, endDayOfMonth, SelectedDate.Type.RANGE, isReset); } } } } } mSelectedDay = day; } /** * Sets the listener to call when the user selects a day. * * @param listener The listener to call. */ public void setDaySelectionEventListener(DaySelectionEventListener listener) { mDaySelectionEventListener = listener; } @SuppressWarnings("unused") void setCalendarTextColor(ColorStateList calendarTextColor) { mCalendarTextColor = calendarTextColor; } void setDaySelectorColor(ColorStateList selectorColor) { mDaySelectorColor = selectorColor; } void setMonthTextAppearance(int resId) { mMonthTextAppearance = resId; } void setDayOfWeekTextAppearance(int resId) { mDayOfWeekTextAppearance = resId; } int getDayOfWeekTextAppearance() { return mDayOfWeekTextAppearance; } void setDayTextAppearance(int resId) { mDayTextAppearance = resId; } int getDayTextAppearance() { return mDayTextAppearance; } public SimpleMonthView getmItems(int position) { return mItems.get(position).calendar; } @Override public int getCount() { return 2; } @Override public boolean isViewFromObject(View view, Object object) { final ViewHolder holder = (ViewHolder) object; return view == holder.container; } private int getMonthForPosition(int position) { Log.i("TAG", "mMinDate.get(Calendar.Month)=" + mMinDate.get(Calendar.MONTH)); 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); } @SuppressWarnings("unused") 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); return (yearOffset * MONTHS_IN_YEAR + monthOffset); } private int[] getPositionsForDay(@Nullable SelectedDate day) { if (day == null) { return null; } SelectedDate.Type typeOfDay = day.getType(); int[] positions = null; if (typeOfDay == SelectedDate.Type.SINGLE) { positions = new int[1]; final int yearOffset = day.getFirstDate().get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR); final int monthOffset = day.getFirstDate().get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH); positions[0] = yearOffset * MONTHS_IN_YEAR + monthOffset; } else if (typeOfDay == SelectedDate.Type.RANGE || typeOfDay == SelectedDate.Type.TOGETHER) { positions = new int[2]; final int yearOffsetFirstDate = day.getFirstDate().get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR); final int monthOffsetFirstDate = day.getFirstDate().get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH); positions[0] = yearOffsetFirstDate * MONTHS_IN_YEAR + monthOffsetFirstDate; final int yearOffsetSecondDate = day.getSecondDate().get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR); final int monthOffsetSecondDate = day.getSecondDate().get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH); positions[1] = yearOffsetSecondDate * MONTHS_IN_YEAR + monthOffsetSecondDate; } return positions; } @Override public Object instantiateItem(ViewGroup container, int position) { Log.i("TAG", "rangeHashMapdddffff=" + rangeHashMap); final View itemView = mInflater.inflate(mLayoutResId, container, false); Log.i("TAG", "instantiateItem"); final SimpleMonthView v = (SimpleMonthView) itemView.findViewById(mCalendarViewId); v.setOnRangeClickListener(this); 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 = resolveSelectedDayBasedOnType(month, year); 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; } if (Config.DEBUG) { Log.i(TAG, "mSelectedDay.getType(): " + (mSelectedDay != null ? mSelectedDay.getType() : null)); } v.setMonthParams(month, year, mFirstDayOfWeek, enabledDayRangeStart, enabledDayRangeEnd, selectedDay[0], selectedDay[1], mSelectedDay != null ? mSelectedDay.getType() : null, true, position); final ViewHolder holder = new ViewHolder(position, itemView, v); mItems.put(position, holder); container.addView(itemView); if (dateList(month + 1) != null) { v.setCalendar(dateList(month + 1), isFill); } return holder; } @Override public void notifyDataSetChanged() { super.notifyDataSetChanged(); } public void setCalendar(LinkedHashMap<Integer, List<Integer>> countDate, boolean isfill) { isFill = isfill; this.countDate = countDate; for (Integer integer : countDate.keySet()) { monthCount.add(integer); } } public List<Integer> dateList(int month) { if (monthCount.contains(month)) { return countDate.get(month); } else { return null; } } @Override public void destroyItem(ViewGroup container, int position, Object object) { final ViewHolder holder = (ViewHolder) object; container.removeView(holder.container); mItems.remove(position); rangeHashMap.clear(); } @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.getTitle(); } return null; } private final SimpleMonthView.OnDayClickListener mOnDayClickListener = new SimpleMonthView.OnDayClickListener() { @Override public boolean onDayClick(SimpleMonthView view, Calendar day) { if (day != null) { if (mDaySelectionEventListener != null) { return mDaySelectionEventListener.onDaySelected(view, day); } } return true; } }; final Map<Integer, ArrayList<Integer>> rangeHashMap = new HashMap<Integer, ArrayList<Integer>>(); public Map<Integer, ArrayList<Integer>> getRangeHashMap() { return rangeHashMap; } @Override public void onRangeSelected(ArrayList<Integer> calenders, int position) { Log.i("TAG", "onRangeSelected=" + position); ArrayList<Integer> myCalenders = new ArrayList<>(); if (calenders.size() != 0) { myCalenders.addAll(calenders); rangeHashMap.put(position, myCalenders); } else { if (rangeHashMap.containsKey(position)) rangeHashMap.get(position).clear(); } } @Override public void onPageSelected(int position) { if (isFill) { final int month = getMonthForPosition(position); if (monthCount.size() > 0) { if (dateList(month + 1) != null) { getmItems(position).setCalendar(dateList(month + 1), isFill); } } } else { for (Integer o : rangeHashMap.keySet()) { if (o == position) { getmItems(position).setCalendar(rangeHashMap.get(position)); } ; } } } 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 SelectedDate resolveStartDateForRange(int x, int y, int position) { if (position >= 0) { final ViewHolder newMonthView = mItems.get(position, null); if (newMonthView != null) { final int dayOfMonth = newMonthView.calendar.getDayAtLocation(x, y); Log.i("TAG", "dayOfMonth=" + dayOfMonth); Calendar selectedDayStart = newMonthView.calendar.composeDate(dayOfMonth); if (selectedDayStart != null) { Log.i("TAG", "selectedDayStart="); mTempSelectedDay.setDate(selectedDayStart); return mTempSelectedDay; } } } return null; } public SelectedDate resolveEndDateForRange(int x, int y, int position, boolean updateIfNecessary) { if (position >= 0) { final ViewHolder newMonthView = mItems.get(position, null); if (newMonthView != null) { final int dayOfMonth = newMonthView.calendar.getDayAtLocation(x, y); Calendar selectedDayEnd = newMonthView.calendar.composeDate(dayOfMonth); if (selectedDayEnd != null && (!updateIfNecessary || mSelectedDay.getSecondDate().getTimeInMillis() != selectedDayEnd.getTimeInMillis())) { mTempSelectedDay.setSecondDate(selectedDayEnd); return mTempSelectedDay; } } } return null; } private int[] resolveSelectedDayBasedOnType(int month, int year) { if (mSelectedDay == null) { return new int[] { -1, -1 }; } if (mSelectedDay.getType() == SelectedDate.Type.SINGLE) { return resolveSelectedDayForTypeSingle(month, year); } else if (mSelectedDay.getType() == SelectedDate.Type.RANGE) { return resolveSelectedDayForTypeRange(month, year); } return new int[] { -1, -1 }; } private int[] resolveSelectedDayForTypeSingle(int month, int year) { Log.i("TAG", "month=" + month); Log.i("TAG", "mSelectedDay.getFirstDate().get(Calendar.MONTH)=" + mSelectedDay.getFirstDate().get(Calendar.MONTH)); Log.i("TAG", "month=" + month); if (mSelectedDay.getFirstDate().get(Calendar.MONTH) == month && mSelectedDay.getFirstDate().get(Calendar.YEAR) == year) { int resolvedDay = mSelectedDay.getFirstDate().get(Calendar.DAY_OF_MONTH); return new int[] { resolvedDay, resolvedDay }; } return new int[] { -1, -1 }; } private int[] resolveSelectedDayForTypeRange(int month, int year) { // Quan: "year.month" Eg: Feb, 2015 ==> 2015.02, Dec, 2000 ==> 2000.12 float startDateQuan = mSelectedDay.getStartDate().get(Calendar.YEAR) + (mSelectedDay.getStartDate().get(Calendar.MONTH) + 1) / 100f; float endDateQuan = mSelectedDay.getEndDate().get(Calendar.YEAR) + (mSelectedDay.getEndDate().get(Calendar.MONTH) + 1) / 100f; float dateQuan = year + (month + 1) / 100f; if (dateQuan >= startDateQuan && dateQuan <= endDateQuan) { int startDay, endDay; if (dateQuan == startDateQuan) { startDay = mSelectedDay.getStartDate().get(Calendar.DAY_OF_MONTH); } else { startDay = 1; } if (dateQuan == endDateQuan) { endDay = mSelectedDay.getEndDate().get(Calendar.DAY_OF_MONTH); } else { endDay = SUtils.getDaysInMonth(month, year); } return new int[] { startDay, endDay }; } return new int[] { -1, -1 }; } public void onDateRangeSelectionStarted(SelectedDate selectedDate) { if (mDaySelectionEventListener != null) { mDaySelectionEventListener.onDateRangeSelectionStarted(selectedDate); } } public void onDateRangeSelectionEnded(SelectedDate selectedDate) { if (mDaySelectionEventListener != null) { mDaySelectionEventListener.onDateRangeSelectionEnded(selectedDate); } } public void onDateRangeSelectionUpdated(SelectedDate selectedDate) { if (mDaySelectionEventListener != null) { mDaySelectionEventListener.onDateRangeSelectionUpdated(selectedDate); } } public interface DaySelectionEventListener { boolean onDaySelected(SimpleMonthView view, Calendar day); void onDateRangeSelectionStarted(@NonNull SelectedDate selectedDate); void onDateRangeSelectionEnded(@Nullable SelectedDate selectedDate); void onDateRangeSelectionUpdated(@NonNull SelectedDate selectedDate); } }