精华内容
下载资源
问答
  • 自定义日历开发

    2018-09-04 14:56:32
    还就没写博客了,最近写了个自定义日历,分享下; 一.某月的日历信息 private static class CalendarInfo { private Paint mPaint; private Paint bgPaint; /** * 各部分高度 */ private float mon...

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

    一.某月的日历信息

    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);
        }
    }

    感谢查阅;

    展开全文
  • 自定义日历开发笔记

    千次阅读 2018-11-01 18:12:01
    开发思路 - 使用HTML合理规划组件结构 - 为组件编写美观的样式 - 如何使用javascript获取组件所需数据 - 将数据与HTML结构结合 - 用户时间处理 原生js的操作和jquery的对比 //查询dom元素 document....

    开发思路

     - 使用HTML合理规划组件结构
     - 为组件编写美观的样式
     - 如何使用javascript获取组件所需数据
     - 将数据与HTML结构结合
     - 用户时间处理
    

    原生js的操作和jquery的对比

    //查询dom元素
     document.querySelector('.ui-datepicker-wrapper');
    $("xxx")[0]
    
    //判断是否有class
    $target.classList.contains('ui-datepicker-next-btn')
    $("xxx").hasClass('ui-datepicker-next-btn')
    
    //获取data值
    $target.dataset.year
    $("xxx").data("year")
    
    //添加class
    $wrapper.classList.add('ui-datepicker-wrapper-show')
    $("xxx").addClass('ui-datepicker-wrapper-show');
    
    

    日期对象的基本函数

    	//获取年份
     		getFullYear()
     	//获取月份
     		getMonth()
     	//获取日期
     		getDate()
     	//获取星期几		周一 —— 周日  [1,2,3,4,5,6,0]
     		getDay()		
     	//当月第一天的获取
     		new Date(year,month-1,1)
     	//当月第一天的获取
     		new Date(year,month,0)
    

    页面的布局
    table布局,head为星期,tbody为日期 以td的6*7的格式设置,

    核心数据的获取
    通过计算,获取当月的第一天是周几,最后一天是周几,然后获取上个月的最后一天是周几,这样就能获取日历当月的开头和结尾的非本月的日期以及合理的位置。

    展开全文
  • Android 自定义实现日历

    千次阅读 2018-09-24 11:06:01
    Android 自定义实现日历开发工具AndroidStudio,使用组件GridView实现步骤以及原理具体实现 开发工具AndroidStudio,使用组件GridView 实现步骤以及原理 通过Calendar获取当前年月日 获取指定年月的天数 得到当月...


    测试机为小米8

    开发工具AndroidStudio,使用组件GridView

    实现步骤以及原理

    1. 通过Calendar获取当前年月日
    2. 获取指定年月的天数
    3. 得到当月一号是星期几
    4. 获取日期对象的列表数据:当月天数加上当月1号星期几之前的空白数据(比如1号是星期3,那么日期列表数据之前添加三个数据)
    5. 设置GridView的适配器

    具体实现

    1. 用Calendar对象获取日期
      Calendar calendar = Calendar.getInstance(); currYear = calendar.get(Calendar.YEAR); currMouth = calendar.get(Calendar.MONTH);
    2. 获取对应年月的天数
        private int getMonthLastDay(int year, int month) {
          Calendar a = Calendar.getInstance();
          a.set(Calendar.YEAR, year);
          a.set(Calendar.MONTH, month - 1);
          a.set(Calendar.DATE, 1);//把日期设置为当月第一天
          a.roll(Calendar.DATE, -1);//日期回滚一天,也就是最后一天
          return a.get(Calendar.DATE);
      }
      
    3. 一号是星期几
    		Calendar calendar = Calendar.getInstance();
            int currYear = calendar.get(Calendar.YEAR);
            int currMouth = calendar.get(Calendar.MONTH) + 1;
            int currDay = calendar.get(Calendar.DAY_OF_MONTH);
            calendar.set(year, mouth - 1, 0);
    
            int i1 = calendar.get(Calendar.DAY_OF_WEEK);//这就是星期几
    
    1. 得到日期数据列表
     public void requestData() {
            last_state = 0;
            state_count = 0;
            ArrayList<DateInfo> datas = new ArrayList<>();
            Calendar calendar = Calendar.getInstance();
            int currYear = calendar.get(Calendar.YEAR);
            int currMouth = calendar.get(Calendar.MONTH) + 1;
            int currDay = calendar.get(Calendar.DAY_OF_MONTH);
            calendar.set(year, mouth - 1, 0);
    
            int i1 = calendar.get(Calendar.DAY_OF_WEEK);
            if (i1 > 6)//如果大于6天,也就是一个星期的天数,就不用添加,否则显示一行空白
                i1 = 0;
    
            for (int i = 0; i < i1; i++) {
                datas.add(new DateInfo(true));
            }
    
            for (int i = 0; i < getMonthLastDay(year, mouth); i++) {
                DateInfo data = new DateInfo(year, mouth, i + 1);
                if (currYear == year && currMouth == mouth && currDay == i + 1)
                    data.setToday(true);
                data.setState(new Random().nextInt(4));//设置这一天的状态的
                if (last_state == 0) {
                    last_state = data.getState();
                    state_count = 1;
                } else if (last_state == data.getState()) {
                    ++state_count;
                    datas.get(i + i1 - 1).setState_count(state_count);
                    data.setState_count(state_count);
                } else {
                    last_state = data.getState();
                    state_count = 1;
                }
                datas.add(data);
            }
      }
    
    1. 最后继承自BaseAdapter,设置GridView的适配器
    展开全文
  • 自定义时间日历控件解析

    千次阅读 2016-05-31 13:10:33
    自定义时间日历控件解析 在android开发中我们往往会遇到一些用...## 开发自定义时间日历步骤 ## 了解View的工作原理 编写继承自View的子类 为自定义View类增加属性 绘制控件 最后就是使用自定义控件 一些自定义方法

    自定义时间日历控件解析

    在android开发中我们往往会遇到一些用现有控件难以实现或者实现起来不太容易,且需要重复使用的时候,我们不可能每次都用复杂的代码来实现吧,这样不止浪费了时间,还要付出更多的精力来调试,这时我们就需要自己定义控件


    ## 开发自定义时间日历步骤 ##

    1. 了解View的工作原理
    2. 编写继承自View的子类
    3. 为自定义View类增加属性
    4. 绘制控件
    5. 最后就是使用自定义控件了
    6. 一些自定义方法

    我们些看一下效果图吧

    这里写图片描述这里写图片描述这里写图片描述这里写图片描述

    从这里我们不难看出我做的是组合自定也控件
    下面我们开始解析源代码吧

    了解View的工作原理

    Android系统的视图结构的设计也采用了组合模式,即View作为所有图形的基类,Viewgroup对View继承扩展为视图容器类。

    View定义了绘图的基本操作

    基本操作由三个函数完成:measure()、layout()、draw(),其内部又分别包含了onMeasure()、onLayout()、onDraw()三个子方法。具体操作如下:

    1、measure操作

     measure操作主要用于计算视图的大小,即视图的宽度和长度。在view中定义为final类型,要求子类不能修改。measure()函数中又会调用下面的函数:
    
     (1)onMeasure(),视图大小的将在这里最终确定,也就是说measure只是对onMeasure的一个包装,子类可以覆写onMeasure()方法实现自己的计算视图大小的方式,并通过setMeasuredDimension(width, height)保存计算结果。
    

    2、layout操作

     layout操作用于设置视图在屏幕中显示的位置。在view中定义为final类型,要求子类不能修改。layout()函数中有两个基本操作:
    
     (1)setFrame(l,t,r,b),l,t,r,b即子视图在父视图中的具体位置,该函数用于将这些参数保存起来;
    
     (2)onLayout(),在View中这个函数什么都不会做,提供该函数主要是为viewGroup类型布局子视图用的;
    

    3、draw操作

     draw操作利用前两部得到的参数,将视图显示在屏幕上,到这里也就完成了整个的视图绘制工作。子类也不应该修改该方法,因为其内部定义了绘图的基本操作:
    
     (1)绘制背景;
    
     (2)如果要视图显示渐变框,这里会做一些准备工作;
    
     (3)绘制视图本身,即调用onDraw()函数。在view中onDraw()是个空函数,也就是说具体的视图都要覆写该函数来实现自己的显示(比如TextView在这里实现了绘制文字的过程)。而对于ViewGroup则不需要实现该函数,因为作为容器是“没有内容“的,其包含了多个子view,而子View已经实现了自己的绘制方法,因此只需要告诉子view绘制自己就可以了,也就是下面的dispatchDraw()方法;
    
     (4)绘制子视图,即dispatchDraw()函数。在view中这是个空函数,具体的视图不需要实现该方法,它是专门为容器类准备的,也就是容器类必须实现该方法;
    
     (5)如果需要(应用程序调用了setVerticalFadingEdge或者setHorizontalFadingEdge),开始绘制渐变框;
    
     (6)绘制滚动条;
    
      从上面可以看出自定义View需要最少覆写onMeasure()和onDraw()两个方法。
    

    编写继承自View的子类

    因为事先了解我们要做什么,所以我选择了LinearLayout 来继承这样更方便我们的自定以控件的建立。

    public class CalendarPickView extends LinearLayout {
            public CalendarPickView(Context context) {
            super(context);
        }
    
        public CalendarPickView(Context context, AttributeSet attrs) {
            super(context, attrs);
           }

    为自定义View类增加属性

    我们知道每个控件都有它特有的属性,而这些属性都建立在attrs.xml文件下如果你有兴趣的话可以查看开发包SDK\platforms\android-19\data\res\values\attrs.xml
    自定义sttrs.xml代码如下

    <resources>
        <declare-styleable name="CalendarPickView">
            <attr name="dateFormatStr" format="string"></attr>
            <attr name="dateFormat">
                <enum name="date" value="0"></enum>
                <enum name="time" value="1"></enum>
            </attr>
        </declare-styleable>
        <declare-styleable name="AuthCodeView">
            <attr name="titleText" format="string"></attr>
            <attr name="titleTextColors" format="color"></attr>
            <attr name="titleTextSize" format="dimension"></attr>
        </declare-styleable>
    </resources>

    绘制控件

    控件的属性配置好后就开始绘制控件了,绘制控件有着多种方法

    第一种是在扩展的LinearLayout构造函数中使用Inflater加载一个布局,并从中提取出相关的UI组件进行封装,形成一个独立的控件。在使用该控件时,由于它所有的子元素都是在运行时通过代码动态创建的,所以该控件只能以一个独立控件的形式在Layout文件中声明

    第二种方式是:在自定义控件中声明它的所有子元素,然后在Layout文件中像使用LinearLayout一样去进行布局,不过切记:自定义控件Code中声明的UI元素必须与Layout文件中声明的元素保持一致,否则,在代码中无法找到对应的控件;最后,在自定义控件的onInflateFinish中通过findViewById将layout中声明的控件跟代码中声明的控件匹配起来

    第三种方式是:这个自定义VIEW中的任何控件都不是通过XML文件来定义的,而是在JAVA代码中通过动态生成的,然后再addView()加入到你自定义的View中

    而我们用的是第一种实列代码如下

     TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CalendarPickView);
            dateFormatStr = typedArray.getString(R.styleable.CalendarPickView_dateFormatStr);
            dateFormat = typedArray.getInteger(R.styleable.CalendarPickView_dateFormat, FORMAT_DATE);
            sdf = new SimpleDateFormat(dateFormatStr);
    //        LayoutInflater.from(context).inflate(R.layout.date_pick_txt,null);
            LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            layoutInflater.inflate(R.layout.date_pick_txt, this);
            editText = (EditText) findViewById(R.id.calendarEt);
            imageView = (ImageView) findViewById(R.id.calendarIv);
            processUi(context);
            typedArray.recycle();

    需要强调的是, TypeArray使用完毕后需要销毁,不然会发生内存泄露

    最后就是使用自定义控件了

    MainActivity的布局文件:先定义命名空间xmlns:uview=”http://schemas.android.com/apk/res/com.example.myimageview2” (com.example.myimageview2为你
    在manifest中定义的包名)
    也可以xmlns:uview=”http://schemas.android.com/apk/res-auto”指所有命名空间
    然后可以像使用系统的属性一样使用:uview:Oriental=”Vertical”

     <weizikeyi.com.customcontrols.CalendarPickView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            date:dateFormat="date"
            date:dateFormatStr="yyyy-MM-dd"
            />
        <weizikeyi.com.customcontrols.CalendarPickView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            date:dateFormat="time"
            date:dateFormatStr="HH-mm-SS"
         />

    注意控件的class,属性内置名,空间名要相同,不然会出现找不到属性的情况。

    一些自定义方法

    onFinishInflate() 回调方法,当应用从XML加载该组件并用它构建界面之后调用的方法

    onMeasure() 检测View组件及其子组件的大小

    onLayout() 当该组件需要分配其子组件的位置、大小时

    onSizeChange() 当该组件的大小被改变时

    onDraw() 当组件将要绘制它的内容时

    onKeyDown 当按下某个键盘时

    onKeyUp 当松开某个键盘时

    onTrackballEvent 当发生轨迹球事件时

    onTouchEvent 当发生触屏事件时

    onWindowFocusChanged(boolean) 当该组件得到、失去焦点时

    onAtrrachedToWindow() 当把该组件放入到某个窗口时

    onDetachedFromWindow() 当把该组件从某个窗口上分离时触发的方法

    onWindowVisibilityChanged(int): 当包含该组件的窗口的可见性发生改变时触发的方法


    凡人皆需侍奉

    展开全文
  • 自定义函数threshold方法,生成日历的各个边界值1)计算这个月总天数2)计算这个月第一天与最后一天,各是星期几3)计算日历中的第一个日期与最后一个日期...
  • 最近在开发中需要用到日历多选的功能,用户需要选择多个日期查询数据,Calender控件支持多选功能只需要设置SelectionMode="MultipleRange"就可以实现多选功能。我们的要求是点击日历图标的时候把日期控件...
  • C#自定义日历控件

    2014-06-13 16:33:26
    vs2005开发日历控件,界面美观,有自定义的事件。
  • CVCalendar,是一款 iOS 端的可以自定义视觉的日历应用,采用 Swift 编写。运行截图:开发环境要求:Xcode 7Swift 2.0 标签:CVCalendar
  • 自定义简单日历控件

    千次阅读 2018-02-27 10:13:01
    Android当中也提供了日历控件,但是各种嵌入在应用程序中的日历控件要提供的功能显然比系统控件要求高的多,这种情况下只能靠程序员手动开发自己的日历控件,现在来简单的实现一下。 实现效果 展示日期控件 ...
  • 但博计自带的下拉日历可能风格与具体开发的页面风格不相统一,而开发者想使用自己已经开发出的自定义下拉日历同时又不想完全摆脱方便快捷的博计报表。因此,开发者想了解如何在博计报表的开发中嵌入自己开发的下拉...
  • 最近在用ionic框架开发一个移动应用的项目,给了个需求给我,要实现一个日历,并能够给每个日期自定义样式,看了一下他用的组件,发现改不了,在网上找了一圈,也没发现比较满意的,那就自己动手,丰衣足食。...
  • 但润乾自带的下拉日历可能风格与具体开发的页面风格不相统一,而开发者想使用自己已经开发出的自定义下拉日历同时又不想完全摆脱方便快捷的快逸报表。因此,开发者想了解如何在快逸报表的开发中嵌入自己开发的下拉...
  • C# 开发备忘录(自定义日历

    千次阅读 2019-01-22 13:36:25
    C#开发自定义备忘录(自制精美日历)(用VS开发的winForm应用程序) 目录 1 有关信息 2 程序截图 3 该程序尚未完成的功能/不足之处 4 资源下载 5 源代码 5.1 项目结构 5.2 注意事项 5.3 MemorandumUI ...
  • 最近开发中需要好多各式各样的控件,其中就有一个是日历控件,网络上的自定义日历控件质量参差不齐,看了好多发现源码中都有bug,加上时间比较紧张,就找了一个普通的日历控件,二次封装了一下,希望能给大家提供...
  • 2. 需要对项目中的已有的ionic-datePicker插件进行兼容,需要改造这个签到组件,不影响其原来原有的选择日期的日历插件功能。 经过长途跋涉,万水千山只等闲,改造成功!很简单的! 看效果图: 对此,我专门开了一个...
  • ?来源:wenzhihao123https://www.jianshu.com/p/a2f102c728ce前言最近项目需要日历效果,考虑用第三方的反而不太适合设计需求,修改复杂...效果图:详解实现思路头部是一个自定义组合控件;显示一周的日期部分用Gri...
  • react 自定义日历组件

    2021-02-24 17:23:02
    基于hooks开发自定义日历组件,可以根据自己需要修改; image.png index.tsx import React, { useState } from "react"; import Taro from "@tarojs/taro"; import { View } from "@tarojs/components"; ...
  • 这个日历页跟我之前开发的任何一个页面都不太像,这个页面的所有模块之间都有关联,一个模块的数据层有任何修改,其他模块都要跟着改变,关联性非常强。具体如下图所示: 这只是一个基本流程的截图,当满足某些...
  • 自己开发sliverlight日历插件,可自主修改其各部分样式
  • 最近项目需要日历效果,考虑用第三方的反而不太适合设计需求,修改复杂,与其这样不入自己重新写一个干净的控件。虽不是什么牛逼控件,但是也需要我们能按照设计自己写出来。在此记录一下实现思路。效果图:实现思路...
  • 基于QCalendarWidget自定义日历控件

    千次阅读 2019-08-17 17:12:20
    所以只能参考网上的大神们的帖子,结合自己的项目需求,基于QCalendarWidget开发自定义日历控件。最终效果就是如下图所示了。 代码实现 BaseCalendarWidget类就是我们的自定义日历控件,主要的定义如下,继承于...
  • 之前开发任务中有涉及到年月日日历的切换效果,由于是需要联动,想到的方向大概有3种,要么通过处理view的touch事件,要么是通过自定义behavior去实现,要么是通过ViewDragHelper这个神器去实现,网上比较多的是通过...
  • 自定义日历控件-CalendarView

    千次阅读 2015-01-23 15:39:15
    我们在开发中会遇到使用到日历控件,下面就介绍一个自定义日历控件。 思路: 1.自定义类CalendarView继承LinearLayout,使用布局文件,显示布局。 2.使用ViewFlipper,里面添加GridView,当月的日期。 3.使用手势...
  • ?来源:wenzhihao123https://www.jianshu.com/p/a2f102c728ce前言最近项目需要日历效果,考虑用第三方的反而不太适合设计需求,修改复杂...效果图:详解实现思路头部是一个自定义组合控件;显示一周的日期部分用Gri...
  • android开发中,自定义控件的实现步骤,项目中实现日历控件如何标识事务
  • 自定义jquery ui日历

    2015-07-19 18:47:31
    自定义的jquery ui组件开发日历控件,和系统配置支持变更语言,变更时间格式,切换时区 $(function() { jQuery.widget("xway.Calendar", { _div : null, hide : function() { jQuery(document).off...
  • 前言在企业级开发中,我们经常会使用到日期控件。在以前的jquery框架项目中,我们通常会选择mydate 97。现在我们使用Angular框架,Material官网也为我们提供了Datepicker组件。对于日期的显示的格式,有很多种,比如...
  • 自定义view实现日历

    2017-11-07 11:01:45
    最近都在学习自定义view相关的知识,另外工作之余也在独立开发一款金融应用,因为作为程序员的我们,看这个看那个都觉得很简单,谁都会,真正着手时,fuck,都不知道从何下手。动手,writing the fuck code!

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 651
精华内容 260
关键字:

自定义开发日历