自定义日历开发

还就没写博客了,最近写了个自定义日历,分享下;

一.某月的日历信息

private static class CalendarInfo {
        private Paint mPaint;
        private Paint bgPaint;
        /**
         * 各部分高度
         */
        private float monthHeight, dayHeight, oneHeight;

        private Date month; //当前的月份
        private int yearValue;    //当前年
        private int monthValue;    //当前月
        private int day;    //当前日期
        private boolean isCurrentMonth;       //展示的月份是否是当前月
        private int dayOfMonth;    //月份天数
        private int firstIndex;    //当月第一天位置索引
        private int firstLineNum, lastLineNum; //第一行、最后一行能展示多少日期
        private int lineNum;      //日期行数

        private Map<String, DayInfo> dayWeekMap;

        public CalendarInfo() {
            dayWeekMap = new HashMap<>();
        }

        public void setDayWeekMapIndex(CustomizeCalendarView customizeCalendar, int day, int week) {
            DayInfo dayInfo = new DayInfo(customizeCalendar.getDayStr(getMonth(), day), getYearValue(), getMonthValue(), day, week);
            this.dayWeekMap.put(dayInfo.getDate(), dayInfo);
        }

        public boolean isSunday(CustomizeCalendarView customizeCalendar, int day) {
            return dayWeekMap.get(customizeCalendar.getDayStr(getMonth(), day)).getWeek() == 0;
        }

        public boolean isSaturday(CustomizeCalendarView customizeCalendar, int day) {
            return dayWeekMap.get(customizeCalendar.getDayStr(getMonth(), day)).getWeek() == 6;
        }

        public void setPaint(Paint paint) {
            mPaint = paint;
        }

        public Paint getPaint() {
            return mPaint;
        }

        public void setBgPaint(Paint bgPaint) {
            this.bgPaint = bgPaint;
        }

        public Paint getBgPaint() {
            return bgPaint;
        }

        public void setMonthHeight(float monthHeight) {
            this.monthHeight = monthHeight;
        }

        public float getMonthHeight() {
            return monthHeight;
        }

        public void setDayHeight(float dayHeight) {
            this.dayHeight = dayHeight;
        }

        public float getDayHeight() {
            return dayHeight;
        }

        public void setOneHeight(float oneHeight) {
            this.oneHeight = oneHeight;
        }

        public float getOneHeight() {
            return oneHeight;
        }

        public void setMonth(Date month) {
            this.month = month;
        }

        public Date getMonth() {
            return month;
        }

        public void setYearValue(int yearValue) {
            this.yearValue = yearValue;
        }

        public int getYearValue() {
            return yearValue;
        }

        public void setMonthValue(int monthValue) {
            this.monthValue = monthValue;
        }

        public int getMonthValue() {
            return monthValue;
        }

        public void setDay(int day) {
            this.day = day;
        }

        public int getDay() {
            return day;
        }

        public void setCurrentMonth(boolean currentMonth) {
            isCurrentMonth = currentMonth;
        }

        public boolean isCurrentMonth() {
            return isCurrentMonth;
        }

        public void setDayOfMonth(int dayOfMonth) {
            this.dayOfMonth = dayOfMonth;
        }

        public int getDayOfMonth() {
            return dayOfMonth;
        }

        public void setFirstIndex(int firstIndex) {
            this.firstIndex = firstIndex;
        }

        public int getFirstIndex() {
            return firstIndex;
        }

        public void setFirstLineNum(int firstLineNum) {
            this.firstLineNum = firstLineNum;
        }

        public int getFirstLineNum() {
            return firstLineNum;
        }

        public void setLastLineNum(int lastLineNum) {
            this.lastLineNum = lastLineNum;
        }

        public int getLastLineNum() {
            return lastLineNum;
        }

        public void setLineNum(int lineNum) {
            this.lineNum = lineNum;
        }

        public int getLineNum() {
            return lineNum;
        }
    }

二.某日信息 

private static class DayInfo {
        private String date; //时期
        private int year; //年
        private int month; //月
        private int day; //日
        private int week; //第几周

        public DayInfo(String date, int year, int month, int day, int week) {
            this.date = date;
            this.year = year;
            this.month = month;
            this.day = day;
            this.week = week;
        }

        public String getDate() {
            return date;
        }

        public void setDate(String date) {
            this.date = date;
        }

        public int getYear() {
            return year;
        }

        public void setYear(int year) {
            this.year = year;
        }

        public int getMonth() {
            return month;
        }

        public void setMonth(int month) {
            this.month = month;
        }

        public int getDay() {
            return day;
        }

        public void setDay(int day) {
            this.day = day;
        }

        public int getWeek() {
            return week;
        }

        public void setWeek(int week) {
            this.week = week;
        }
    }

三.选择日期数据

public static class SelectDay {
        public final static String SINGLE = "single";
        public final static String DOUBLE = "double";
        public final static String REMOVE = "remove";

        public SelectDay(Date startDate) {
            setClickType(SINGLE);
            setStartDate(startDate);
            setDaySelectMap(setSelectDay(getStartDate()));
        }

        public SelectDay(Date sDate, Date eDate, boolean isRemove) {
            setClickType(REMOVE);
            setRemove(isRemove);
            setStartDate(sDate);
            setEndDate(eDate);
            setDaySelectMap(setSelectDay());
        }

        public SelectDay(Date startDate, Date endDate) {
            setClickType(DOUBLE);
            if (compareDate(startDate, endDate) < 0) {
                setStartDate(startDate);
                setEndDate(endDate);
            } else if (compareDate(startDate, endDate) > 0) {
                setStartDate(endDate);
                setEndDate(startDate);
            }
            setDaySelectMap(setSelectDay());
        }

        private String clickType;
        private boolean isRemove;

        public void setClickType(String clickType) {
            this.clickType = clickType;
        }

        public String getClickType() {
            return clickType;
        }

        public void setRemove(boolean remove) {
            isRemove = remove;
        }

        public boolean isRemove() {
            return isRemove;
        }

        private Date startDate, endDate;

        public void setStartDate(Date startDate) {
            this.startDate = startDate;
        }

        public Date getStartDate() {
            return startDate;
        }

        public void setEndDate(Date endDate) {
            this.endDate = endDate;
        }

        public Date getEndDate() {
            return endDate;
        }

        private Map<String, Integer> daySelectMap;

        public Map<String, Integer> getDaySelectMap() {
            return daySelectMap;
        }

        public void setDaySelectMap(Map<String, Integer> daySelectMap) {
            this.daySelectMap = daySelectMap;
        }

        public String getDaySelectKey() {
            return getDaySelectMap().keySet().toString();
        }

        public Date getStartDay() {
            if (null != daySelectMap && daySelectMap.values().size() > 0) {
                Set set = daySelectMap.keySet();
                Iterator iter = set.iterator();
                while (iter.hasNext()) {
                    String key = (String) iter.next();
                    if (daySelectMap.get(key) == 1) {
                        return strToDate(key);
                    }
                }
            }
            return null;
        }

        public Date getEndDay() {
            if (null != daySelectMap && daySelectMap.values().size() > 0) {
                Set set = daySelectMap.keySet();
                Iterator iter = set.iterator();
                while (iter.hasNext()) {
                    String key = (String) iter.next();
                    if (daySelectMap.get(key) == 2) {
                        return strToDate(key);
                    }
                }
            }
            return null;
        }

        /**
         * 调用方法
         */
        private Map<String, Integer> setSelectDay() {
            return setSelectDay(getStartDate(), getEndDate());
        }

        private Map<String, Integer> setSelectDay(Date start) {
            return setSelectDay(start, start);
        }

        private Map<String, Integer> setSelectDay(Date start, Date end) {
            if (TextUtils.equals(DOUBLE, getClickType())) {
                return doubleSelectDay(start, end);
            } else if (TextUtils.equals(SINGLE, getClickType())) {
                return singleSelectDay(start);
            } else {
                if (isRemove()) {
                    return removeSelectDay(start, end);
                } else {
                    return doubleSelectDay(start, end);
                }
            }
        }

        private Map<String, Integer> singleSelectDay(Date date){
            Map<String, Integer> daySelectMap = new HashMap<>();
            daySelectMap.put(getDayStr(date), DAY_START_SELECT);
            return daySelectMap;
        }

        private Map<String, Integer> doubleSelectDay(Date start, Date end){
            Map<String, Integer> daySelectMap = new HashMap<>();
            int numberDay = (int) dateDiff(start, end) + 1;
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(start);
            for (int i = 0; i < numberDay; i++) {
                int day = calendar.get(Calendar.DAY_OF_MONTH);
                int dayOfMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
                int dayIndex = day + i;
                if (i == 0) {
                    daySelectMap.put(getMonthAndDayStr(start, day), DAY_START_SELECT);
                } else if (i == numberDay - 1) {
                    if (dayIndex <= dayOfMonth) {
                        daySelectMap.put(getMonthAndDayStr(start, dayIndex), DAY_END_SELECT);
                    } else {
                        daySelectMap.put(getMonthAndDayStr(end, dayIndex - dayOfMonth), DAY_END_SELECT);
                    }
                } else {
                    if (dayIndex <= dayOfMonth) {
                        daySelectMap.put(getMonthAndDayStr(start, dayIndex), DAY_SELECT);
                    } else {
                        daySelectMap.put(getMonthAndDayStr(end, dayIndex - dayOfMonth), DAY_SELECT);
                    }
                }
            }
            return daySelectMap;
        }

        private Map<String, Integer> removeSelectDay(Date start, Date end){
            Map<String, Integer> daySelectMap = new HashMap<>();
            int numberDay = (int) dateDiff(start, end);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(start);
            for (int i = 0; i < numberDay; i++) {
                int day = calendar.get(Calendar.DAY_OF_MONTH);
                int dayOfMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
                int dayIndex = day + i;
                if (i == 0) {
                    daySelectMap.put(getMonthAndDayStr(start, day), DAY_START_SELECT);
                } else if (i == numberDay - 1) {
                    if (dayIndex <= dayOfMonth) {
                        daySelectMap.put(getMonthAndDayStr(start, dayIndex), DAY_SELECT);
                    } else {
                        daySelectMap.put(getMonthAndDayStr(end, dayIndex - dayOfMonth), DAY_SELECT);
                    }
                    daySelectMap.put(getDayStr(end), DAY_END_SELECT);
                } else {
                    if (dayIndex <= dayOfMonth) {
                        daySelectMap.put(getMonthAndDayStr(start, dayIndex), DAY_SELECT);
                    } else {
                        daySelectMap.put(getMonthAndDayStr(end, dayIndex - dayOfMonth), DAY_SELECT);
                    }
                }
            }
            return daySelectMap;
        }

        private int compareDate(Date dt1, Date dt2) {
            if (dt1.getTime() > dt2.getTime()) {
                return 1;
            } else if (dt1.getTime() < dt2.getTime()) {
                return -1;
            } else {
                return 0;
            }
        }

        private long dateDiff(Date startTime, Date endTime) {
            long nd = 1000 * 24 * 60 * 60;// 一天的毫秒数
            long diff = endTime.getTime() - startTime.getTime();
            long day = diff / nd;// 计算差多少天
            if (day >= 1) {
                return day;
            } else {
                if (day == 0) {
                    return 1;
                } else {
                    return 0;
                }
            }
        }

        private Date strToDate(String str) {
            try {
                SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日");
                return df.parse(str);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }

        private String getDayStr(Date date) {
            SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日");
            return df.format(date);
        }

        private String getMonthAndDayStr(Date date, int day) {
            SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月");
            return String.format("%s%02d日", df.format(date), day);
        }

        private Date maxDate(List<Long> dates) {
            long max = dates.get(0);//把数组第一个数赋值给max和min
            for (int i = 0; i < dates.size(); i++) {//依次判断剩下每个数
                if (dates.get(i) > max) max = dates.get(i);//如果该数大于max,把其赋值给max
            }
            return new Date(max);
        }

        private Date minDate(List<Long> dates) {
            long min = dates.get(0);//把数组第一个数赋值给max和min
            for (int i = 0; i < dates.size(); i++) {//依次判断剩下每个数
                if (dates.get(i) < min) min = dates.get(i);//如果该数小于min,把其赋值给min
            }
            return new Date(min);
        }
    }

四.控件画布

@Override
    protected void onDraw(Canvas canvas) {
        drawWeek(canvas);
        drawOtherDate(canvas);
        drawCurrentDate(canvas);
    }

    /**
     * 绘制绘制星期
     */
    private void drawWeek(Canvas canvas) {
        //背景
        bgWeekPaint.setColor(mBgWeek);
        RectF rect = new RectF(0, 0, getWidth(), weekHeight);
        canvas.drawRect(rect, bgWeekPaint);
        //绘制星期:七天
        mWeekPaint.setTextSize(mWeekSize);
        mWeekPaint.setColor(mWeekColor);
        for (int i = 0; i < weekText.length; i++) {
            int len = (int) FontUtil.getFontlength(mWeekPaint, weekText[i]);
            int x = i * columnWidth + (columnWidth - len) / 2;
            canvas.drawText(weekText[i], x, FontUtil.getFontLeading(mWeekPaint) + mTextSpac, mWeekPaint);
        }
    }

    /** 两个月 */
    private void drawOtherDate(Canvas canvas) {
        drawOtherMonth(canvas);
        drawOtherDay(canvas);
    }

    /**
     * 绘制上个月的月份
     */
    private void drawOtherMonth(Canvas canvas) {
        //背景
        otherCalendarInfo.getBgPaint().setColor(mBgMonth);
        RectF rect = new RectF(0, weekHeight, getWidth(), weekHeight + otherCalendarInfo.getMonthHeight());
        canvas.drawRect(rect, otherCalendarInfo.getBgPaint());
        //绘制月份
        otherCalendarInfo.getPaint().setTextSize(mMonthSize);
        otherCalendarInfo.getPaint().setColor(mMonthColor);
        float textLen = FontUtil.getFontlength(otherCalendarInfo.getPaint(), getMonthStr(otherCalendarInfo.getMonth()));
        float textStart = (getWidth() - textLen) / 2;
        canvas.drawText(getMonthStr(otherCalendarInfo.getMonth()), textStart, weekHeight + FontUtil.getFontLeading(otherCalendarInfo.getPaint()) + mTextSpac, otherCalendarInfo.getPaint());
    }

    /**
     * 绘制上个月的日期和次数
     */
    private void drawOtherDay(Canvas canvas) {
        float top = weekHeight + otherCalendarInfo.getMonthHeight();
        //行
        for (int line = 0; line < otherCalendarInfo.getLineNum(); line++) {
            if (line == 0) {
                //第一行
                drawOtherDayAndPre(canvas, top, otherCalendarInfo.getFirstLineNum(), 0, otherCalendarInfo.getFirstIndex());
            } else if (line == otherCalendarInfo.getLineNum() - 1) {
                //最后一行
                top += otherCalendarInfo.getOneHeight();
                drawOtherDayAndPre(canvas, top, otherCalendarInfo.getLastLineNum(), otherCalendarInfo.getFirstLineNum() + (line - 1) * 7, 0);
            } else {
                //满行
                top += otherCalendarInfo.getOneHeight();
                drawOtherDayAndPre(canvas, top, 7, otherCalendarInfo.getFirstLineNum() + (line - 1) * 7, 0);
            }
        }
    }

    /**
     * 绘制某一行的日期
     */
    private void drawOtherDayAndPre(Canvas canvas, float top, int count, int overDay, int startIndex) {
        //背景
        float topPre = top + otherCalendarInfo.getDayHeight();
        otherCalendarInfo.getBgPaint().setColor(mBgDay);
        RectF rect = new RectF(0, top, getWidth(), topPre);
        canvas.drawRect(rect, otherCalendarInfo.getBgPaint());
        otherCalendarInfo.getBgPaint().setColor(mBgDay);
        rect = new RectF(0, topPre, getWidth(), topPre + mTextSpac + otherCalendarInfo.getDayHeight());
        canvas.drawRect(rect, otherCalendarInfo.getBgPaint());

        otherCalendarInfo.getPaint().setTextSize(mDaySize);
        float dayTextLeading = FontUtil.getFontLeading(otherCalendarInfo.getPaint()) + mTextSpac;
        for (int i = 0; i < count; i++) {
            int left = (startIndex + i) * columnWidth;
            int day = (overDay + i + 1);
            otherCalendarInfo.setDayWeekMapIndex(this, day, startIndex + i);
            otherCalendarInfo.getPaint().setTextSize(mDaySize);
            if (yesSelectDay < 0) {
                if (day <= (otherCalendarInfo.getDayOfMonth() + yesSelectDay)) {
                    otherCalendarInfo.getPaint().setColor(mDayTranColor);
                    dayEnabledMap.put(getDayStr(otherCalendarInfo.getMonth(), day), false);
                } else {
                    if (selectStartHeight == 0) {
                        selectStartHeight = top;
                    }
                    otherCalendarInfo.getPaint().setColor(mDayColor);
                    dayEnabledMap.put(getDayStr(otherCalendarInfo.getMonth(), day), true);
                }
            } else {
                otherCalendarInfo.getPaint().setColor(mDayTranColor);
                dayEnabledMap.put(getDayStr(otherCalendarInfo.getMonth(), day), false);
            }

            if (dayEnabledMap.get(getDayStr(otherCalendarInfo.getMonth(), day))) {
                otherCalendarInfo.getPaint().setColor(mSelectDayColor);
                if (null != mSelectDay && mSelectDay.getDaySelectKey().contains(getDayStr(otherCalendarInfo.getMonth(), day))) {
                    if (TextUtils.equals(SelectDay.SINGLE, mSelectDay.getClickType())) {
                        otherCalendarInfo.getPaint().setColor(mSelectDayColor);
                        drawSelectDate(canvas, otherCalendarInfo, left, top, mBgSelectDay, true);
                    } else if (mSelectDay.getDaySelectMap().get(getDayStr(otherCalendarInfo.getMonth(), day)) == DAY_START_SELECT) {
                        /*if (i == count-1) {
                            drawSelectDate(canvas, otherCalendarInfo, left, top, mBgSelectDay, true);
                        } else {
                            drawStartDate(canvas, otherCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectDay);
                        }*/
                        drawStartDate(canvas, otherCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectDay, true);
                    } else if (mSelectDay.getDaySelectMap().get(getDayStr(otherCalendarInfo.getMonth(), day)) == DAY_END_SELECT) {
                        /*if (i == 0) {
                            drawSelectDate(canvas, otherCalendarInfo, left, top, mBgSelectDay, true);
                        } else {
                            drawEndDate(canvas, otherCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectDay);
                        }*/
                        drawEndDate(canvas, otherCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectDay, true);
                    } else {
                        /*if (i == 0 && i == count-1) {
                            drawSelectDate(canvas, otherCalendarInfo, left, top, mBgSelectMiddleDayColor2, true);
                        } else if (i == count-1) {
                            drawEndDate(canvas, otherCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectMiddleDayColor2, false);
                        } else if (i == 0) {
                            drawStartDate(canvas, otherCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectMiddleDayColor2, false);
                        } else {
                            drawSelectDate(canvas, otherCalendarInfo, left, top, mBgSelectMiddleDayColor1, false);
                        }*/
                        drawSelectDate(canvas, otherCalendarInfo, left, top, mBgSelectMiddleDayColor1, false);
                    }
                } else {
                    if (selectDay == day) {
                        drawSelectDate(canvas, otherCalendarInfo, left, top, mBgSelectDay, true);
                    }
                }
            }

            int len = (int) FontUtil.getFontlength(otherCalendarInfo.getPaint(), day + "");
            int x = left + (columnWidth - len) / 2;
            canvas.drawText(day + "", x, top + dayTextLeading, otherCalendarInfo.getPaint());
        }
    }

    private void drawCurrentDate(Canvas canvas) {
        drawCurrentMonth(canvas);
        drawCurrentDay(canvas);
    }

    /**
     * 绘制月份
     */
    private void drawCurrentMonth(Canvas canvas) {
        //背景
        currentCalendarInfo.getBgPaint().setColor(mBgMonth);
        RectF rect = new RectF(0, dateHeight, getWidth(), dateHeight + currentCalendarInfo.getMonthHeight());
        canvas.drawRect(rect, currentCalendarInfo.getBgPaint());
        //绘制月份
        currentCalendarInfo.getPaint().setTextSize(mMonthSize);
        currentCalendarInfo.getPaint().setColor(mMonthColor);
        float textLen = FontUtil.getFontlength(currentCalendarInfo.getPaint(), getMonthStr(currentCalendarInfo.getMonth()));
        float textStart = (getWidth() - textLen) / 2;
        canvas.drawText(getMonthStr(currentCalendarInfo.getMonth()), textStart, dateHeight + FontUtil.getFontLeading(currentCalendarInfo.getPaint()) + mTextSpac, currentCalendarInfo.getPaint());
    }

    /**
     * 绘制日期和次数
     */
    private void drawCurrentDay(Canvas canvas) {
        float top = dateHeight + currentCalendarInfo.getMonthHeight();
        //行
        for (int line = 0; line < currentCalendarInfo.getLineNum(); line++) {
            if (line == 0) {
                //第一行
                drawCurrentDayAndPre(canvas, top, currentCalendarInfo.getFirstLineNum(), 0, currentCalendarInfo.getFirstIndex());
            } else if (line == currentCalendarInfo.getLineNum() - 1) {
                //最后一行
                top += currentCalendarInfo.getOneHeight();
                drawCurrentDayAndPre(canvas, top, currentCalendarInfo.getLastLineNum(), currentCalendarInfo.getFirstLineNum() + (line - 1) * 7, 0);
            } else {
                //满行
                top += currentCalendarInfo.getOneHeight();
                drawCurrentDayAndPre(canvas, top, 7, currentCalendarInfo.getFirstLineNum() + (line - 1) * 7, 0);
            }
        }
    }

    /**
     * 绘制某一行的日期
     */
    private void drawCurrentDayAndPre(Canvas canvas, float top, int count, int overDay, int startIndex) {
        //背景
        float topPre = top + currentCalendarInfo.getDayHeight();
        currentCalendarInfo.getBgPaint().setColor(mBgDay);
        RectF rect = new RectF(0, top, getWidth(), topPre);
        canvas.drawRect(rect, currentCalendarInfo.getBgPaint());

        currentCalendarInfo.getBgPaint().setColor(mBgDay);
        rect = new RectF(0, topPre, getWidth(), topPre + mTextSpac + currentCalendarInfo.getDayHeight());
        canvas.drawRect(rect, currentCalendarInfo.getBgPaint());

        currentCalendarInfo.getPaint().setTextSize(mDaySize);
        float dayTextLeading = FontUtil.getFontLeading(currentCalendarInfo.getPaint()) + mTextSpac;
        for (int i = 0; i < count; i++) {
            int left = (startIndex + i) * columnWidth;
            int day = (overDay + i + 1);
            currentCalendarInfo.setDayWeekMapIndex(this, day, startIndex + i);
            currentCalendarInfo.getPaint().setTextSize(mDaySize);
            if (yesSelectDay > 0) {
                if (day == yesSelectDay) {
                    currentCalendarInfo.getPaint().setColor(mDayTranColor);
                    dayEnabledMap.put(getDayStr(currentCalendarInfo.getMonth(), day), false);
                } else {
                    if (selectStartHeight == 0) {
                        selectStartHeight = top;
                    }
                    currentCalendarInfo.getPaint().setColor(mDayColor);
                    dayEnabledMap.put(getDayStr(currentCalendarInfo.getMonth(), day), true);
                }
            } else {
                if (day > currentDay) {
                    currentCalendarInfo.getPaint().setColor(mDayTranColor);
                    dayEnabledMap.put(getDayStr(currentCalendarInfo.getMonth(), day), false);
                } else {
                    currentCalendarInfo.getPaint().setColor(mDayColor);
                    dayEnabledMap.put(getDayStr(currentCalendarInfo.getMonth(), day), true);
                }
            }

            if (dayEnabledMap.get(getDayStr(currentCalendarInfo.getMonth(), day))) {
                currentCalendarInfo.getPaint().setColor(mSelectDayColor);
                if (null != mSelectDay && mSelectDay.getDaySelectKey().contains(getDayStr(currentCalendarInfo.getMonth(), day))) {
                    if (TextUtils.equals(SelectDay.SINGLE, mSelectDay.getClickType())) {
                        currentCalendarInfo.getBgPaint().setColor(mBgSelectDay);
                        drawSelectDate(canvas, currentCalendarInfo, left, top, mBgSelectDay, true);
                    } else {
                        if (mSelectDay.getDaySelectMap().get(getDayStr(currentCalendarInfo.getMonth(), day)) == DAY_START_SELECT) {
                            /*if (i == count-1) {
                                drawSelectDate(canvas, currentCalendarInfo, left, top, mBgSelectDay, true);
                            } else {
                                drawStartDate(canvas, currentCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectDay);
                            }*/
                            drawStartDate(canvas, currentCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectDay, true);
                        } else if (mSelectDay.getDaySelectMap().get(getDayStr(currentCalendarInfo.getMonth(), day)) == DAY_END_SELECT) {
                            /*if (i == 0) {
                                drawSelectDate(canvas, currentCalendarInfo, left, top, mBgSelectDay, true);
                            } else {
                                drawEndDate(canvas, currentCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectDay);
                            }*/
                            drawEndDate(canvas, currentCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectDay, true);
                        } else {
                            /*if (i == 0 && i == count-1) {
                                drawSelectDate(canvas, currentCalendarInfo, left, top, mBgSelectMiddleDayColor2, true);
                            } else if (i == count-1) {
                                drawEndDate(canvas, currentCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectMiddleDayColor2, false);
                            } else if (i == 0) {
                                drawStartDate(canvas, currentCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectMiddleDayColor2, false);
                            } else {
                                drawSelectDate(canvas, currentCalendarInfo, left, top, mBgSelectMiddleDayColor1, false);
                            }*/
                            drawSelectDate(canvas, currentCalendarInfo, left, top, mBgSelectMiddleDayColor1, false);
                        }
                    }
                } else {
                    if (selectDay == day) {
                        drawSelectDate(canvas, currentCalendarInfo, left, top, mBgSelectDay, true);
                        if (selectEndHeight == 0) {
                            selectEndHeight = top;
                        }
                    }
                }
            }

            int len = (int) FontUtil.getFontlength(currentCalendarInfo.getPaint(), day + "");
            int x = left + (columnWidth - len) / 2;
            canvas.drawText(day + "", x, top + dayTextLeading, currentCalendarInfo.getPaint());
        }
    }

    public int sp2px(float spValue) {
        final float fontScale = getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }

    public static class FontUtil {

        /**
         * @param paint
         * @param str
         * @return 返回指定笔和指定字符串的长度
         */
        public static float getFontlength(Paint paint, String str) {
            return paint.measureText(str);
        }

        /**
         * @return 返回指定笔的文字高度
         */
        public static float getFontHeight(Paint paint) {
            Paint.FontMetrics fm = paint.getFontMetrics();
            return fm.descent - fm.ascent;
        }

        /**
         * @return 返回指定笔离文字顶部的基准距离
         */
        public static float getFontLeading(Paint paint) {
            Paint.FontMetrics fm = paint.getFontMetrics();
            return fm.leading - fm.ascent;
        }
    }

    private void drawStartDate(Canvas canvas, CalendarInfo calendarInfo, int left, float top, int bgColor, int circleColor, boolean isCircle) {
        if (isCircle) {
            calendarInfo.getBgPaint().setColor(bgColor);
            RectF rect = new RectF(left + columnWidth / 2, top, left + columnWidth, top + columnHeight);
            canvas.drawRect(rect, calendarInfo.getBgPaint());
            calendarInfo.getBgPaint().setColor(circleColor);
            canvas.drawCircle(left + columnWidth / 2, top + columnHeight / 2, mSelectRadiusSize, calendarInfo.getBgPaint());
        } else {
            /*calendarInfo.getBgPaint().setColor(circleColor);
            RectF rect = new RectF(left, top, left + columnWidth, top + columnHeight);
            canvas.drawRoundRect(rect, mSelectRadiusSize, mSelectRadiusSize, calendarInfo.getBgPaint());*/
        }
    }

    private void drawEndDate(Canvas canvas, CalendarInfo calendarInfo, int left, float top, int bgColor, int circleColor, boolean isCircle) {
        if (isCircle) {
            calendarInfo.getBgPaint().setColor(bgColor);
            RectF rect = new RectF(left, top, left + columnWidth / 2, top + columnHeight);
            canvas.drawRect(rect, calendarInfo.getBgPaint());
            calendarInfo.getBgPaint().setColor(circleColor);
            canvas.drawCircle(left + columnWidth / 2, top + columnHeight / 2, mSelectRadiusSize, calendarInfo.getBgPaint());
        } else {
            /*calendarInfo.getBgPaint().setColor(circleColor);
            RectF rect = new RectF(left, top, left + columnWidth, top + columnHeight);
            canvas.drawRoundRect(rect, mSelectRadiusSize, mSelectRadiusSize, calendarInfo.getBgPaint());*/
        }
    }

    private void drawSelectDate(Canvas canvas, CalendarInfo calendarInfo, int left, float top, int bgColor, boolean isCircle) {
        if (isCircle) {
            calendarInfo.getBgPaint().setColor(bgColor);
            canvas.drawCircle(left + columnWidth / 2, top + columnHeight / 2, mSelectRadiusSize, calendarInfo.getBgPaint());
        } else {
            calendarInfo.getBgPaint().setColor(bgColor);
            RectF rect = new RectF(left, top, left + columnWidth, top + columnHeight);
            canvas.drawRect(rect, calendarInfo.getBgPaint());
        }
    }

其实呢,自定义日历,麻烦的是对天的位置计算;

好了,不多说了,完整代码吧;

/**
 * @创建者 ALin
 * @创建时间 2018/8/24 10:59
 */
public class CustomizeCalendarView extends View {

    public static String[] weekText = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};

    public final static Integer DAY_SELECT = 0;
    public final static Integer DAY_START_SELECT = 1;
    public final static Integer DAY_END_SELECT = 2;

    private Paint mWeekPaint;
    private Paint bgWeekPaint;

    /**
     * 各部分背景
     */
    private int mBgMonth, mBgWeek, mBgDay, mBgSelectDay;
    private int mBgSelectMiddleDayColor1, mBgSelectMiddleDayColor2;
    /**
     * 各部分字体颜色
     */
    private int mMonthColor, mWeekColor, mDayColor, mDayTranColor, mSelectDayColor;
    /**
     * 各部分字体大小
     */
    private float mMonthSize, mWeekSize, mDaySize, mSelectRadiusSize;
    /**
     * 字体上下间距
     */
    private float mTextSpac;
    /**
     * 每列宽度
     */
    private int columnWidth, columnHeight = 100;
    private float weekHeight, dateHeight;
    private float selectStartHeight, selectEndHeight;
    private int currentDay, yesSelectDay;
    private int selectDay = 0;
    private Map<String, Boolean> dayEnabledMap;
    private SelectDay mSelectDay;

    private CalendarInfo currentCalendarInfo, otherCalendarInfo, selectCalendarInfo;

    public CustomizeCalendarView(Context context) {
        this(context, null, 0);
    }

    public CustomizeCalendarView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomizeCalendarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
        setBackgroundColor(getResources().getColor(R.color.record_edit_back_color));
    }

    public interface SelectDayDate {
        void selectBeginDate(Date date);

        void selectEndDate(Date date);
    }

    public SelectDayDate mSelectDayDate;

    public void setSelectDayDate(SelectDayDate selectDayDate) {
        mSelectDayDate = selectDayDate;
    }

    private TextView beginDate, beginWeek;

    public void setBeginData(TextView beginDate, TextView beginWeek) {
        this.beginDate = beginDate;
        this.beginWeek = beginWeek;
    }

    private TextView endDate, endWeek;

    public void setEndData(TextView endDate, TextView endWeek) {
        this.endDate = endDate;
        this.endWeek = endWeek;
    }

    private void init() {
        mBgWeek = getResources().getColor(R.color.customize_bg_1);
        mBgMonth = getResources().getColor(R.color.customize_month_bg);
        mBgDay = getResources().getColor(R.color.record_edit_back_color);
        mBgSelectDay = getResources().getColor(R.color.newselectedcolor);
        mBgSelectMiddleDayColor1 = getResources().getColor(R.color.calendar_select_color_1);
        mBgSelectMiddleDayColor2 = getResources().getColor(R.color.calendar_select_color_1);

        mWeekColor = getResources().getColor(R.color.market_gray);
        mMonthColor = getResources().getColor(R.color.main_gray);
        mDayColor = getResources().getColor(R.color.white);
        mDayTranColor = getResources().getColor(R.color.gray_alpha);
        mSelectDayColor = getResources().getColor(R.color.white);

        mWeekSize = sp2px(getResources().getDimension(R.dimen.customer_week));
        mMonthSize = sp2px(getResources().getDimension(R.dimen.customer_month));
        mDaySize = sp2px(getResources().getDimension(R.dimen.customer_day));
        mTextSpac = 14;

        dayEnabledMap = new HashMap<>();
        mWeekPaint = new Paint();
        bgWeekPaint = new Paint();
        mWeekPaint.setAntiAlias(true);
        bgWeekPaint.setAntiAlias(true);
        mWeekPaint.setTextSize(mWeekSize);
        weekHeight = FontUtil.getFontHeight(mWeekPaint) + 2 * mTextSpac;

        currentCalendarInfo = currentMonth(getMonthStr(new Date()));
        currentCalendarInfo.setPaint(new Paint());
        currentCalendarInfo.setBgPaint(new Paint());
        currentCalendarInfo.getPaint().setAntiAlias(true);
        currentCalendarInfo.getBgPaint().setAntiAlias(true);
        //月份高度
        currentCalendarInfo.getPaint().setTextSize(mMonthSize);
        currentCalendarInfo.setMonthHeight(FontUtil.getFontHeight(currentCalendarInfo.getPaint()) + 2 * mTextSpac);
        //日期高度
        currentCalendarInfo.getPaint().setTextSize(mDaySize);
        currentCalendarInfo.setDayHeight(FontUtil.getFontHeight(currentCalendarInfo.getPaint()) + 2 * mTextSpac);
        currentCalendarInfo.setOneHeight(currentCalendarInfo.getDayHeight());
        currentDay = currentCalendarInfo.getDay();
        yesSelectDay = currentDay - 30;
        if (currentCalendarInfo.isCurrentMonth()) {
            selectDay = currentCalendarInfo.getDay();
            selectCalendarInfo = currentCalendarInfo;
        } else {
            selectDay = 0;
        }

        otherCalendarInfo = otherMonth(String.format("%s年%02d月", currentCalendarInfo.getYearValue(), (currentCalendarInfo.getMonthValue() - 1)));
        otherCalendarInfo.setPaint(new Paint());
        otherCalendarInfo.setBgPaint(new Paint());
        otherCalendarInfo.getPaint().setAntiAlias(true);
        otherCalendarInfo.getBgPaint().setAntiAlias(true);
        //月份高度
        otherCalendarInfo.getPaint().setTextSize(mMonthSize);
        otherCalendarInfo.setMonthHeight(FontUtil.getFontHeight(otherCalendarInfo.getPaint()) + 2 * mTextSpac);
        //日期高度
        otherCalendarInfo.getPaint().setTextSize(mDaySize);
        otherCalendarInfo.setDayHeight(FontUtil.getFontHeight(otherCalendarInfo.getPaint()) + 2 * mTextSpac);
        otherCalendarInfo.setOneHeight(otherCalendarInfo.getDayHeight());
        dateHeight = weekHeight + otherCalendarInfo.getMonthHeight() + otherCalendarInfo.getLineNum() * otherCalendarInfo.getOneHeight();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //宽度 = 填充父窗体
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);   //获取宽的尺寸
        columnWidth = widthSize / 7;
        columnHeight = (int) (FontUtil.getFontHeight(currentCalendarInfo.getPaint()) + 2 * mTextSpac);
        mSelectRadiusSize = columnHeight / 2;
        //高度 = 标题高度 + 星期高度 + 日期行数*每行高度
        //float height = monthHeight + weekHeight + (lineNum * oneHeight);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        drawWeek(canvas);
        drawOtherDate(canvas);
        drawCurrentDate(canvas);
    }

    /**
     * 绘制绘制星期
     */
    private void drawWeek(Canvas canvas) {
        //背景
        bgWeekPaint.setColor(mBgWeek);
        RectF rect = new RectF(0, 0, getWidth(), weekHeight);
        canvas.drawRect(rect, bgWeekPaint);
        //绘制星期:七天
        mWeekPaint.setTextSize(mWeekSize);
        mWeekPaint.setColor(mWeekColor);
        for (int i = 0; i < weekText.length; i++) {
            int len = (int) FontUtil.getFontlength(mWeekPaint, weekText[i]);
            int x = i * columnWidth + (columnWidth - len) / 2;
            canvas.drawText(weekText[i], x, FontUtil.getFontLeading(mWeekPaint) + mTextSpac, mWeekPaint);
        }
    }

    /** 两个月 */
    private void drawOtherDate(Canvas canvas) {
        drawOtherMonth(canvas);
        drawOtherDay(canvas);
    }

    /**
     * 绘制上个月的月份
     */
    private void drawOtherMonth(Canvas canvas) {
        //背景
        otherCalendarInfo.getBgPaint().setColor(mBgMonth);
        RectF rect = new RectF(0, weekHeight, getWidth(), weekHeight + otherCalendarInfo.getMonthHeight());
        canvas.drawRect(rect, otherCalendarInfo.getBgPaint());
        //绘制月份
        otherCalendarInfo.getPaint().setTextSize(mMonthSize);
        otherCalendarInfo.getPaint().setColor(mMonthColor);
        float textLen = FontUtil.getFontlength(otherCalendarInfo.getPaint(), getMonthStr(otherCalendarInfo.getMonth()));
        float textStart = (getWidth() - textLen) / 2;
        canvas.drawText(getMonthStr(otherCalendarInfo.getMonth()), textStart, weekHeight + FontUtil.getFontLeading(otherCalendarInfo.getPaint()) + mTextSpac, otherCalendarInfo.getPaint());
    }

    /**
     * 绘制上个月的日期和次数
     */
    private void drawOtherDay(Canvas canvas) {
        float top = weekHeight + otherCalendarInfo.getMonthHeight();
        //行
        for (int line = 0; line < otherCalendarInfo.getLineNum(); line++) {
            if (line == 0) {
                //第一行
                drawOtherDayAndPre(canvas, top, otherCalendarInfo.getFirstLineNum(), 0, otherCalendarInfo.getFirstIndex());
            } else if (line == otherCalendarInfo.getLineNum() - 1) {
                //最后一行
                top += otherCalendarInfo.getOneHeight();
                drawOtherDayAndPre(canvas, top, otherCalendarInfo.getLastLineNum(), otherCalendarInfo.getFirstLineNum() + (line - 1) * 7, 0);
            } else {
                //满行
                top += otherCalendarInfo.getOneHeight();
                drawOtherDayAndPre(canvas, top, 7, otherCalendarInfo.getFirstLineNum() + (line - 1) * 7, 0);
            }
        }
    }

    /**
     * 绘制某一行的日期
     */
    private void drawOtherDayAndPre(Canvas canvas, float top, int count, int overDay, int startIndex) {
        //背景
        float topPre = top + otherCalendarInfo.getDayHeight();
        otherCalendarInfo.getBgPaint().setColor(mBgDay);
        RectF rect = new RectF(0, top, getWidth(), topPre);
        canvas.drawRect(rect, otherCalendarInfo.getBgPaint());
        otherCalendarInfo.getBgPaint().setColor(mBgDay);
        rect = new RectF(0, topPre, getWidth(), topPre + mTextSpac + otherCalendarInfo.getDayHeight());
        canvas.drawRect(rect, otherCalendarInfo.getBgPaint());

        otherCalendarInfo.getPaint().setTextSize(mDaySize);
        float dayTextLeading = FontUtil.getFontLeading(otherCalendarInfo.getPaint()) + mTextSpac;
        for (int i = 0; i < count; i++) {
            int left = (startIndex + i) * columnWidth;
            int day = (overDay + i + 1);
            otherCalendarInfo.setDayWeekMapIndex(this, day, startIndex + i);
            otherCalendarInfo.getPaint().setTextSize(mDaySize);
            if (yesSelectDay < 0) {
                if (day <= (otherCalendarInfo.getDayOfMonth() + yesSelectDay)) {
                    otherCalendarInfo.getPaint().setColor(mDayTranColor);
                    dayEnabledMap.put(getDayStr(otherCalendarInfo.getMonth(), day), false);
                } else {
                    if (selectStartHeight == 0) {
                        selectStartHeight = top;
                    }
                    otherCalendarInfo.getPaint().setColor(mDayColor);
                    dayEnabledMap.put(getDayStr(otherCalendarInfo.getMonth(), day), true);
                }
            } else {
                otherCalendarInfo.getPaint().setColor(mDayTranColor);
                dayEnabledMap.put(getDayStr(otherCalendarInfo.getMonth(), day), false);
            }

            if (dayEnabledMap.get(getDayStr(otherCalendarInfo.getMonth(), day))) {
                otherCalendarInfo.getPaint().setColor(mSelectDayColor);
                if (null != mSelectDay && mSelectDay.getDaySelectKey().contains(getDayStr(otherCalendarInfo.getMonth(), day))) {
                    if (TextUtils.equals(SelectDay.SINGLE, mSelectDay.getClickType())) {
                        otherCalendarInfo.getPaint().setColor(mSelectDayColor);
                        drawSelectDate(canvas, otherCalendarInfo, left, top, mBgSelectDay, true);
                    } else if (mSelectDay.getDaySelectMap().get(getDayStr(otherCalendarInfo.getMonth(), day)) == DAY_START_SELECT) {
                        /*if (i == count-1) {
                            drawSelectDate(canvas, otherCalendarInfo, left, top, mBgSelectDay, true);
                        } else {
                            drawStartDate(canvas, otherCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectDay);
                        }*/
                        drawStartDate(canvas, otherCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectDay, true);
                    } else if (mSelectDay.getDaySelectMap().get(getDayStr(otherCalendarInfo.getMonth(), day)) == DAY_END_SELECT) {
                        /*if (i == 0) {
                            drawSelectDate(canvas, otherCalendarInfo, left, top, mBgSelectDay, true);
                        } else {
                            drawEndDate(canvas, otherCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectDay);
                        }*/
                        drawEndDate(canvas, otherCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectDay, true);
                    } else {
                        /*if (i == 0 && i == count-1) {
                            drawSelectDate(canvas, otherCalendarInfo, left, top, mBgSelectMiddleDayColor2, true);
                        } else if (i == count-1) {
                            drawEndDate(canvas, otherCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectMiddleDayColor2, false);
                        } else if (i == 0) {
                            drawStartDate(canvas, otherCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectMiddleDayColor2, false);
                        } else {
                            drawSelectDate(canvas, otherCalendarInfo, left, top, mBgSelectMiddleDayColor1, false);
                        }*/
                        drawSelectDate(canvas, otherCalendarInfo, left, top, mBgSelectMiddleDayColor1, false);
                    }
                } else {
                    if (selectDay == day) {
                        drawSelectDate(canvas, otherCalendarInfo, left, top, mBgSelectDay, true);
                    }
                }
            }

            int len = (int) FontUtil.getFontlength(otherCalendarInfo.getPaint(), day + "");
            int x = left + (columnWidth - len) / 2;
            canvas.drawText(day + "", x, top + dayTextLeading, otherCalendarInfo.getPaint());
        }
    }

    private void drawCurrentDate(Canvas canvas) {
        drawCurrentMonth(canvas);
        drawCurrentDay(canvas);
    }

    /**
     * 绘制月份
     */
    private void drawCurrentMonth(Canvas canvas) {
        //背景
        currentCalendarInfo.getBgPaint().setColor(mBgMonth);
        RectF rect = new RectF(0, dateHeight, getWidth(), dateHeight + currentCalendarInfo.getMonthHeight());
        canvas.drawRect(rect, currentCalendarInfo.getBgPaint());
        //绘制月份
        currentCalendarInfo.getPaint().setTextSize(mMonthSize);
        currentCalendarInfo.getPaint().setColor(mMonthColor);
        float textLen = FontUtil.getFontlength(currentCalendarInfo.getPaint(), getMonthStr(currentCalendarInfo.getMonth()));
        float textStart = (getWidth() - textLen) / 2;
        canvas.drawText(getMonthStr(currentCalendarInfo.getMonth()), textStart, dateHeight + FontUtil.getFontLeading(currentCalendarInfo.getPaint()) + mTextSpac, currentCalendarInfo.getPaint());
    }

    /**
     * 绘制日期和次数
     */
    private void drawCurrentDay(Canvas canvas) {
        float top = dateHeight + currentCalendarInfo.getMonthHeight();
        //行
        for (int line = 0; line < currentCalendarInfo.getLineNum(); line++) {
            if (line == 0) {
                //第一行
                drawCurrentDayAndPre(canvas, top, currentCalendarInfo.getFirstLineNum(), 0, currentCalendarInfo.getFirstIndex());
            } else if (line == currentCalendarInfo.getLineNum() - 1) {
                //最后一行
                top += currentCalendarInfo.getOneHeight();
                drawCurrentDayAndPre(canvas, top, currentCalendarInfo.getLastLineNum(), currentCalendarInfo.getFirstLineNum() + (line - 1) * 7, 0);
            } else {
                //满行
                top += currentCalendarInfo.getOneHeight();
                drawCurrentDayAndPre(canvas, top, 7, currentCalendarInfo.getFirstLineNum() + (line - 1) * 7, 0);
            }
        }
    }

    /**
     * 绘制某一行的日期
     */
    private void drawCurrentDayAndPre(Canvas canvas, float top, int count, int overDay, int startIndex) {
        //背景
        float topPre = top + currentCalendarInfo.getDayHeight();
        currentCalendarInfo.getBgPaint().setColor(mBgDay);
        RectF rect = new RectF(0, top, getWidth(), topPre);
        canvas.drawRect(rect, currentCalendarInfo.getBgPaint());

        currentCalendarInfo.getBgPaint().setColor(mBgDay);
        rect = new RectF(0, topPre, getWidth(), topPre + mTextSpac + currentCalendarInfo.getDayHeight());
        canvas.drawRect(rect, currentCalendarInfo.getBgPaint());

        currentCalendarInfo.getPaint().setTextSize(mDaySize);
        float dayTextLeading = FontUtil.getFontLeading(currentCalendarInfo.getPaint()) + mTextSpac;
        for (int i = 0; i < count; i++) {
            int left = (startIndex + i) * columnWidth;
            int day = (overDay + i + 1);
            currentCalendarInfo.setDayWeekMapIndex(this, day, startIndex + i);
            currentCalendarInfo.getPaint().setTextSize(mDaySize);
            if (yesSelectDay > 0) {
                if (day == yesSelectDay) {
                    currentCalendarInfo.getPaint().setColor(mDayTranColor);
                    dayEnabledMap.put(getDayStr(currentCalendarInfo.getMonth(), day), false);
                } else {
                    if (selectStartHeight == 0) {
                        selectStartHeight = top;
                    }
                    currentCalendarInfo.getPaint().setColor(mDayColor);
                    dayEnabledMap.put(getDayStr(currentCalendarInfo.getMonth(), day), true);
                }
            } else {
                if (day > currentDay) {
                    currentCalendarInfo.getPaint().setColor(mDayTranColor);
                    dayEnabledMap.put(getDayStr(currentCalendarInfo.getMonth(), day), false);
                } else {
                    currentCalendarInfo.getPaint().setColor(mDayColor);
                    dayEnabledMap.put(getDayStr(currentCalendarInfo.getMonth(), day), true);
                }
            }

            if (dayEnabledMap.get(getDayStr(currentCalendarInfo.getMonth(), day))) {
                currentCalendarInfo.getPaint().setColor(mSelectDayColor);
                if (null != mSelectDay && mSelectDay.getDaySelectKey().contains(getDayStr(currentCalendarInfo.getMonth(), day))) {
                    if (TextUtils.equals(SelectDay.SINGLE, mSelectDay.getClickType())) {
                        currentCalendarInfo.getBgPaint().setColor(mBgSelectDay);
                        drawSelectDate(canvas, currentCalendarInfo, left, top, mBgSelectDay, true);
                    } else {
                        if (mSelectDay.getDaySelectMap().get(getDayStr(currentCalendarInfo.getMonth(), day)) == DAY_START_SELECT) {
                            /*if (i == count-1) {
                                drawSelectDate(canvas, currentCalendarInfo, left, top, mBgSelectDay, true);
                            } else {
                                drawStartDate(canvas, currentCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectDay);
                            }*/
                            drawStartDate(canvas, currentCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectDay, true);
                        } else if (mSelectDay.getDaySelectMap().get(getDayStr(currentCalendarInfo.getMonth(), day)) == DAY_END_SELECT) {
                            /*if (i == 0) {
                                drawSelectDate(canvas, currentCalendarInfo, left, top, mBgSelectDay, true);
                            } else {
                                drawEndDate(canvas, currentCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectDay);
                            }*/
                            drawEndDate(canvas, currentCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectDay, true);
                        } else {
                            /*if (i == 0 && i == count-1) {
                                drawSelectDate(canvas, currentCalendarInfo, left, top, mBgSelectMiddleDayColor2, true);
                            } else if (i == count-1) {
                                drawEndDate(canvas, currentCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectMiddleDayColor2, false);
                            } else if (i == 0) {
                                drawStartDate(canvas, currentCalendarInfo, left, top, mBgSelectMiddleDayColor1, mBgSelectMiddleDayColor2, false);
                            } else {
                                drawSelectDate(canvas, currentCalendarInfo, left, top, mBgSelectMiddleDayColor1, false);
                            }*/
                            drawSelectDate(canvas, currentCalendarInfo, left, top, mBgSelectMiddleDayColor1, false);
                        }
                    }
                } else {
                    if (selectDay == day) {
                        drawSelectDate(canvas, currentCalendarInfo, left, top, mBgSelectDay, true);
                        if (selectEndHeight == 0) {
                            selectEndHeight = top;
                        }
                    }
                }
            }

            int len = (int) FontUtil.getFontlength(currentCalendarInfo.getPaint(), day + "");
            int x = left + (columnWidth - len) / 2;
            canvas.drawText(day + "", x, top + dayTextLeading, currentCalendarInfo.getPaint());
        }
    }

    public int sp2px(float spValue) {
        final float fontScale = getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }

    public static class FontUtil {

        /**
         * @param paint
         * @param str
         * @return 返回指定笔和指定字符串的长度
         */
        public static float getFontlength(Paint paint, String str) {
            return paint.measureText(str);
        }

        /**
         * @return 返回指定笔的文字高度
         */
        public static float getFontHeight(Paint paint) {
            Paint.FontMetrics fm = paint.getFontMetrics();
            return fm.descent - fm.ascent;
        }

        /**
         * @return 返回指定笔离文字顶部的基准距离
         */
        public static float getFontLeading(Paint paint) {
            Paint.FontMetrics fm = paint.getFontMetrics();
            return fm.leading - fm.ascent;
        }
    }

    private void drawStartDate(Canvas canvas, CalendarInfo calendarInfo, int left, float top, int bgColor, int circleColor, boolean isCircle) {
        if (isCircle) {
            calendarInfo.getBgPaint().setColor(bgColor);
            RectF rect = new RectF(left + columnWidth / 2, top, left + columnWidth, top + columnHeight);
            canvas.drawRect(rect, calendarInfo.getBgPaint());
            calendarInfo.getBgPaint().setColor(circleColor);
            canvas.drawCircle(left + columnWidth / 2, top + columnHeight / 2, mSelectRadiusSize, calendarInfo.getBgPaint());
        } else {
            /*calendarInfo.getBgPaint().setColor(circleColor);
            RectF rect = new RectF(left, top, left + columnWidth, top + columnHeight);
            canvas.drawRoundRect(rect, mSelectRadiusSize, mSelectRadiusSize, calendarInfo.getBgPaint());*/
        }
    }

    private void drawEndDate(Canvas canvas, CalendarInfo calendarInfo, int left, float top, int bgColor, int circleColor, boolean isCircle) {
        if (isCircle) {
            calendarInfo.getBgPaint().setColor(bgColor);
            RectF rect = new RectF(left, top, left + columnWidth / 2, top + columnHeight);
            canvas.drawRect(rect, calendarInfo.getBgPaint());
            calendarInfo.getBgPaint().setColor(circleColor);
            canvas.drawCircle(left + columnWidth / 2, top + columnHeight / 2, mSelectRadiusSize, calendarInfo.getBgPaint());
        } else {
            /*calendarInfo.getBgPaint().setColor(circleColor);
            RectF rect = new RectF(left, top, left + columnWidth, top + columnHeight);
            canvas.drawRoundRect(rect, mSelectRadiusSize, mSelectRadiusSize, calendarInfo.getBgPaint());*/
        }
    }

    private void drawSelectDate(Canvas canvas, CalendarInfo calendarInfo, int left, float top, int bgColor, boolean isCircle) {
        if (isCircle) {
            calendarInfo.getBgPaint().setColor(bgColor);
            canvas.drawCircle(left + columnWidth / 2, top + columnHeight / 2, mSelectRadiusSize, calendarInfo.getBgPaint());
        } else {
            calendarInfo.getBgPaint().setColor(bgColor);
            RectF rect = new RectF(left, top, left + columnWidth, top + columnHeight);
            canvas.drawRect(rect, calendarInfo.getBgPaint());
        }
    }

    private static class CalendarInfo {
        private Paint mPaint;
        private Paint bgPaint;
        /**
         * 各部分高度
         */
        private float monthHeight, dayHeight, oneHeight;

        private Date month; //当前的月份
        private int yearValue;    //当前年
        private int monthValue;    //当前月
        private int day;    //当前日期
        private boolean isCurrentMonth;       //展示的月份是否是当前月
        private int dayOfMonth;    //月份天数
        private int firstIndex;    //当月第一天位置索引
        private int firstLineNum, lastLineNum; //第一行、最后一行能展示多少日期
        private int lineNum;      //日期行数

        private Map<String, DayInfo> dayWeekMap;

        public CalendarInfo() {
            dayWeekMap = new HashMap<>();
        }

        public void setDayWeekMapIndex(CustomizeCalendarView customizeCalendar, int day, int week) {
            DayInfo dayInfo = new DayInfo(customizeCalendar.getDayStr(getMonth(), day), getYearValue(), getMonthValue(), day, week);
            this.dayWeekMap.put(dayInfo.getDate(), dayInfo);
        }

        public boolean isSunday(CustomizeCalendarView customizeCalendar, int day) {
            return dayWeekMap.get(customizeCalendar.getDayStr(getMonth(), day)).getWeek() == 0;
        }

        public boolean isSaturday(CustomizeCalendarView customizeCalendar, int day) {
            return dayWeekMap.get(customizeCalendar.getDayStr(getMonth(), day)).getWeek() == 6;
        }

        public void setPaint(Paint paint) {
            mPaint = paint;
        }

        public Paint getPaint() {
            return mPaint;
        }

        public void setBgPaint(Paint bgPaint) {
            this.bgPaint = bgPaint;
        }

        public Paint getBgPaint() {
            return bgPaint;
        }

        public void setMonthHeight(float monthHeight) {
            this.monthHeight = monthHeight;
        }

        public float getMonthHeight() {
            return monthHeight;
        }

        public void setDayHeight(float dayHeight) {
            this.dayHeight = dayHeight;
        }

        public float getDayHeight() {
            return dayHeight;
        }

        public void setOneHeight(float oneHeight) {
            this.oneHeight = oneHeight;
        }

        public float getOneHeight() {
            return oneHeight;
        }

        public void setMonth(Date month) {
            this.month = month;
        }

        public Date getMonth() {
            return month;
        }

        public void setYearValue(int yearValue) {
            this.yearValue = yearValue;
        }

        public int getYearValue() {
            return yearValue;
        }

        public void setMonthValue(int monthValue) {
            this.monthValue = monthValue;
        }

        public int getMonthValue() {
            return monthValue;
        }

        public void setDay(int day) {
            this.day = day;
        }

        public int getDay() {
            return day;
        }

        public void setCurrentMonth(boolean currentMonth) {
            isCurrentMonth = currentMonth;
        }

        public boolean isCurrentMonth() {
            return isCurrentMonth;
        }

        public void setDayOfMonth(int dayOfMonth) {
            this.dayOfMonth = dayOfMonth;
        }

        public int getDayOfMonth() {
            return dayOfMonth;
        }

        public void setFirstIndex(int firstIndex) {
            this.firstIndex = firstIndex;
        }

        public int getFirstIndex() {
            return firstIndex;
        }

        public void setFirstLineNum(int firstLineNum) {
            this.firstLineNum = firstLineNum;
        }

        public int getFirstLineNum() {
            return firstLineNum;
        }

        public void setLastLineNum(int lastLineNum) {
            this.lastLineNum = lastLineNum;
        }

        public int getLastLineNum() {
            return lastLineNum;
        }

        public void setLineNum(int lineNum) {
            this.lineNum = lineNum;
        }

        public int getLineNum() {
            return lineNum;
        }
    }

    private static class DayInfo {
        private String date; //时期
        private int year; //年
        private int month; //月
        private int day; //日
        private int week; //第几周

        public DayInfo(String date, int year, int month, int day, int week) {
            this.date = date;
            this.year = year;
            this.month = month;
            this.day = day;
            this.week = week;
        }

        public String getDate() {
            return date;
        }

        public void setDate(String date) {
            this.date = date;
        }

        public int getYear() {
            return year;
        }

        public void setYear(int year) {
            this.year = year;
        }

        public int getMonth() {
            return month;
        }

        public void setMonth(int month) {
            this.month = month;
        }

        public int getDay() {
            return day;
        }

        public void setDay(int day) {
            this.day = day;
        }

        public int getWeek() {
            return week;
        }

        public void setWeek(int week) {
            this.week = week;
        }
    }

    /**
     * 设置当前月份
     */
    public CalendarInfo currentMonth(String date) {
        CalendarInfo calendarInfo = new CalendarInfo();
        calendarInfo.setMonth(str2Date(date));

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendarInfo.setYearValue(calendar.get(Calendar.YEAR));
        calendarInfo.setMonthValue(calendar.get(Calendar.MONTH) + 1);
        //获取今天是多少号
        calendarInfo.setDay(calendar.get(Calendar.DAY_OF_MONTH));

        Date cM = str2Date(getMonthStr(new Date()));
        //判断是否为当月
        calendarInfo.setCurrentMonth(cM.getTime() == calendarInfo.getMonth().getTime());
        calendar.setTime(calendarInfo.getMonth());
        calendarInfo.setDayOfMonth(calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        //第一行1号显示在什么位置(星期几)
        calendarInfo.setFirstIndex(calendar.get(Calendar.DAY_OF_WEEK) - 1);
        int lineNum = 1;
        //第一行能展示的天数
        calendarInfo.setFirstLineNum(7 - calendarInfo.getFirstIndex());
        int size = calendarInfo.getDayOfMonth() - calendarInfo.getFirstLineNum();
        while (size > 7) {
            lineNum++;
            size -= 7;
        }
        if (size > 0) {
            lineNum++;
            calendarInfo.setLastLineNum(size);
        }
        calendarInfo.setLineNum(lineNum);
        return calendarInfo;
    }

    /**
     * 设置上个月月份
     */
    public CalendarInfo otherMonth(String date) {
        CalendarInfo calendarInfo = new CalendarInfo();
        calendarInfo.setMonth(str2Date(date));

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(calendarInfo.getMonth());
        calendarInfo.setYearValue(calendar.get(Calendar.YEAR));
        calendarInfo.setMonthValue(calendar.get(Calendar.MONTH) + 1);
        //获取今天是多少号
        calendarInfo.setDay(calendar.get(Calendar.DAY_OF_MONTH));

        Date cM = str2Date(getMonthStr(new Date()));
        //判断是否为当月
        calendarInfo.setCurrentMonth(cM.getTime() == calendarInfo.getMonth().getTime());
        calendar.setTime(calendarInfo.getMonth());
        calendarInfo.setDayOfMonth(calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        //第一行1号显示在什么位置(星期几)
        calendarInfo.setFirstIndex(calendar.get(Calendar.DAY_OF_WEEK) - 1);
        int lineNum = 1;
        //第一行能展示的天数
        calendarInfo.setFirstLineNum(7 - calendarInfo.getFirstIndex());
        int size = calendarInfo.getDayOfMonth() - calendarInfo.getFirstLineNum();
        while (size > 7) {
            lineNum++;
            size -= 7;
        }
        if (size > 0) {
            lineNum++;
            calendarInfo.setLastLineNum(size);
        }
        calendarInfo.setLineNum(lineNum);
        return calendarInfo;
    }

    private Date str2Date(String str) {
        try {
            SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月");
            return df.parse(str);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private int selectDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取月份标题
     */
    private String getMonthStr(Date month) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月");
        return df.format(month);
    }

    private String getDayStr(Date month) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日");
        return df.format(month);
    }

    /**
     * 获取日期
     */
    private String getDayStr(Date month, int day) {
        return String.format("%s%02d日", getMonthStr(month), day);
    }

    /**
     * 焦点坐标
     */
    private PointF focusPoint = new PointF();

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction() & MotionEvent.ACTION_MASK;
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                focusPoint.set(event.getX(), event.getY());
                selectDayMethod(focusPoint, true, false);
                break;
            case MotionEvent.ACTION_MOVE:
                focusPoint.set(event.getX(), event.getY());
                selectDayMethod(focusPoint, false, false);
                break;
            case MotionEvent.ACTION_OUTSIDE:
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                focusPoint.set(event.getX(), event.getY());
                selectDayMethod(focusPoint, false, true);
                break;
        }
        return true;
    }

    public static class SelectDay {
        public final static String SINGLE = "single";
        public final static String DOUBLE = "double";
        public final static String REMOVE = "remove";

        public SelectDay(Date startDate) {
            setClickType(SINGLE);
            setStartDate(startDate);
            setDaySelectMap(setSelectDay(getStartDate()));
        }

        public SelectDay(Date sDate, Date eDate, boolean isRemove) {
            setClickType(REMOVE);
            setRemove(isRemove);
            setStartDate(sDate);
            setEndDate(eDate);
            setDaySelectMap(setSelectDay());
        }

        public SelectDay(Date startDate, Date endDate) {
            setClickType(DOUBLE);
            if (compareDate(startDate, endDate) < 0) {
                setStartDate(startDate);
                setEndDate(endDate);
            } else if (compareDate(startDate, endDate) > 0) {
                setStartDate(endDate);
                setEndDate(startDate);
            }
            setDaySelectMap(setSelectDay());
        }

        private String clickType;
        private boolean isRemove;

        public void setClickType(String clickType) {
            this.clickType = clickType;
        }

        public String getClickType() {
            return clickType;
        }

        public void setRemove(boolean remove) {
            isRemove = remove;
        }

        public boolean isRemove() {
            return isRemove;
        }

        private Date startDate, endDate;

        public void setStartDate(Date startDate) {
            this.startDate = startDate;
        }

        public Date getStartDate() {
            return startDate;
        }

        public void setEndDate(Date endDate) {
            this.endDate = endDate;
        }

        public Date getEndDate() {
            return endDate;
        }

        private Map<String, Integer> daySelectMap;

        public Map<String, Integer> getDaySelectMap() {
            return daySelectMap;
        }

        public void setDaySelectMap(Map<String, Integer> daySelectMap) {
            this.daySelectMap = daySelectMap;
        }

        public String getDaySelectKey() {
            return getDaySelectMap().keySet().toString();
        }

        public Date getStartDay() {
            if (null != daySelectMap && daySelectMap.values().size() > 0) {
                Set set = daySelectMap.keySet();
                Iterator iter = set.iterator();
                while (iter.hasNext()) {
                    String key = (String) iter.next();
                    if (daySelectMap.get(key) == 1) {
                        return strToDate(key);
                    }
                }
            }
            return null;
        }

        public Date getEndDay() {
            if (null != daySelectMap && daySelectMap.values().size() > 0) {
                Set set = daySelectMap.keySet();
                Iterator iter = set.iterator();
                while (iter.hasNext()) {
                    String key = (String) iter.next();
                    if (daySelectMap.get(key) == 2) {
                        return strToDate(key);
                    }
                }
            }
            return null;
        }

        /**
         * 调用方法
         */
        private Map<String, Integer> setSelectDay() {
            return setSelectDay(getStartDate(), getEndDate());
        }

        private Map<String, Integer> setSelectDay(Date start) {
            return setSelectDay(start, start);
        }

        private Map<String, Integer> setSelectDay(Date start, Date end) {
            if (TextUtils.equals(DOUBLE, getClickType())) {
                return doubleSelectDay(start, end);
            } else if (TextUtils.equals(SINGLE, getClickType())) {
                return singleSelectDay(start);
            } else {
                if (isRemove()) {
                    return removeSelectDay(start, end);
                } else {
                    return doubleSelectDay(start, end);
                }
            }
        }

        private Map<String, Integer> singleSelectDay(Date date){
            Map<String, Integer> daySelectMap = new HashMap<>();
            daySelectMap.put(getDayStr(date), DAY_START_SELECT);
            return daySelectMap;
        }

        private Map<String, Integer> doubleSelectDay(Date start, Date end){
            Map<String, Integer> daySelectMap = new HashMap<>();
            int numberDay = (int) dateDiff(start, end) + 1;
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(start);
            for (int i = 0; i < numberDay; i++) {
                int day = calendar.get(Calendar.DAY_OF_MONTH);
                int dayOfMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
                int dayIndex = day + i;
                if (i == 0) {
                    daySelectMap.put(getMonthAndDayStr(start, day), DAY_START_SELECT);
                } else if (i == numberDay - 1) {
                    if (dayIndex <= dayOfMonth) {
                        daySelectMap.put(getMonthAndDayStr(start, dayIndex), DAY_END_SELECT);
                    } else {
                        daySelectMap.put(getMonthAndDayStr(end, dayIndex - dayOfMonth), DAY_END_SELECT);
                    }
                } else {
                    if (dayIndex <= dayOfMonth) {
                        daySelectMap.put(getMonthAndDayStr(start, dayIndex), DAY_SELECT);
                    } else {
                        daySelectMap.put(getMonthAndDayStr(end, dayIndex - dayOfMonth), DAY_SELECT);
                    }
                }
            }
            return daySelectMap;
        }

        private Map<String, Integer> removeSelectDay(Date start, Date end){
            Map<String, Integer> daySelectMap = new HashMap<>();
            int numberDay = (int) dateDiff(start, end);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(start);
            for (int i = 0; i < numberDay; i++) {
                int day = calendar.get(Calendar.DAY_OF_MONTH);
                int dayOfMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
                int dayIndex = day + i;
                if (i == 0) {
                    daySelectMap.put(getMonthAndDayStr(start, day), DAY_START_SELECT);
                } else if (i == numberDay - 1) {
                    if (dayIndex <= dayOfMonth) {
                        daySelectMap.put(getMonthAndDayStr(start, dayIndex), DAY_SELECT);
                    } else {
                        daySelectMap.put(getMonthAndDayStr(end, dayIndex - dayOfMonth), DAY_SELECT);
                    }
                    daySelectMap.put(getDayStr(end), DAY_END_SELECT);
                } else {
                    if (dayIndex <= dayOfMonth) {
                        daySelectMap.put(getMonthAndDayStr(start, dayIndex), DAY_SELECT);
                    } else {
                        daySelectMap.put(getMonthAndDayStr(end, dayIndex - dayOfMonth), DAY_SELECT);
                    }
                }
            }
            return daySelectMap;
        }

        private int compareDate(Date dt1, Date dt2) {
            if (dt1.getTime() > dt2.getTime()) {
                return 1;
            } else if (dt1.getTime() < dt2.getTime()) {
                return -1;
            } else {
                return 0;
            }
        }

        private long dateDiff(Date startTime, Date endTime) {
            long nd = 1000 * 24 * 60 * 60;// 一天的毫秒数
            long diff = endTime.getTime() - startTime.getTime();
            long day = diff / nd;// 计算差多少天
            if (day >= 1) {
                return day;
            } else {
                if (day == 0) {
                    return 1;
                } else {
                    return 0;
                }
            }
        }

        private Date strToDate(String str) {
            try {
                SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日");
                return df.parse(str);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }

        private String getDayStr(Date date) {
            SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日");
            return df.format(date);
        }

        private String getMonthAndDayStr(Date date, int day) {
            SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月");
            return String.format("%s%02d日", df.format(date), day);
        }

        private Date maxDate(List<Long> dates) {
            long max = dates.get(0);//把数组第一个数赋值给max和min
            for (int i = 0; i < dates.size(); i++) {//依次判断剩下每个数
                if (dates.get(i) > max) max = dates.get(i);//如果该数大于max,把其赋值给max
            }
            return new Date(max);
        }

        private Date minDate(List<Long> dates) {
            long min = dates.get(0);//把数组第一个数赋值给max和min
            for (int i = 0; i < dates.size(); i++) {//依次判断剩下每个数
                if (dates.get(i) < min) min = dates.get(i);//如果该数小于min,把其赋值给min
            }
            return new Date(min);
        }
    }

    private int number;
    private float downX, downY;
    private Date mSelectDate;

    private void selectDayMethod(PointF focusPoint, boolean eventDown, boolean eventEnd) {
        if (eventDown) {
            downX = focusPoint.x;
            downY = focusPoint.y;
            Date date = touchDay(focusPoint);
            if (null != date && dayEnabledMap.get(getDayStr(date))) {
                mSelectDate = date;
            }
        } else if (eventEnd) {
            if (Math.abs(downX - focusPoint.x) > columnWidth || Math.abs(downY - focusPoint.y) > columnHeight) {
                onRemoveClick(null, null,false);
            } else {
                onSingleClick(focusPoint);
            }
        } else {
            Date date = touchDay(focusPoint);
            if (null != date && null != mSelectDate && dayEnabledMap.get(getDayStr(date)) && (focusPoint.y > selectStartHeight || focusPoint.y < selectEndHeight )) {
                if (mSelectDate.getTime() < date.getTime()) {
                    onRemoveClick(mSelectDate, date, true);
                } else if (mSelectDate.getTime() > date.getTime()) {
                    onRemoveClick(date, mSelectDate, true);
                }
            }
        }
    }

    private void onRemoveClick(Date start, Date end, boolean isRemove){
        number = 0;
        if (isRemove) {
            mSelectDay = new SelectDay(start, end, true);
        } else {
            start = mSelectDay.getStartDate();
            end = mSelectDay.getEndDate();

            mSelectDay = new SelectDay(start, end, false);
            setBeginText(mSelectDay.getStartDay());
            setEndText(mSelectDay.getEndDay());
        }
        invalidate();
    }

    private void onSingleClick(PointF focusPoint) {
        Date date = touchDay(focusPoint);
        if (null != date) {
            number++;
            if (number == 1) {
                mSelectDay = new SelectDay(date);
                selectDay = selectDay(mSelectDay.getStartDate());
                setBeginText(mSelectDay.getStartDay());
                setEndText(mSelectDay.getStartDay());
            } else if (number == 2) {
                Date startDate = mSelectDay.getStartDate();
                if (startDate.getTime() != date.getTime()) {
                    mSelectDay = new SelectDay(startDate, date);
                    setBeginText(mSelectDay.getStartDay());
                    setEndText(mSelectDay.getEndDay());
                    number = 0;
                } else {
                    mSelectDay = new SelectDay(date);
                    selectDay = selectDay(mSelectDay.getStartDate());
                    setBeginText(mSelectDay.getStartDay());
                    setEndText(mSelectDay.getStartDay());
                    number = 1;
                }
            }
            invalidate();
        }
    }

    private Date touchDay(PointF focusPoint) {
        //根据Y坐标找到焦点行
        boolean isOtherDay = false;  //事件是否有效
        boolean isCurrentDay = false;  //事件是否有效
        //日期部分
        float height = weekHeight + otherCalendarInfo.getMonthHeight();
        float otherOneTop = weekHeight + otherCalendarInfo.getMonthHeight() + otherCalendarInfo.getOneHeight();
        float otherDateHeight = dateHeight + currentCalendarInfo.getMonthHeight();
        float currentHeight = otherDateHeight + (currentCalendarInfo.getLineNum() * currentCalendarInfo.getOneHeight());
        float currentOneTop = otherDateHeight + currentCalendarInfo.getOneHeight();

        int focusOtherLine = 1;
        int focusCurrentLine = 1;

        if (focusPoint.y > height && focusPoint.y <= dateHeight) {
            while (focusOtherLine <= otherCalendarInfo.getLineNum()) {
                if (otherOneTop >= focusPoint.y) {
                    isOtherDay = true;
                    break;
                }
                otherOneTop += otherCalendarInfo.getOneHeight();
                focusOtherLine++;
            }
        } else if (focusPoint.y > dateHeight && focusPoint.y < currentHeight) {
            while (focusCurrentLine <= currentCalendarInfo.getLineNum()) {
                if (currentOneTop >= focusPoint.y) {
                    isCurrentDay = true;
                    break;
                }
                currentOneTop += currentCalendarInfo.getOneHeight();
                focusCurrentLine++;
            }
        }

        //根据X坐标找到具体的焦点日期
        int xIndex = (int) focusPoint.x / columnWidth;
        if ((focusPoint.x / columnWidth - xIndex) > 0) {
            xIndex += 1;
        }
        if (xIndex <= 0)
            xIndex = 1;   //避免调到上一行最后一个日期
        if (xIndex > 7)
            xIndex = 7;   //避免调到下一行第一个日期

        if (isOtherDay) {
            if (focusOtherLine == 1) {
                //第一行
                if (xIndex <= otherCalendarInfo.getFirstIndex()) {
                    return getSelectedDay(selectCalendarInfo, selectDay);
                } else {
                    return getSelectedDay(otherCalendarInfo, xIndex - otherCalendarInfo.getFirstIndex());
                }
            } else if (focusOtherLine == otherCalendarInfo.getLineNum()) {
                //最后一行
                if (xIndex > otherCalendarInfo.getLastLineNum()) {
                    return getSelectedDay(selectCalendarInfo, selectDay);
                } else {
                    return getSelectedDay(otherCalendarInfo, otherCalendarInfo.getFirstLineNum() + (focusOtherLine - 2) * 7 + xIndex);
                }
            } else {
                return getSelectedDay(otherCalendarInfo, otherCalendarInfo.getFirstLineNum() + (focusOtherLine - 2) * 7 + xIndex);
            }
        } else if (isCurrentDay) {
            if (focusCurrentLine == 1) {
                //第一行
                if (xIndex <= currentCalendarInfo.getFirstIndex()) {
                    return getSelectedDay(selectCalendarInfo, selectDay);
                } else {
                    return getSelectedDay(currentCalendarInfo, xIndex - currentCalendarInfo.getFirstIndex());
                }
            } else if (focusCurrentLine == currentCalendarInfo.getLineNum()) {
                //最后一行
                if (xIndex > currentCalendarInfo.getLastLineNum()) {
                    return getSelectedDay(selectCalendarInfo, selectDay);
                } else {
                    return getSelectedDay(currentCalendarInfo, currentCalendarInfo.getFirstLineNum() + (focusCurrentLine - 2) * 7 + xIndex);
                }
            } else {
                return getSelectedDay(currentCalendarInfo, currentCalendarInfo.getFirstLineNum() + (focusCurrentLine - 2) * 7 + xIndex);
            }
        } else {
            return getSelectedDay(selectCalendarInfo, selectDay);
        }
    }

    private Date getSelectedDay(CalendarInfo calendarInfo, int day) {
        if (dayEnabledMap.get(getDayStr(calendarInfo.getMonth(), day))) {
            selectDay = day;
            selectCalendarInfo = calendarInfo;
            return dayDate(getDayStr(calendarInfo.getMonth(), day));
        }
        return null;
    }

    private Date dayDate(String str) {
        try {
            SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日");
            return df.parse(str);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public void invalidate() {
        requestLayout();
        super.invalidate();
    }

    private void setBeginText(Date start) {
        if (null != mSelectDayDate) {
            mSelectDayDate.selectBeginDate(start);
        }

        if (null != beginDate) {
            beginDate.setText(selectDate(start));
        }

        if (null != beginWeek) {
            beginWeek.setText(selectWeek(start));
        }
    }

    private void setEndText(Date end) {
        if (null != mSelectDayDate) {
            mSelectDayDate.selectEndDate(end);
        }

        if (null != endDate) {
            endDate.setText(selectDate(end));
        }

        if (null != endWeek) {
            endWeek.setText(selectWeek(end));
        }
    }

    public String selectWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int week = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        return CustomizeCalendarView.weekText[week];
    }

    private String selectDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        return String.format("%s月%s日", month, day);
    }
}

感谢查阅;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值