Android 签到日历(左右滑动)

先看一下效果图

根据项目需求选择合适的控件

 

下面这张图就是根据第一个日历进行的改动

 

1.创建一个类LunarHelper(阴历)



class LunarHelper {


    private final static int[] lunar_month_days = {1887, 0x1694, 0x16aa, 0x4ad5, 0xab6, 0xc4b7, 0x4ae, 0xa56, 0xb52a, 0x1d2a,
            0xd54, 0x75aa, 0x156a, 0x1096d, 0x95c, 0x14ae, 0xaa4d, 0x1a4c, 0x1b2a, 0x8d55, 0xad4, 0x135a, 0x495d, 0x95c,
            0xd49b, 0x149a, 0x1a4a, 0xbaa5, 0x16a8, 0x1ad4, 0x52da, 0x12b6, 0xe937, 0x92e, 0x1496, 0xb64b, 0xd4a, 0xda8,
            0x95b5, 0x56c, 0x12ae, 0x492f, 0x92e, 0xcc96, 0x1a94, 0x1d4a, 0xada9, 0xb5a, 0x56c, 0x726e, 0x125c, 0xf92d,
            0x192a, 0x1a94, 0xdb4a, 0x16aa, 0xad4, 0x955b, 0x4ba, 0x125a, 0x592b, 0x152a, 0xf695, 0xd94, 0x16aa, 0xaab5,
            0x9b4, 0x14b6, 0x6a57, 0xa56, 0x1152a, 0x1d2a, 0xd54, 0xd5aa, 0x156a, 0x96c, 0x94ae, 0x14ae, 0xa4c, 0x7d26,
            0x1b2a, 0xeb55, 0xad4, 0x12da, 0xa95d, 0x95a, 0x149a, 0x9a4d, 0x1a4a, 0x11aa5, 0x16a8, 0x16d4, 0xd2da,
            0x12b6, 0x936, 0x9497, 0x1496, 0x1564b, 0xd4a, 0xda8, 0xd5b4, 0x156c, 0x12ae, 0xa92f, 0x92e, 0xc96, 0x6d4a,
            0x1d4a, 0x10d65, 0xb58, 0x156c, 0xb26d, 0x125c, 0x192c, 0x9a95, 0x1a94, 0x1b4a, 0x4b55, 0xad4, 0xf55b,
            0x4ba, 0x125a, 0xb92b, 0x152a, 0x1694, 0x96aa, 0x15aa, 0x12ab5, 0x974, 0x14b6, 0xca57, 0xa56, 0x1526,
            0x8e95, 0xd54, 0x15aa, 0x49b5, 0x96c, 0xd4ae, 0x149c, 0x1a4c, 0xbd26, 0x1aa6, 0xb54, 0x6d6a, 0x12da,
            0x1695d, 0x95a, 0x149a, 0xda4b, 0x1a4a, 0x1aa4, 0xbb54, 0x16b4, 0xada, 0x495b, 0x936, 0xf497, 0x1496,
            0x154a, 0xb6a5, 0xda4, 0x15b4, 0x6ab6, 0x126e, 0x1092f, 0x92e, 0xc96, 0xcd4a, 0x1d4a, 0xd64, 0x956c, 0x155c,
            0x125c, 0x792e, 0x192c, 0xfa95, 0x1a94, 0x1b4a, 0xab55, 0xad4, 0x14da, 0x8a5d, 0xa5a, 0x1152b, 0x152a,
            0x1694, 0xd6aa, 0x15aa, 0xab4, 0x94ba, 0x14b6, 0xa56, 0x7527, 0xd26, 0xee53, 0xd54, 0x15aa, 0xa9b5, 0x96c,
            0x14ae, 0x8a4e, 0x1a4c, 0x11d26, 0x1aa4, 0x1b54, 0xcd6a, 0xada, 0x95c, 0x949d, 0x149a, 0x1a2a, 0x5b25,
            0x1aa4, 0xfb52, 0x16b4, 0xaba, 0xa95b, 0x936, 0x1496, 0x9a4b, 0x154a, 0x136a5, 0xda4, 0x15ac};

    private final static int[] solar_1_1 = {1887, 0xec04c, 0xec23f, 0xec435, 0xec649, 0xec83e, 0xeca51, 0xecc46, 0xece3a,
            0xed04d, 0xed242, 0xed436, 0xed64a, 0xed83f, 0xeda53, 0xedc48, 0xede3d, 0xee050, 0xee244, 0xee439, 0xee64d,
            0xee842, 0xeea36, 0xeec4a, 0xeee3e, 0xef052, 0xef246, 0xef43a, 0xef64e, 0xef843, 0xefa37, 0xefc4b, 0xefe41,
            0xf0054, 0xf0248, 0xf043c, 0xf0650, 0xf0845, 0xf0a38, 0xf0c4d, 0xf0e42, 0xf1037, 0xf124a, 0xf143e, 0xf1651,
            0xf1846, 0xf1a3a, 0xf1c4e, 0xf1e44, 0xf2038, 0xf224b, 0xf243f, 0xf2653, 0xf2848, 0xf2a3b, 0xf2c4f, 0xf2e45,
            0xf3039, 0xf324d, 0xf3442, 0xf3636, 0xf384a, 0xf3a3d, 0xf3c51, 0xf3e46, 0xf403b, 0xf424e, 0xf4443, 0xf4638,
            0xf484c, 0xf4a3f, 0xf4c52, 0xf4e48, 0xf503c, 0xf524f, 0xf5445, 0xf5639, 0xf584d, 0xf5a42, 0xf5c35, 0xf5e49,
            0xf603e, 0xf6251, 0xf6446, 0xf663b, 0xf684f, 0xf6a43, 0xf6c37, 0xf6e4b, 0xf703f, 0xf7252, 0xf7447, 0xf763c,
            0xf7850, 0xf7a45, 0xf7c39, 0xf7e4d, 0xf8042, 0xf8254, 0xf8449, 0xf863d, 0xf8851, 0xf8a46, 0xf8c3b, 0xf8e4f,
            0xf9044, 0xf9237, 0xf944a, 0xf963f, 0xf9853, 0xf9a47, 0xf9c3c, 0xf9e50, 0xfa045, 0xfa238, 0xfa44c, 0xfa641,
            0xfa836, 0xfaa49, 0xfac3d, 0xfae52, 0xfb047, 0xfb23a, 0xfb44e, 0xfb643, 0xfb837, 0xfba4a, 0xfbc3f, 0xfbe53,
            0xfc048, 0xfc23c, 0xfc450, 0xfc645, 0xfc839, 0xfca4c, 0xfcc41, 0xfce36, 0xfd04a, 0xfd23d, 0xfd451, 0xfd646,
            0xfd83a, 0xfda4d, 0xfdc43, 0xfde37, 0xfe04b, 0xfe23f, 0xfe453, 0xfe648, 0xfe83c, 0xfea4f, 0xfec44, 0xfee38,
            0xff04c, 0xff241, 0xff436, 0xff64a, 0xff83e, 0xffa51, 0xffc46, 0xffe3a, 0x10004e, 0x100242, 0x100437,
            0x10064b, 0x100841, 0x100a53, 0x100c48, 0x100e3c, 0x10104f, 0x101244, 0x101438, 0x10164c, 0x101842,
            0x101a35, 0x101c49, 0x101e3d, 0x102051, 0x102245, 0x10243a, 0x10264e, 0x102843, 0x102a37, 0x102c4b,
            0x102e3f, 0x103053, 0x103247, 0x10343b, 0x10364f, 0x103845, 0x103a38, 0x103c4c, 0x103e42, 0x104036,
            0x104249, 0x10443d, 0x104651, 0x104846, 0x104a3a, 0x104c4e, 0x104e43, 0x105038, 0x10524a, 0x10543e,
            0x105652, 0x105847, 0x105a3b, 0x105c4f, 0x105e45, 0x106039, 0x10624c, 0x106441, 0x106635, 0x106849,
            0x106a3d, 0x106c51, 0x106e47, 0x10703c, 0x10724f, 0x107444, 0x107638, 0x10784c, 0x107a3f, 0x107c53,
            0x107e48};

    private static final String[] LUNAR_DAY = {"初一", "初二", "初三", "初四", "初五", "初六", "初七",
            "初八", "初九", "初十", "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八",
            "十九", "二十", "廿一", "廿二", "廿三", "廿四", "廿五", "廿六", "廿七", "廿八", "廿九", "三十"};

    private static final String[] LUNAR_MONTH = {"正月", "二月", "三月", "四月", "五月",
            "六月", "七月", "八月", "九月", "十月", "冬月", "腊月"};

    private final static String[] LUNAR_HOLIDAY = new String[]{"0101-春节",
            "0115-元宵节", "0505-端午节", "0707-七夕", "0815-中秋节", "0909-重阳节"};


    private Lunar lunar = new Lunar();
    private int lastYear, lastMonth, lastDay;
    private int lastLunarDay;

    private void setLastData(int year, int month, int day) {
        lastYear = year;
        lastMonth = month;
        lastDay = day;
        lastLunarDay = lunar.lunarDay;
    }

    private boolean initLastData(int year, int month, int day) {
        //如果阳历是当在同一年,同一月,day是lastDay的后一天,并且
        //阴历lastLunarDay<29的时候,
        //此时的阴历直接在前天的基础上加1,否则重新计算
        //返回结果是需不需要重新计算,true为重新计算,
        // false为在前一天的基础上已经修改了,直接可以使用lunar实例
        if (lastYear == year && lastMonth == month && day - lastDay == 1) {
            if (lastLunarDay > 0 && lastLunarDay < 29) {
                lunar.lunarDay = lastLunarDay + 1;
                return false;
            }
        }
        return true;
    }

    /**
     * 公历转农历
     */
    String SolarToLunarString(int year, int month, int day) {
        Lunar l;
        if (initLastData(year, month, day)) {
            l = SolarToLunar(year, month, day);
        } else {
            l = lunar;
        }
        setLastData(year, month, day);
        if (l.lunarDay == 1) {
            if (l.lunarMonth == 1) {
                return "春节";
            }
            return LUNAR_MONTH[l.lunarMonth - 1];
        } else {
            String lunar = String.format("%s.%s", l.lunarMonth, l.lunarDay);
            switch (lunar) {
                case "1.15":
                    return "元宵节";
                case "5.5":
                    return "端午节";
                case "7.7":
                    return "七夕";
                case "8.15":
                    return "中秋节";
                case "9.9":
                    return "重阳节";
                default:
                    return LUNAR_DAY[l.lunarDay - 1];
            }
        }
    }

    /**
     * 公历转农历
     */
    private Lunar SolarToLunar(int year, int month, int day) {
        int index = year - solar_1_1[0];
        int data = (year << 9) | (month << 5) | day;
        int solar11;
        if (solar_1_1[index] > data) {
            index--;
        }
        solar11 = solar_1_1[index];
        int y = GetBitInt(solar11, 12, 9);
        int m = GetBitInt(solar11, 4, 5);
        int d = GetBitInt(solar11, 5, 0);
        long offset = SolarToInt(year, month, day) - SolarToInt(y, m, d);

        int days = lunar_month_days[index];
        int leap = GetBitInt(days, 4, 13);

        int lunarY = index + solar_1_1[0];
        int lunarM = 1;
        int lunarD = 1;
        offset += 1;

        for (int i = 0; i < 13; i++) {
            int dm = GetBitInt(days, 1, 12 - i) == 1 ? 30 : 29;
            if (offset > dm) {
                lunarM++;
                offset -= dm;
            } else {
                break;
            }
        }
        lunarD = (int) (offset);
        lunar.lunarYear = lunarY;
        lunar.lunarMonth = lunarM;
        lunar.isleap = false;
        if (leap != 0 && lunarM > leap) {
            lunar.lunarMonth = lunarM - 1;
            if (lunarM == leap + 1) {
                lunar.isleap = true;
            }
        }

        lunar.lunarDay = lunarD;
        return lunar;
    }

    private static int GetBitInt(int data, int length, int shift) {
        return (data & (((1 << length) - 1) << shift)) >> shift;
    }

    private static long SolarToInt(int y, int m, int d) {
        m = (m + 9) % 12;
        y = y - m / 10;
        return 365 * y + y / 4 - y / 100 + y / 400 + (m * 306 + 5) / 10 + (d - 1);
    }

    private static class Lunar {
        boolean isleap;
        int lunarDay;
        int lunarMonth;
        int lunarYear;
    }


}

2.ZWCalendar(第一个日历)



class ZWCalendar extends View {

    private String[] weekTitles = new String[]{"日", "一", "二", "三", "四", "五", "六"};
    private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);
    private Calendar calendar = Calendar.getInstance();
    //今天所在的年月日信息
    private int currentYear, currentMonth, currentDay;
    //点击选中的年月日信息
    private int clickYear, clickMonth, clickDay;
    //当前选择的年月信息
    private int selectYear, selectMonth;
    private GregorianCalendar date = new GregorianCalendar();
    private HashMap<String, Boolean> signRecords;
    private GestureDetectorCompat detectorCompat;
    private Bitmap signSuccess, signError;
    private ZWCalendarView.Config config;
    private Paint paint = new Paint();
    private LunarHelper lunarHelper;
    private int itemWidth, itemHeight;
    private float solarTextHeight;
    private int currentPosition;
    private float signDelay;


    public ZWCalendar(Context context) {
        super(context);
    }

    public ZWCalendar(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ZWCalendar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    void init(ZWCalendarView.Config config) {
        this.config = config;
        currentYear = calendar.get(Calendar.YEAR);
        currentMonth = calendar.get(Calendar.MONTH);
        currentDay = calendar.get(Calendar.DAY_OF_MONTH);
        selectYear = currentYear;
        selectMonth = currentMonth;
        clickYear = currentYear;
        clickMonth = currentMonth;
        clickDay = currentDay;
        detectorCompat = new GestureDetectorCompat(getContext(), gestureListener);
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.FILL);
        paint.setTextAlign(Paint.Align.CENTER);
        paint.setStrokeWidth(sp2px(0.6f));
        currentPosition = (currentYear - 1970) * 12 + currentMonth + 1;
        setClickable(true);
        if (config.isShowLunar) lunarHelper = new LunarHelper();
        if (config.signIconSuccessId != 0) {
            signSuccess = BitmapFactory.decodeResource(getResources(), config.signIconSuccessId);
            signError = BitmapFactory.decodeResource(getResources(), config.signIconErrorId);
            if (signSuccess != null) {
                int width = signSuccess.getWidth();
                int height = signSuccess.getHeight();
                Matrix matrix = new Matrix();
                matrix.postScale(config.signIconSize / width, config.signIconSize / height);
                signSuccess = Bitmap.createBitmap(signSuccess, 0, 0, width, height, matrix, true);
                signError = Bitmap.createBitmap(signError, 0, 0, width, height, matrix, true);
            }
        }
    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        itemWidth = getWidth() / 7;
        itemHeight = (getHeight() - (int) config.weekHeight) / 6;
        paint.setTextSize(config.calendarTextSize);
        solarTextHeight = getTextHeight();
        signDelay = getX(Math.min(itemHeight, itemWidth) / 2, -45);
    }

    final void selectDate(int position) {
        currentPosition = position - 1;
        selectYear = 1970 + currentPosition / 12;
        selectMonth = currentPosition % 12;
        invalidate();
    }

    final void initSelect(int clickYear, int clickMonth, int clickDay) {
        this.clickYear = clickYear;
        this.clickMonth = clickMonth;
        this.clickDay = clickDay;
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        paint.setColor(Color.LTGRAY);
        canvas.drawLine(0, config.weekHeight, 0, getHeight() - config.weekHeight, paint);
        //画日历顶部周的标题
        paint.setColor(config.weekBackgroundColor);
        canvas.drawRect(0, 0, getWidth(), config.weekHeight, paint);
        paint.setTextSize(config.weekTextSize);
        paint.setColor(config.weekTextColor);
        float delay = getTextHeight() / 4;
        for (int i = 0; i < 7; i++) {
            canvas.drawText(weekTitles[i], itemWidth * (i + 0.5f), config.weekHeight / 2 + delay, paint);
        }
        //画日历
        int year = 1970 + currentPosition / 12;
        int month = currentPosition % 12;
        calendar.set(year, month, 1);
        int firstDay = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        int selectMonthMaxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        //上一个月的最大天数
        calendar.add(Calendar.MONTH, -1);
        int previousMonthMaxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        delay = solarTextHeight / 4;
        if (config.isShowLunar) delay = 0;
        for (int i = 1; i <= 42; i++) {
            int copyI = i - 1;
            int x = (copyI % 7) * itemWidth + itemWidth / 2;
            int y = (copyI / 7) * itemHeight + itemHeight / 2 + (int) config.weekHeight + (int) delay;
            if (i <= firstDay) {//前一月数据
                if (!config.isShowOtherMonth) continue;
                int day = previousMonthMaxDay - firstDay + i;
                paint.setColor(config.otherMonthTextColor);
                paint.setTextSize(config.calendarTextSize);
                canvas.drawText(String.valueOf(day), x, y, paint);
                drawLunar(canvas, month == 0 ? (year - 1) : year, month == 0 ? 11 : (month - 1), day, x, y);
            } else if (i > selectMonthMaxDay + firstDay) {//后一月数据
                if (!config.isShowOtherMonth) continue;
                int day = i - firstDay - selectMonthMaxDay;
                paint.setColor(config.otherMonthTextColor);
                paint.setTextSize(config.calendarTextSize);
                canvas.drawText(String.valueOf(day), x, y, paint);
                drawLunar(canvas, month == 11 ? (year + 1) : year, month == 11 ? 0 : (month + 1), day, x, y);
            } else {//当前月数据
                int day = i - firstDay;
                if (year == currentYear && month == currentMonth && day == currentDay) {//今天
                    paint.setColor(config.todayTextColor);
                } else {//其他天
                    paint.setColor(config.calendarTextColor);
                }
                if (year == clickYear && month == clickMonth && day == clickDay) {//当前选中的一天
                    paint.setColor(config.selectColor);
                    canvas.drawCircle(x, y - delay, Math.min(itemHeight, itemWidth) / 2, paint);
                    paint.setColor(config.selectTextColor);
                }
                paint.setTextSize(config.calendarTextSize);
                drawSign(canvas, year, month, day, x, y);
                canvas.drawText(String.valueOf(day), x, y, paint);
                drawLunar(canvas, year, month, day, x, y);
            }
        }
    }


    private void drawLunar(Canvas canvas, int year, int month, int day, int x, int y) {
        if (config.isShowLunar) {
            if (year != clickYear || month != clickMonth || day != clickDay) {
                paint.setColor(config.lunarTextColor);
            }
            String lunar = lunarHelper.SolarToLunarString(year, month + 1, day);
            paint.setTextSize(config.lunarTextSize);
            canvas.drawText(lunar, x, y + solarTextHeight * 2 / 3, paint);
        }
    }

    private void drawSign(Canvas canvas, int year, int month, int day, int x, int y) {
        if (signSuccess == null || signRecords == null) return;
        date.set(year, month, day);
        String dateStr = format.format(date.getTime());
        if (signRecords.containsKey(dateStr)) {
            if (year != clickYear || month != clickMonth || day != clickDay) {
                paint.setColor(config.signTextColor);
            }
            if (signRecords.get(dateStr)) {
                canvas.drawBitmap(signSuccess, x + signDelay - config.signIconSize / 2,
                        y - signDelay - config.signIconSize / 2, paint);
            } else {
                canvas.drawBitmap(signError, x + signDelay - config.signIconSize / 2,
                        y - signDelay - config.signIconSize / 2, paint);
            }
        }
    }

    int[] getCurrentDayInfo() {
        return new int[]{currentYear, currentMonth, currentDay};
    }

    private float getX(float radius, int angle) {
        int centerX = 0;
        return (float) (centerX + radius * Math.cos(angle * 3.14 / 180));
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        detectorCompat.onTouchEvent(event);
        return super.onTouchEvent(event);
    }

    private GestureDetector.OnGestureListener
            gestureListener = new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onDown(MotionEvent e) {
            return super.onDown(e);
        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            int position = getPosition(e.getX(), e.getY());
            if (dateClickListener != null) {
                calendar.set(selectYear, selectMonth, 1);
                int firstDay = calendar.get(Calendar.DAY_OF_WEEK) - 1;
                calendar.set(selectYear, selectMonth, position - firstDay + 1);
                int year = calendar.get(Calendar.YEAR);
                int month = calendar.get(Calendar.MONTH);
                int day = calendar.get(Calendar.DAY_OF_MONTH);
                int week = calendar.get(Calendar.DAY_OF_WEEK) - 1;
                if (month == selectMonth) {
                    clickYear = year;
                    clickMonth = month;
                    clickDay = day;
                    invalidate();
                    dateClickListener.dateSelect(year, month, day, week);
                }
            }
            return super.onSingleTapUp(e);
        }
    };

    private int getPosition(float x, float y) {
        y -= config.weekHeight;
        int y1 = (int) (y / itemHeight);
        int x1 = (int) (x / itemWidth);
        return y1 * 7 + x1;
    }

    void setSignRecords(HashMap<String, Boolean> signRecords) {
        this.signRecords = signRecords;
    }

    private float sp2px(float spValue) {
        float fontScale = getContext().getResources().getDisplayMetrics().scaledDensity;
        return spValue * fontScale + 0.5f;
    }

    private float getTextHeight() {
        return paint.descent() - paint.ascent();
    }

    interface DateSelectListener {
        void dateSelect(int year, int month, int day, int week);
    }

    private DateSelectListener dateClickListener;

    void setDateSelectListener(DateSelectListener clickListener) {
        dateClickListener = clickListener;
    }


}

3.ZWCalendarView(第一个日历)


public class ZWCalendarView extends FrameLayout {

    private ArraySet<ZWCalendar> destroyViews = new ArraySet<>();
    private ArraySet<ZWCalendar> viewSet = new ArraySet<>();
    private int selectYear, selectMonth, selectDay, selectWeek;
    private HashMap<String, Boolean> signRecords;
    private int PAGER_SIZE = 1200;
    private Calendar calendar;
    private ViewPager pager;
    private Config config;

    public ZWCalendarView(Context context) {
        super(context);
        init(null, 0);
    }

    public ZWCalendarView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs, 0);
    }

    public ZWCalendarView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs, defStyleAttr);
    }

    private void init(AttributeSet attrs, int def) {
        config = new Config();
        //获取日历的UI配置
        TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.ZWCalendarView, def, 0);
        config.weekHeight = array.getDimension(R.styleable.ZWCalendarView_weekHeight, dip2px(30));
        config.weekBackgroundColor = array.getColor(R.styleable.ZWCalendarView_weekBackgroundColor, Color.WHITE);
        config.weekTextColor = array.getColor(R.styleable.ZWCalendarView_weekTextColor, Color.GRAY);
        config.weekTextSize = array.getDimension(R.styleable.ZWCalendarView_weekTextSize, sp2px(14));
        config.calendarTextColor = array.getColor(R.styleable.ZWCalendarView_calendarTextColor, Color.BLACK);
        config.calendarTextSize = array.getDimension(R.styleable.ZWCalendarView_calendarTextSize, sp2px(14));
        config.isShowOtherMonth = array.getBoolean(R.styleable.ZWCalendarView_isShowOtherMonth, false);
        if (config.isShowOtherMonth) {
            config.otherMonthTextColor = array.getColor(R.styleable.ZWCalendarView_otherMonthTextColor, Color.LTGRAY);
        }
        config.isShowLunar = array.getBoolean(R.styleable.ZWCalendarView_isShowLunar, false);
        if (config.isShowLunar) {
            config.lunarTextColor = array.getColor(R.styleable.ZWCalendarView_lunarTextColor, Color.LTGRAY);
            config.lunarTextSize = array.getDimension(R.styleable.ZWCalendarView_lunarTextSize, sp2px(11));
        }
        config.todayTextColor = array.getColor(R.styleable.ZWCalendarView_todayTextColor, Color.BLUE);
        config.selectColor = array.getColor(R.styleable.ZWCalendarView_selectColor, Color.BLUE);
        config.selectTextColor = array.getColor(R.styleable.ZWCalendarView_selectTextColor, Color.WHITE);
        config.signIconSuccessId = array.getResourceId(R.styleable.ZWCalendarView_signIconSuccessId, 0);
        config.signIconErrorId = array.getResourceId(R.styleable.ZWCalendarView_signIconErrorId, 0);
        if (config.signIconSuccessId != 0) {
            config.signIconSize = array.getDimension(R.styleable.ZWCalendarView_signIconSize, dip2px(16));
        }
        config.signTextColor = array.getColor(R.styleable.ZWCalendarView_signTextColor, Color.parseColor("#BA7436"));
        config.limitFutureMonth = array.getBoolean(R.styleable.ZWCalendarView_limitFutureMonth, false);
        array.recycle();
        initPager();
    }

    private float sp2px(float spValue) {
        float fontScale = getContext().getResources().getDisplayMetrics().scaledDensity;
        return spValue * fontScale + 0.5f;
    }

    private int dip2px(float dipValue) {
        final float scale = Resources.getSystem().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        int hMode = MeasureSpec.getMode(heightMeasureSpec);
        height = hMode == MeasureSpec.EXACTLY ? height : dip2px(220);
        setMeasuredDimension(widthMeasureSpec, height);
    }

    private void initPager() {
        pager = new ViewPager(getContext());
        addView(pager);
        pager.setOffscreenPageLimit(1);
        pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageSelected(int position) {
                if (listener == null) return;
                position -= 1;
                int year = 1970 + position / 12;
                int month = position % 12;
                listener.change(year, month + 1);
            }

            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });

        //选择当前日期
        calendar = Calendar.getInstance();
        selectYear = calendar.get(Calendar.YEAR);
        selectMonth = calendar.get(Calendar.MONTH);
        selectDay = calendar.get(Calendar.DAY_OF_MONTH);
        selectWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        int currentPosition = getPosition(selectYear, selectMonth);
        if (config.limitFutureMonth) PAGER_SIZE = currentPosition + 1;
        pager.setAdapter(new CVAdapter());
        pager.setCurrentItem(currentPosition, false);
    }

    private int getPosition(int year, int month) {
        return (year - 1970) * 12 + month + 1;
    }

    private class CVAdapter extends PagerAdapter {
        @Override
        public int getCount() {
            return PAGER_SIZE;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            ZWCalendar calendarView = getContent(position);
            container.addView(calendarView);
            return calendarView;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            destroyViews.add((ZWCalendar) object);
            container.removeView((View) object);
        }
    }

    private ZWCalendar getContent(int position) {
        ZWCalendar calendarView;
        if (destroyViews.size() != 0) {
            calendarView = destroyViews.valueAt(0);
            destroyViews.remove(calendarView);
        } else {
            calendarView = new ZWCalendar(getContext());
            calendarView.init(config);
            calendarView.setDateSelectListener(new ZWCalendar.DateSelectListener() {
                @Override
                public void dateSelect(int year, int month, int day, int week) {
                    selectYear = year;
                    selectMonth = month;
                    selectDay = day;
                    for (ZWCalendar view : viewSet) {
                        view.initSelect(selectYear, selectMonth, selectDay);
                    }
                    if (listener != null) {
                        listener.select(year, month + 1, day, week == 0 ? 7 : week);
                    }
                }
            });
            viewSet.add(calendarView);
        }
        calendarView.setSignRecords(signRecords);
        calendarView.selectDate(position);
        calendarView.setTag(position);
        return calendarView;
    }

    static class Config {
        float weekHeight;
        float weekTextSize;
        int weekBackgroundColor;
        int weekTextColor;
        float calendarTextSize;
        int calendarTextColor;
        boolean isShowOtherMonth;
        int otherMonthTextColor;
        boolean isShowLunar;
        int lunarTextColor;
        float lunarTextSize;
        int todayTextColor;
        int selectColor;
        int selectTextColor;
        int signIconSuccessId;
        int signIconErrorId;
        float signIconSize;
        int signTextColor;
        boolean limitFutureMonth;
    }

    /*---------------------------------------对外方法-----------------------------------*/

    public interface SelectListener {
        void change(int year, int month);

        void select(int year, int month, int day, int week);
    }

    private SelectListener listener;

    public void setSelectListener(SelectListener listener) {
        this.listener = listener;
        listener.change(selectYear, selectMonth + 1);
        selectWeek = selectWeek == 0 ? 7 : selectWeek;
        listener.select(selectYear, selectMonth + 1, selectDay, selectWeek);
    }


    public void selectDate(int year, int month, int day) {
        if (listener == null || year < 1970 || month < 1 || month > 12 || day < 1 || day > 31)
            return;
        month -= 1;
        calendar.set(year, month, day);
        int yearTemp = calendar.get(Calendar.YEAR);
        int monthTemp = calendar.get(Calendar.MONTH);
        int dayTemp = calendar.get(Calendar.DAY_OF_MONTH);
        if (yearTemp != year || monthTemp != month || dayTemp != day) return;
        selectYear = year;
        selectMonth = month;
        selectDay = day;
        for (ZWCalendar view : viewSet) {
            view.initSelect(selectYear, selectMonth, selectDay);
        }
        int position = getPosition(selectYear, selectMonth);
        pager.setCurrentItem(position, false);
        int week = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        listener.select(selectYear, selectMonth + 1, selectDay, week == 0 ? 7 : week);
    }

    public void selectMonth(int year, int month) {
        if (pager == null || year < 1970 || month < 1 || month > 12) return;
        int position = getPosition(year, month);
        pager.setCurrentItem(position, false);
    }

    /**
     * 设置签到记录
     *
     * @param signRecords 为日期格式像 "2017-08-25"
     */
    public void setSignRecords(final HashMap<String, Boolean> signRecords) {
        if (signRecords == null) return;
        this.signRecords = signRecords;
        for (ZWCalendar view : viewSet) {
            view.setSignRecords(signRecords);
            view.invalidate();
        }
    }

    public void showNextMonth() {
        if (pager != null) {
            int index = pager.getCurrentItem() + 1;
            pager.setCurrentItem(index, true);
        }
    }

    public void showPreviousMonth() {
        if (pager != null) {
            int index = pager.getCurrentItem() - 1;
            pager.setCurrentItem(index, true);
        }
    }

    public void backToday() {
        if (pager != null) {
            ZWCalendar item = (ZWCalendar) pager.findViewWithTag(pager.getCurrentItem());
            if (item != null) {
                int[] info = item.getCurrentDayInfo();
                selectDate(info[0], info[1] + 1, info[2]);
            }
        }
    }


}

4.ZWSignCalendar(第二个日历)



class ZWSignCalendar extends View {

    private String[] weekTitles = new String[]{"日", "一", "二", "三", "四", "五", "六"};
    private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);
    private Calendar calendar = Calendar.getInstance();
    //今天所在的年月日信息
    private int currentYear, currentMonth, currentDay;
    private GregorianCalendar date = new GregorianCalendar();
    private ZWSignCalendarView.Config config;
    private HashSet<String> signRecords;
    private Paint paint = new Paint();
    private LunarHelper lunarHelper;
    private int itemWidth, itemHeight;
    private float solarTextHeight;
    private int currentPosition;


    public ZWSignCalendar(Context context) {
        super(context);
    }

    public ZWSignCalendar(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ZWSignCalendar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    void init(ZWSignCalendarView.Config config) {
        this.config = config;
        currentYear = calendar.get(Calendar.YEAR);
        currentMonth = calendar.get(Calendar.MONTH);
        currentDay = calendar.get(Calendar.DAY_OF_MONTH);
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.FILL);
        paint.setTextAlign(Paint.Align.CENTER);
        paint.setStrokeWidth(sp2px(0.6f));
        currentPosition = (currentYear - 1970) * 12 + currentMonth + 1;
        setClickable(true);
        if (config.isShowLunar) lunarHelper = new LunarHelper();
    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        itemWidth = getWidth() / 7;
        itemHeight = (getHeight() - (int) config.weekHeight) / 6;
        paint.setTextSize(config.calendarTextSize);
        solarTextHeight = getTextHeight();
        if (config.signSize == 0) config.signSize = Math.min(itemHeight, itemWidth);
    }

    final void selectDate(int position) {
        currentPosition = position - 1;
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        paint.setColor(Color.LTGRAY);
        canvas.drawLine(0, config.weekHeight, 0, getHeight() - config.weekHeight, paint);
        //画日历顶部周的标题
        paint.setColor(config.weekBackgroundColor);
        canvas.drawRect(0, 0, getWidth(), config.weekHeight, paint);
        paint.setTextSize(config.weekTextSize);
        paint.setColor(config.weekTextColor);
        float delay = getTextHeight() / 4;
        for (int i = 0; i < 7; i++) {
            canvas.drawText(weekTitles[i], itemWidth * (i + 0.5f), config.weekHeight / 2 + delay, paint);
        }
        //画日历
        int year = 1970 + currentPosition / 12;
        int month = currentPosition % 12;
        calendar.set(year, month, 1);
        int firstDay = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        int selectMonthMaxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        delay = solarTextHeight / 4;
        if (config.isShowLunar) delay = 0;
        for (int i = 1; i <= selectMonthMaxDay; i++) {
            int position = i - 1 + firstDay;
            int x = (position % 7) * itemWidth + itemWidth / 2;
            int y = (position / 7) * itemHeight + itemHeight / 2 + (int) config.weekHeight + (int) delay;
            int day = i;
            //签到背景
            boolean isSign = false;
            if (signRecords != null) {
                date.set(year, month, day);
                String dateStr = format.format(date.getTime());
                if (signRecords.contains(dateStr)) {
                    paint.setColor(config.signColor);
                    canvas.drawCircle(x, y, config.signSize / 2, paint);
                    isSign = true;
                }
            }
            //农历
            if (config.isShowLunar) {
                paint.setColor(isSign ? config.signTextColor : config.lunarTextColor);
                String lunar = lunarHelper.SolarToLunarString(year, month + 1, day);
                paint.setTextSize(config.lunarTextSize);
                canvas.drawText(lunar, x, y + solarTextHeight * 2 / 3, paint);
            }
            //阳历
            if (isSign) {
                paint.setColor(config.signTextColor);
            } else if (year == currentYear && month == currentMonth && day == currentDay) {//今天
                paint.setColor(config.todayTextColor);
            } else {//其他天
                paint.setColor(config.calendarTextColor);
            }
            paint.setTextSize(config.calendarTextSize);
            canvas.drawText(String.valueOf(day), x, y, paint);
        }
    }

    void setSignRecords(HashSet<String> signRecords) {
        this.signRecords = signRecords;
    }

    private float sp2px(float spValue) {
        float fontScale = getContext().getResources().getDisplayMetrics().scaledDensity;
        return spValue * fontScale + 0.5f;
    }

    private float getTextHeight() {
        return paint.descent() - paint.ascent();
    }


}

5.ZWSignCalendarView(第二个日历)


public class ZWSignCalendarView extends FrameLayout {

    private ArraySet<ZWSignCalendar> destroyViews = new ArraySet<>();
    private ArraySet<ZWSignCalendar> viewSet = new ArraySet<>();
    private HashSet<String> signRecords;
    private int PAGER_SIZE = 1200;
    private ViewPager pager;
    private Config config;
    private int currentPosition;

    public ZWSignCalendarView(Context context) {
        super(context);
        init(null, 0);
    }

    public ZWSignCalendarView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs, 0);
    }

    public ZWSignCalendarView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs, defStyleAttr);
    }

    private void init(AttributeSet attrs, int def) {
        config = new Config();
        //获取日历的UI配置
        TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.ZWSignCalendarView, def, 0);
        config.weekHeight = array.getDimension(R.styleable.ZWSignCalendarView_weekHeight, dip2px(30));
        config.weekBackgroundColor = array.getColor(R.styleable.ZWSignCalendarView_weekBackgroundColor, Color.WHITE);
        config.weekTextColor = array.getColor(R.styleable.ZWSignCalendarView_weekTextColor, Color.GRAY);
        config.weekTextSize = array.getDimension(R.styleable.ZWSignCalendarView_weekTextSize, sp2px(14));
        config.calendarTextColor = array.getColor(R.styleable.ZWSignCalendarView_calendarTextColor, Color.BLACK);
        config.calendarTextSize = array.getDimension(R.styleable.ZWSignCalendarView_calendarTextSize, sp2px(14));
        config.isShowLunar = array.getBoolean(R.styleable.ZWSignCalendarView_isShowLunar, false);
        if (config.isShowLunar) {
            config.lunarTextColor = array.getColor(R.styleable.ZWSignCalendarView_lunarTextColor, Color.LTGRAY);
            config.lunarTextSize = array.getDimension(R.styleable.ZWSignCalendarView_lunarTextSize, sp2px(11));
        }
        config.todayTextColor = array.getColor(R.styleable.ZWSignCalendarView_todayTextColor, Color.BLUE);
        config.signSize = array.getDimension(R.styleable.ZWSignCalendarView_signSize, 0);
        config.signTextColor = array.getColor(R.styleable.ZWSignCalendarView_signTextColor, Color.parseColor("#BA7436"));
        config.limitFutureMonth = array.getBoolean(R.styleable.ZWSignCalendarView_limitFutureMonth, false);
        config.signColor = array.getColor(R.styleable.ZWSignCalendarView_signColor, Color.BLUE);
        array.recycle();
        initPager();
    }

    private float sp2px(float spValue) {
        float fontScale = getContext().getResources().getDisplayMetrics().scaledDensity;
        return spValue * fontScale + 0.5f;
    }

    private int dip2px(float dipValue) {
        final float scale = Resources.getSystem().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        int hMode = MeasureSpec.getMode(heightMeasureSpec);
        height = hMode == MeasureSpec.EXACTLY ? height : dip2px(220);
        setMeasuredDimension(widthMeasureSpec, height);
    }

    private void initPager() {
        pager = new ViewPager(getContext());
        addView(pager);
        pager.setOffscreenPageLimit(1);
        pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageSelected(int position) {
                if (listener == null) return;
                position -= 1;
                int year = 1970 + position / 12;
                int month = position % 12;
                listener.change(year, month + 1);
            }

            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });

        //选择当前日期
        Calendar calendar = Calendar.getInstance();
        final int year = calendar.get(Calendar.YEAR);
        final int month = calendar.get(Calendar.MONTH);
        currentPosition = getPosition(year, month);
        if (config.limitFutureMonth) PAGER_SIZE = currentPosition + 1;
        pager.setAdapter(new CVAdapter());
        pager.setCurrentItem(currentPosition, false);
        post(new Runnable() {
            public void run() {
                if (listener != null) listener.change(year, month + 1);
            }
        });
    }

    private int getPosition(int year, int month) {
        return (year - 1970) * 12 + month + 1;
    }

    private class CVAdapter extends PagerAdapter {
        @Override
        public int getCount() {
            return PAGER_SIZE;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            ZWSignCalendar calendarView = getContent(position);
            container.addView(calendarView);
            return calendarView;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            destroyViews.add((ZWSignCalendar) object);
            container.removeView((View) object);
        }
    }

    private ZWSignCalendar getContent(int position) {
        ZWSignCalendar calendarView;
        if (destroyViews.size() != 0) {
            calendarView = destroyViews.valueAt(0);
            destroyViews.remove(calendarView);
        } else {
            calendarView = new ZWSignCalendar(getContext());
            calendarView.init(config);
            viewSet.add(calendarView);
        }
        calendarView.setSignRecords(signRecords);
        calendarView.selectDate(position);
        calendarView.setTag(position);
        return calendarView;
    }

    static class Config {
        float weekHeight;
        float weekTextSize;
        int weekBackgroundColor;
        int weekTextColor;
        float calendarTextSize;
        int calendarTextColor;
        boolean isShowLunar;
        int lunarTextColor;
        float lunarTextSize;
        int todayTextColor;
        int signColor;
        float signSize;
        int signTextColor;
        boolean limitFutureMonth;
    }

    /*---------------------------------------对外方法-----------------------------------*/

    public interface DateListener {
        void change(int year, int month);
    }

    private DateListener listener;

    public void setDateListener(DateListener listener) {
        this.listener = listener;
    }


    public void selectMonth(int year, int month) {
        if (pager == null || year < 1970 || month < 1 || month > 12) return;
        int position = getPosition(year, month);
        pager.setCurrentItem(position, false);
    }

    /**
     * 设置签到记录
     *
     * @param signRecords 为日期格式像 "2017-08-25"
     */
    public void setSignRecords(final HashSet<String> signRecords) {
        if (signRecords == null) return;
        this.signRecords = signRecords;
        for (ZWSignCalendar view : viewSet) {
            view.setSignRecords(signRecords);
            view.invalidate();
        }
    }

    public void showNextMonth() {
        if (pager != null) {
            int index = pager.getCurrentItem() + 1;
            pager.setCurrentItem(index, true);
        }
    }

    public void showPreviousMonth() {
        if (pager != null) {
            int index = pager.getCurrentItem() - 1;
            pager.setCurrentItem(index, true);
        }
    }

    public void backCurrentMonth() {
        if (pager != null) {
            pager.setCurrentItem(currentPosition, false);
        }
    }


}

6.activity_main

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <ImageView
                android:id="@+id/calendar_previous"
                android:layout_width="60dp"
                android:layout_height="wrap_content"
                android:rotation="180"
                android:src="@mipmap/ic_launcher" />


            <TextView
                android:id="@+id/tv_calendar_show"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:gravity="center"
                android:padding="5dp"
                android:text="222"
                android:textColor="#333333"
                android:textSize="14sp" />

            <TextView
                android:id="@+id/tv_calendar_today"
                android:layout_width="60dp"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:padding="5dp"
                android:text="今天"
                android:textColor="#333333"
                android:textSize="14sp" />

            <ImageView
                android:id="@+id/calendar_next"
                android:layout_width="60dp"
                android:layout_height="wrap_content"
                android:src="@mipmap/ic_launcher" />
        </LinearLayout>

        <com.yjjk.date_two.ZWCalendarView
            android:id="@+id/calendarView"
            android:layout_width="match_parent"
            android:layout_height="250dp"
            app:calendarTextSize="14sp"
            app:isShowLunar="true"
            app:isShowOtherMonth="false"
            app:limitFutureMonth="true"
            app:lunarTextSize="9sp"
            app:selectColor="#5675F2"
            app:signIconErrorId="@mipmap/record_error"
            app:signIconSuccessId="@mipmap/record_success"
            app:signTextColor="@android:color/holo_green_dark"
            app:weekTextColor="#BA7436"
            app:weekTextSize="13sp">

        </com.yjjk.date_two.ZWCalendarView>

        <View
            android:layout_width="match_parent"
            android:layout_height="10dp"
            android:background="#999999" />


        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <ImageView
                android:id="@+id/calendar_previous2"
                android:layout_width="60dp"
                android:layout_height="wrap_content"
                android:rotation="180"
                android:src="@mipmap/ic_launcher" />


            <TextView
                android:id="@+id/tv_calendar_show2"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:gravity="center"
                android:padding="5dp"
                android:text="222"
                android:textColor="#333333"
                android:textSize="14sp" />

            <TextView
                android:id="@+id/tv_calendar_today2"
                android:layout_width="60dp"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:padding="5dp"
                android:text="今天"
                android:textColor="#333333"
                android:textSize="14sp" />

            <ImageView
                android:id="@+id/calendar_next2"
                android:layout_width="60dp"
                android:layout_height="wrap_content"
                android:src="@mipmap/ic_launcher" />
        </LinearLayout>

        <com.yjjk.date_two.ZWSignCalendarView
            android:id="@+id/calendarView2"
            android:layout_width="match_parent"
            android:layout_height="250dp"
            app:calendarTextSize="14sp"
            app:isShowLunar="true"
            app:isShowOtherMonth="false"
            app:limitFutureMonth="false"
            app:lunarTextSize="9sp"
            app:signColor="#5675F2"
            app:signSize="35sp"
            app:signTextColor="#FFFFFF"
            app:todayTextColor="@android:color/holo_red_light"
            app:weekTextColor="#BA7436"
            app:weekTextSize="13sp">

        </com.yjjk.date_two.ZWSignCalendarView>
    </LinearLayout>
</ScrollView>

7.MainActivity



public class MainActivity extends AppCompatActivity {

    private ZWCalendarView calendarView;
    private ZWSignCalendarView signCalendarView;
    private TextView show, show2;

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        calendarView = (ZWCalendarView) findViewById(R.id.calendarView);
        show = (TextView) findViewById(R.id.tv_calendar_show);
        show2 = (TextView) findViewById(R.id.tv_calendar_show2);
        calendarView.setSelectListener(new ZWCalendarView.SelectListener() {
            @Override
            public void change(int year, int month) {
                show.setText(String.format("%s 年 %s 月", year, month));
            }

            @Override
            public void select(int year, int month, int day, int week) {
                Toast.makeText(getApplicationContext(),
                        String.format("%s 年 %s 月 %s日,周%s", year, month, day, week),
                        Toast.LENGTH_SHORT).show();
            }
        });

        //代码选中一个日期
        show.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                calendarView.selectDate(2017, 9, 3);
            }
        });

        //前一月
        findViewById(R.id.calendar_previous).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                calendarView.showPreviousMonth();
            }
        });

        //后一月
        findViewById(R.id.calendar_next).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                calendarView.showNextMonth();
            }
        });

        //返回今天
        findViewById(R.id.tv_calendar_today).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                calendarView.backToday();
            }
        });

        HashMap<String, Boolean> sign = new HashMap<>();
        sign.put("2019-07-12", true);
        sign.put("2019-07-23", true);
        sign.put("2019-07-24", false);
        sign.put("2019-07-25", true);
        sign.put("2019-08-12", false);
        sign.put("2019-08-13", true);
        sign.put("2019-08-14", true);
        sign.put("2019-08-15", false);
        sign.put("2019-08-18", false);
        sign.put("2019-08-31", true);
        sign.put("2019-09-05", true);
        sign.put("2019-09-07", false);
        sign.put("2019-09-08", false);
        sign.put("2019-09-09", true);
        sign.put("2019-10-09", true);
        calendarView.setSignRecords(sign);


        //
        //
        /*------------------------------------------------------------------------------*/
        //
        //


        signCalendarView = (ZWSignCalendarView) findViewById(R.id.calendarView2);
        signCalendarView.setDateListener(new ZWSignCalendarView.DateListener() {
            @Override
            public void change(int year, int month) {
                show2.setText(String.format("%s 年 %s 月", year, month));
            }
        });

        show2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                signCalendarView.selectMonth(2017, 9);
            }
        });


        findViewById(R.id.calendar_previous2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                signCalendarView.showPreviousMonth();
            }
        });

        findViewById(R.id.calendar_next2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                signCalendarView.showNextMonth();
            }
        });

        findViewById(R.id.tv_calendar_today2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                signCalendarView.backCurrentMonth();
            }
        });

        HashSet<String> sign2 = new HashSet<>();
        sign2.add("2017-07-12");
        sign2.add("2017-07-23");
        sign2.add("2017-07-24");
        sign2.add("2017-07-25");
        sign2.add("2017-08-12");
        sign2.add("2017-08-13");
        sign2.add("2017-08-14");
        sign2.add("2017-08-15");
        sign2.add("2017-08-18");
        sign2.add("2017-08-31");
        sign2.add("2017-09-05");
        sign2.add("2017-09-07");
        sign2.add("2017-09-08");
        sign2.add("2017-09-09");
        sign2.add("2017-10-09");
        signCalendarView.setSignRecords(sign2);
    }
}

8.在values布局中创建arrt

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="ZWCalendarView">
        <attr name="weekHeight" />
        <attr name="weekTextSize" />
        <attr name="weekBackgroundColor" />
        <attr name="weekTextColor" />
        <attr name="calendarTextSize" />
        <attr name="calendarTextColor" />
        <attr name="isShowOtherMonth" format="boolean" />
        <attr name="otherMonthTextColor" format="color" />
        <attr name="isShowLunar" />
        <attr name="lunarTextColor" />
        <attr name="lunarTextSize" />
        <attr name="todayTextColor" />
        <attr name="selectColor" format="color" />
        <attr name="selectTextColor" format="color" />
        <attr name="signIconSuccessId" format="integer" />
        <attr name="signIconErrorId" format="integer" />
        <attr name="signIconSize" format="dimension" />
        <attr name="signTextColor" />
        <attr name="limitFutureMonth" />
    </declare-styleable>

    <attr name="weekHeight" format="dimension" />
    <attr name="weekTextSize" format="dimension" />
    <attr name="weekBackgroundColor" format="color" />
    <attr name="weekTextColor" format="color" />
    <attr name="calendarTextSize" format="dimension" />
    <attr name="calendarTextColor" format="color" />
    <attr name="isShowLunar" format="boolean" />
    <attr name="lunarTextColor" format="color" />
    <attr name="lunarTextSize" format="dimension" />
    <attr name="todayTextColor" format="color" />
    <attr name="signTextColor" format="color" />
    <attr name="limitFutureMonth" format="boolean" />

    <declare-styleable name="ZWSignCalendarView">
        <attr name="weekHeight" />
        <attr name="weekTextSize" />
        <attr name="weekBackgroundColor" />
        <attr name="weekTextColor" />
        <attr name="calendarTextSize" />
        <attr name="calendarTextColor" />
        <attr name="isShowLunar" />
        <attr name="lunarTextColor" />
        <attr name="lunarTextSize" />
        <attr name="todayTextColor" />
        <attr name="signColor" format="color" />
        <attr name="signSize" format="dimension" />
        <attr name="signTextColor" />
        <attr name="limitFutureMonth" />
    </declare-styleable>

</resources>

 


版权声明:本文为weixin_42630638原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。