1. 程式人生 > >Android 自定義Calendar(上下左右滑動)

Android 自定義Calendar(上下左右滑動)

    新手小白第一次寫部落格記錄自己的學習過程,寫的不好希望各位大神別噴。望各位大大多多指教。

先發效果圖:

目錄:

一、自定義屬性attrs(定義一些控制元件自己的屬性)

<declare-styleable name="calendarattrs">
    <!---年相關-->
    <attr name="YearTextSize" format="dimension"/>
    <attr name="YearTextColor" format="reference|color"/>
    <!--月相關-->
    <attr name="MonthTextSize" format="dimension"/>
    <attr name="MonthTextColor" format="reference|color"/>
    <!--日相關-->
    <attr name="DayTextSize" format="dimension"/>
    <attr name="DayTextColor" format="reference|color"/>
    <!--星期相關-->
    <attr name="WeekTextSize" format="dimension"/>
    <attr name="WeekTextColor" format="reference|color"/>
    <attr name="WeekBackground" format="reference|color"/>
    <!--日曆內容相關-->
    <attr name="ContentTextSize" format="dimension"/>
    <attr name="ContentTextColor" format="reference|color"/>
    <attr name="SelectContentTextColor" format="reference|color"/>
    <attr name="SelectContentTextSize" format="dimension"/>
    <attr name="SelectContentBackground" format="color|reference"/>
    <attr name="SelectMode" format="integer"/>
    <attr name="SelectRadius" format="dimension" />

    <!--滑動相關 注:1為左右滑動 2為上下滑動-->
    <attr name="SlideDirection" format="integer"/>
</declare-styleable>

二、CalendarIntence單例(儲存自定義的屬性的值隨時獲取更新值)

public class CalendarIntence {

    public int MaxYear;  //最大年份
    public int MinYear;  //最小年份
    public int InitYear; //初始年份
    public int InitMonth; //初始月份
    public int InitDay;   //初始日期
    public int SelectMode; //選擇模式
    public int SlideDirection; //滑動模式
    public float YearTextSize; //年份字型大小
    public float MonthTextSize; //月份字型大小
    public float DayTextSize; //日期字型大小
    public float WeekTextSize; //星期字型大小
    public float ContentTextSize; //日期內容字型大小
    public float SelectRadius; //被選中日期背景半徑
    public int YearTextColor; //年份字型顏色
    public int MonthTextColor; //月份字型顏色
    public int DayTextColor; //日期字型顏色
    public int WeekTextColor; //星期字型顏色
    public int ContentTextColor;//內容字型顏色
    public int SelectContentTextColor; //選中內容字型顏色
    public int SelectContentBackground;//選中內容背景
    public int SelectContentTextSize; //選中內容的字型大小
    public int WeekBackground;   //星期欄背景
    public int Width,Height;
    private static final CalendarIntence INSTANCE = new CalendarIntence();

    private CalendarIntence() {
    }
    public static CalendarIntence getInstance() {
        return INSTANCE;
    }
}

三、自定義CalendarView(繼承View實現三個構造方法,改寫onDraw)

  1.檢視滑動效果主要在onDraw中實現通過不停的對畫布進行繪製與移動實現

  2.滑動功能主要為攔截onTouchEvent事件,通過手指點下的座標與移動的座標相減算出移動的距離實現

  3.點選獲取日期通過攔截onTochEvent事件計算手指點下與擡起座標是否等於0判斷是否為點選,而後通過座標與控制元件的寬高相除判斷日期所在的行列進行日期計算。最後在類中定義一個interface 將值傳輸到外部點選事件中。 


import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;

import com.example.lenovo.calendarmyself.R;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;


public class CalendarView extends View {

    private Calendar calendar;     //當前頁面日曆
    private Calendar calendarNext; //下一個頁面日曆
    private Calendar calendarPrevious;//上一個頁面日曆
    private Paint paintYear;    //繪製年份的畫筆
    private Paint paintMonth;   //繪製月份的畫筆
    private Paint paintDay;     //繪製日期的畫筆
    private Paint paintWeek;    //繪製日期的畫筆
    private Paint paintContent; //繪製內容的畫筆
    private Paint paintWeekBg;  //繪製星期欄的背景
    private Paint paintSelectContent;  //繪製被選中日期的內容
    private Paint paintSelectBg;    //繪製被選中日期的背景
    private Paint paintNextDay;     //繪製下個月日期的畫筆
    private int mWidth, mHeight;     //View的寬高
    private float mtitleHeight;     //標題欄的高度
    private float dtitleWidth, dtitleHeight;    //標題欄的範圍
    private float dtitlex, dtitley;   //標題欄的座標
    private float mweekHeight;      //星期欄的高度
    private float contentHeight;    //內容部分高度
    private float dcontentWidth, dcontentHeight;    //日期每一格的範圍
    private int columnWidth;         //每一列的寬度
    private String[] listWeek = {"日", "一", "二", "三", "四", "五", "六"};
    private int firstDayWeek;              //每月的第一天所在星期數
    private int lastDay;                  //每月的最後一天
    private int DataLineNum;              //行數
    private int FirstLineNum;             //第一行的資料數
    private int Linenum = 1;             //初始化行號
    private int j = 0;                   //記錄所遞迴的次數
    private int drawlastday;            //記錄每次所繪畫的最後一天
    private int scro;                   //滑動的距離
    private PointF pointF = new PointF();
    private float downx = 0, downy = 0;  //手指按下時的座標
    private float upx = 0, upy = 0;      //手指擡起時的座標
    private float movex, movey;         //手指移動中的座標
    private static final int UpState = 2;
    private static final int DownState = 1;
    private static final int LeftState = 3;
    private static final int RightState = 4;
    private static final int SelectState = 5;
    private int State = 0;                 //當前的狀態 初始為0
    private int change = 0;                //移動的距離
    private int changecalendar = 1;        //滑動第一次攔截
    private Bitmap bitmapNext;
    private Canvas canvasNext;
    private Bitmap bitmapPrevious;
    private Canvas canvasPrevious;
    private int isSelectday = 0;
    private float contentWidth1 = 0;
    private float contentHight1 = 0;

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

    public CalendarView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs, 0);
        calendar = Calendar.getInstance(Locale.CHINA);
        calendar.setTime(new Date());
        calendarNext = Calendar.getInstance(Locale.CHINA);
        calendarNext.setTime(new Date());
        monthChange(1, calendarNext);
        calendarPrevious = Calendar.getInstance(Locale.CHINA);
        calendarPrevious.setTime(new Date());
        monthChange(-1, calendarPrevious);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.calendarattrs, 0, 0);
        CalendarIntence.getInstance().YearTextSize = a.getDimensionPixelSize(R.styleable.calendarattrs_YearTextSize, 16);
        CalendarIntence.getInstance().YearTextColor = a.getColor(R.styleable.calendarattrs_YearTextColor, Color.BLACK);
        CalendarIntence.getInstance().MonthTextSize = a.getDimensionPixelSize(R.styleable.calendarattrs_MonthTextSize, 20);
        CalendarIntence.getInstance().MonthTextColor = a.getColor(R.styleable.calendarattrs_MonthTextColor, Color.BLACK);
        CalendarIntence.getInstance().DayTextSize = a.getDimensionPixelSize(R.styleable.calendarattrs_DayTextSize, 16);
        CalendarIntence.getInstance().DayTextColor = a.getColor(R.styleable.calendarattrs_DayTextColor, Color.BLACK);
        CalendarIntence.getInstance().ContentTextSize = a.getDimensionPixelSize(R.styleable.calendarattrs_ContentTextSize, 14);
        CalendarIntence.getInstance().ContentTextColor = a.getColor(R.styleable.calendarattrs_ContentTextColor, Color.BLACK);
        CalendarIntence.getInstance().WeekTextSize = a.getDimensionPixelSize(R.styleable.calendarattrs_WeekTextSize, 14);
        CalendarIntence.getInstance().WeekTextColor = a.getColor(R.styleable.calendarattrs_WeekTextColor, Color.BLACK);
        CalendarIntence.getInstance().SelectContentBackground = a.getColor(R.styleable.calendarattrs_SelectContentBackground, Color.BLUE);
        CalendarIntence.getInstance().SelectContentTextColor = a.getColor(R.styleable.calendarattrs_SelectContentTextColor, Color.BLACK);
        CalendarIntence.getInstance().SelectMode = a.getInt(R.styleable.calendarattrs_SelectMode, 0);
        CalendarIntence.getInstance().SelectRadius = a.getDimensionPixelSize(R.styleable.calendarattrs_SelectRadius, 10);
        CalendarIntence.getInstance().SlideDirection = a.getInt(R.styleable.calendarattrs_SlideDirection, 1);
        CalendarIntence.getInstance().SelectContentTextSize = a.getDimensionPixelSize(R.styleable.calendarattrs_SelectContentTextSize, 14);
        CalendarIntence.getInstance().WeekBackground = a.getColor(R.styleable.calendarattrs_WeekBackground, Color.WHITE);
        a.recycle();
    }

    public CalendarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int CalendarWidth = MeasureSpec.getSize(widthMeasureSpec);
        int Calendarheight = (int) (MeasureSpec.getSize(heightMeasureSpec) * 0.6);
        CalendarIntence.getInstance().Width = CalendarWidth;
        CalendarIntence.getInstance().Height = MeasureSpec.getSize(heightMeasureSpec);
        setMeasuredDimension(CalendarWidth, Calendarheight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        InitPaint();
        switch (State) {
            case 0:
                InitDate(calendar);
                Draw(canvas, calendar);
                break;
            case DownState:
                PageSwitchAnimation(-change, canvas);

                break;
            case UpState:
                PageSwitchAnimation(-change, canvas);
                break;
            case LeftState:
                PageSwitchAnimation(-change, canvas);
                break;
            case RightState:
                PageSwitchAnimation(-change, canvas);
                break;
            case SelectState:
                Draw(canvas, calendar);
                SelectDraw(canvas, pointF, isSelectday);
                break;
        }
    }

    private void CanvasClear(Canvas canvas) {
        try {
            Paint p = new Paint();
            p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
            canvas.drawPaint(p);
            p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
            canvas.drawPaint(p);
        } catch (Exception e) {
            Log.e("eee", e.getMessage());
        }

    }

    private void Draw(Canvas canvas, Calendar calendar) {
        DrawTitle(canvas, calendar);
        DrawWeek(canvas, listWeek);
        DrawContent(canvas, 1);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downx = event.getX();
                downy = event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                movex = event.getX();
                movey = event.getY();
                if (CalendarIntence.getInstance().SlideDirection == 1) {
                    scro = (int) (downx - movex);
                    change = scro;
                    if (change > 0) {
                        State = LeftState;
                        invalidate();
                    } else {
                        State = RightState;
                        invalidate();
                    }
                } else {
                    scro = (int) (downy - movey);
                    change = scro;
                    if (change > 0) {
                        State = UpState;
                        invalidate();
                    } else {
                        State = DownState;
                        invalidate();
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                upx = event.getX();
                upy = event.getY();
                if (upx - downx == 0.0 && upy - downy == 0.0) {
                    pointF.set(upx, upy);
                    isSelectday = onClick(pointF, true);
                    State = SelectState;
                    invalidate();
                } else {
                    State = 0;
                    changecalendar = 1;
                    if (scro > 0) {
                        monthChange(-1, calendar);
                        monthChange(-1, calendarNext);
                        monthChange(-1, calendarPrevious);
                    } else if (scro < 0) {
                        monthChange(1, calendar);
                        monthChange(1, calendarNext);
                        monthChange(1, calendarPrevious);
                    }
                    invalidate();
                }
                break;
            default:
                break;
        }
        return true;
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        InitLayout();
    }

    //初始化畫筆
    private void InitPaint() {
        paintYear = new Paint();
        paintYear.setTextSize(CalendarIntence.getInstance().YearTextSize);

        paintYear.setColor(CalendarIntence.getInstance().YearTextColor);
        paintYear.setAntiAlias(true);
        paintMonth = new Paint();
        paintMonth.setTextSize(CalendarIntence.getInstance().MonthTextSize);
        paintMonth.setColor(CalendarIntence.getInstance().MonthTextColor);
        paintMonth.setAntiAlias(true);
        paintDay = new Paint();
        paintDay.setTextSize(CalendarIntence.getInstance().DayTextSize);
        paintDay.setColor(CalendarIntence.getInstance().DayTextColor);
        paintDay.setAntiAlias(true);
        paintContent = new Paint();
        paintContent.setTextSize(CalendarIntence.getInstance().ContentTextSize);
        paintContent.setColor(CalendarIntence.getInstance().ContentTextColor);
        paintContent.setAntiAlias(true);
        paintWeek = new Paint();
        paintWeek.setTextSize(CalendarIntence.getInstance().WeekTextSize);
        paintWeek.setColor(CalendarIntence.getInstance().WeekTextColor);
        paintWeek.setAntiAlias(true);
        paintWeekBg = new Paint();
        paintWeekBg.setColor(CalendarIntence.getInstance().WeekBackground);
        paintSelectContent = new Paint();
        paintSelectContent.setColor(CalendarIntence.getInstance().SelectContentTextColor);
        paintSelectContent.setTextSize(CalendarIntence.getInstance().SelectContentTextSize);
        paintSelectContent.setAntiAlias(true);
        paintSelectBg = new Paint();
        paintSelectBg.setColor(CalendarIntence.getInstance().SelectContentBackground);
        paintSelectBg.setAntiAlias(true);
        paintNextDay = new Paint();
        paintNextDay.setTextSize(CalendarIntence.getInstance().ContentTextSize);
        paintNextDay.setColor(Color.GRAY);
    }

    //初始化佈局
    private void InitLayout() {
        mWidth = getWidth();
        mHeight = getHeight();
        columnWidth = getWidth() / 7;
        mtitleHeight = mHeight / 8;
        mweekHeight = mHeight / 10;
        contentHeight = mHeight - mtitleHeight - mweekHeight;
        DataLineNum = 6;                                            //日期顯示的行數預設6行
        dcontentHeight = contentHeight / DataLineNum;               //一個內容的高度
        dcontentWidth = columnWidth;                                //一個內容的寬度
        bitmapPrevious = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);         //建立一個bitmap用於繪畫
        canvasPrevious = new Canvas(bitmapPrevious);                                               //將bimap載入到畫布中
        bitmapNext = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);         //建立一個bitmap用於繪畫
        canvasNext = new Canvas(bitmapNext);                                               //將bimap載入到畫布中
    }

    private void InitDate(Calendar calendar) {
        calendar.set(Calendar.DAY_OF_MONTH, 1);                     //設定為當前月的一號
        firstDayWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;       //獲取一號所在的星期
        lastDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH); //獲取本月所在的最後一天
        FirstLineNum = 7 - firstDayWeek;                            //所在月份第1行有多少日期
    }

    private void DrawTitle(Canvas canvas, Calendar calendar) {
        String month = String.valueOf(calendar.get(Calendar.MONTH));
        int y = (int) (mtitleHeight / 3 * 2);
        int x1 = mWidth / 80 + columnWidth / 3;
        canvas.drawText(String.valueOf(calendar.get(Calendar.MONTH) + 1), x1, y, paintMonth);
        int x2 = (int) (x1 + paintMonth.measureText(month + 1) + paintMonth.measureText(month) / 2);//年份的x座標等於月份的起始座標+月份的寬度+加上1/3的月份寬度的邊距
        canvas.drawText(String.valueOf(calendar.get(Calendar.YEAR)), x2, y, paintYear);
        dtitleHeight = mtitleHeight;
        dtitleWidth = paintYear.measureText(String.valueOf(calendar.get(Calendar.MONTH) + 1)) + paintMonth.measureText(String.valueOf(calendar.get(Calendar.YEAR)));
        dtitlex = x1;
        dtitley = y;
    }

    private void DrawWeek(Canvas canvas, String[] week) {
        RectF f = new RectF(0, mtitleHeight - mweekHeight / 3, mWidth, mtitleHeight + mweekHeight);
        canvas.drawRect(f, paintWeekBg);
        for (int i = 0; i < listWeek.length; i++) {
            canvas.drawText(listWeek[i], columnWidth * i + columnWidth / 3, mtitleHeight + mweekHeight / 2, paintWeek);//星期欄Y座標為標題欄高度+星期欄高度的一半
        }
    }

    private void DrawContent(Canvas canvas, int day) {
        DrawContentOne(canvas, day);
        for (int i = 0; i < DataLineNum - 2; i++) {
            DrawContentMiddle(canvas, drawlastday);
        }
        DrawContentLast(canvas, drawlastday);
    }

    private void DrawContentOne(Canvas canvas, int day) {
        if (Linenum == 1) {
            if (day <= FirstLineNum) {
                canvas.drawText(String.valueOf(day), (columnWidth * firstDayWeek + columnWidth / 3) + columnWidth * j, mtitleHeight + mweekHeight + contentHeight / 6 * Linenum, paintContent);
                j = j + 1;
                DrawContentOne(canvas, day + 1);
            } else {
                j = 0;
                Linenum = Linenum + 1;
                drawlastday = day;
            }
        }
    }

    private void DrawContentMiddle(Canvas canvas, int day) {
        if (Linenum > 1 && Linenum < DataLineNum) {
            if (j < 7) {
                if (day <= lastDay) {
                    canvas.drawText(String.valueOf(day), (columnWidth / 3) + columnWidth * j, mtitleHeight + mweekHeight + contentHeight / 6 * Linenum, paintContent);
                    j = j + 1;
                    DrawContentMiddle(canvas, day + 1);
                } else {
                    canvas.drawText(String.valueOf(day - lastDay), (columnWidth / 3) + columnWidth * j, mtitleHeight + mweekHeight + contentHeight / 6 * Linenum, paintNextDay);
                    j = j + 1;
                    DrawContentMiddle(canvas, day + 1);
                }
            } else {
                j = 0;
                Linenum = Linenum + 1;
                drawlastday = day;
            }
        }
    }

    private void DrawContentLast(Canvas canvas, int day) {
        if (Linenum == DataLineNum) {
            if (j < 7) {
                if (day <= lastDay) {
                    canvas.drawText(String.valueOf(day), (columnWidth / 3) + columnWidth * j, mtitleHeight + mweekHeight + contentHeight / 6 * Linenum, paintContent);
                    j = j + 1;
                    DrawContentLast(canvas, day + 1);
                } else {
                    canvas.drawText(String.valueOf(day - lastDay), (columnWidth / 3) + columnWidth * j, mtitleHeight + mweekHeight + contentHeight / 6 * Linenum, paintNextDay);
                    j = j + 1;
                    DrawContentLast(canvas, day + 1);
                }
            }
            //繪製結束初始化變數
            Linenum = 1;
            j = 0;
        }
    }

    //改變月份
    private void monthChange(int change, Calendar calendar) {
        calendar.add(Calendar.MONTH, change);
    }

    private void PageSwitchAnimation(int change, Canvas canvas) {
        if (CalendarIntence.getInstance().SlideDirection == 1) {
            CanvasClear(canvas);
            canvas.drawColor(Color.WHITE);   // 解決清空畫布後畫布變成黑色的問題
            canvas.translate(change, 0);
            InitDate(calendar);
            Draw(canvas, calendar);
            InitDate(calendarNext);
            Draw(canvasNext, calendarNext);
            canvas.drawBitmap(bitmapNext, -mWidth, 0, paintContent);
            bitmapNext.recycle();
            bitmapNext = null;
            bitmapNext = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);         //建立一個bitmap用於繪畫
            canvasNext = new Canvas(bitmapNext);                                               //將bimap載入到畫布中
            InitDate(calendarPrevious);
            Draw(canvasPrevious, calendarPrevious);
            canvas.drawBitmap(bitmapPrevious, mWidth, 0, paintContent);
            bitmapPrevious.recycle();
            bitmapPrevious = null;
            bitmapPrevious = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);         //建立一個bitmap用於繪畫
            canvasPrevious = new Canvas(bitmapPrevious);                                               //將bimap載入到畫布中
            firstDayWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;                                  //恢復firstDayWeek所在月份的值用於點選事件
        } else {
            CanvasClear(canvas);
            canvas.drawColor(Color.WHITE);   // 解決清空畫布後畫布變成黑色的問題
            canvas.translate(0, change);
            InitDate(calendar);
            Draw(canvas, calendar);
            InitDate(calendarNext);
            Draw(canvasNext, calendarNext);
            canvas.drawBitmap(bitmapNext, 0, -mHeight, paintContent);
            bitmapNext.recycle();
            bitmapNext = null;
            bitmapNext = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);         //建立一個bitmap用於繪畫
            canvasNext = new Canvas(bitmapNext);                                               //將bimap載入到畫布中
            InitDate(calendarPrevious);
            Draw(canvasPrevious, calendarPrevious);
            canvas.drawBitmap(bitmapPrevious, 0, mHeight, paintContent);
            bitmapPrevious.recycle();
            bitmapPrevious = null;
            bitmapPrevious = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);         //建立一個bitmap用於繪畫
            canvasPrevious = new Canvas(bitmapPrevious);                                               //將bimap載入到畫布中
            firstDayWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;                                  //恢復firstDayWeek所在月份的值用於點選事件
        }
    }

    private int onClick(PointF p, boolean isclick) {
        int selectday = 0;
        if (p.x > 0 && p.y > mtitleHeight + mweekHeight) {
            int index = (int) (p.x / dcontentWidth);
            int indexy = (int) ((p.y - mtitleHeight - mweekHeight) / dcontentHeight);
            if ((p.x / columnWidth - index) > 0) {
                index += 1;
            }
            if (p.y / dcontentHeight - indexy > 0) {
                indexy += 1;
            }
            if (index <= 0)
                index = 1;   //避免調到上一行最後一個日期
            if (index > 7)
                index = 7;   //避免調到下一行第一個日期
            if (p.y < mtitleHeight + mweekHeight + contentHeight / 6) {
                if (p.x >= columnWidth * firstDayWeek) {
                    selectday = index - firstDayWeek;
                    int month = calendar.get(Calendar.MONTH) + 1;
                    int year = calendar.get(Calendar.YEAR);
                    invalidate();
                    listener.onDayClick(year, month, selectday);
                }
            } else {
                selectday = (7 - firstDayWeek) + (indexy - 2) * 7 + index;
                int month = calendar.get(Calendar.MONTH) + 1;
                int year = calendar.get(Calendar.YEAR);
                if (selectday <= lastDay) {
                    invalidate();
                    listener.onDayClick(year, month, selectday);
                }
            }
        }
        return selectday;
    }

    private onClickListener listener;

    public void setOnClickListener(onClickListener listener) {
        this.listener = listener;
    }

    public interface onClickListener {
        public abstract void onTitleClick(String monthStr, Date month);

        public abstract void onDayClick(int year, int month, int day);
    }

    public void JumpDate(int year, int month, int day) {
        try {
            calendar.setTime(TimeToData(year, month, day));
            calendarNext.setTime(TimeToData(year, month, day));
            calendarPrevious.setTime(TimeToData(year, month, day));
            monthChange(1, calendarNext);
            monthChange(-1, calendarPrevious);
            State = 0;
            invalidate();
        } catch (ParseException e) {
            e.printStackTrace();
        }

    }

    private Date TimeToData(int year, int month, int day) throws ParseException {
        String date = String.valueOf(year) + "-" + String.valueOf(month) + "-" + String.valueOf(day);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date da = simpleDateFormat.parse(date);
        return da;
    }

    private void SelectDraw(Canvas canvas, PointF p, int day) {
        contentWidth1 = paintContent.measureText(String.valueOf(day));
        contentHight1 = paintContent.ascent() + paintContent.descent();
        if (p.x > 0 && p.y > mtitleHeight + mweekHeight) {
            int index = (int) (p.x / dcontentWidth);
            int indexy = (int) ((p.y - mtitleHeight - mweekHeight) / dcontentHeight);
            if (p.y / dcontentHeight - indexy > 0) {
                indexy += 1;
            }
            if (index <= 0)
                index = 1;   //避免調到上一行最後一個日期
            if (index > 7)
                index = 7;   //避免調到下一行第一個日期
            if (day >= 1 && day <= lastDay) {
                canvas.drawCircle((columnWidth / 3) + columnWidth * index + contentWidth1 / 2, mtitleHeight + mweekHeight + indexy * contentHeight / 6 + contentHight1 / 2, columnWidth / 3, paintSelectBg);
                canvas.drawText(String.valueOf(day), (columnWidth / 3) + columnWidth * index, mtitleHeight + mweekHeight + indexy * contentHeight / 6, paintSelectContent);
            }
        }
    }
}

主方法:

calendarView = findViewById(R.id.cal);
linearLayout = findViewById(R.id.main);
bo = findViewById(R.id.button);
bo.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (CalendarIntence.getInstance().SlideDirection == 1) {
            CalendarIntence.getInstance().SlideDirection = 2;
        } else {
            CalendarIntence.getInstance().SlideDirection = 1;
        }
    }
});
calendarView.setOnClickListener(new CalendarView.onClickListener() {
    @Override
    public void onTitleClick(String monthStr, Date month) {

    }

    @Override
    public void onDayClick(int year, int month, int day) {
        Toast.makeText(MainActivity.this, String.valueOf(year) + "-" + String.valueOf(month) + "-" + String.valueOf(day), Toast.LENGTH_SHORT).show();
    }
});
calendarView.JumpDate(2016, 5, 5);

佈局檔案:

<LinearLayout 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"
    android:id="@+id/main"
    tools:context="com.example.lenovo.calendarmyself.MainActivity">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button"
        android:text="改變滑動方向"/>
    <View
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="4"/>
    <com.example.lenovo.calendarView.CalendarView
        android:id="@+id/cal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:YearTextSize="18sp"
        app:YearTextColor="@color/black"
        app:MonthTextSize="28sp"
        app:MonthTextColor="@color/black"
        app:WeekTextSize = "16sp"
        app:WeekTextColor = "@color/white"
        app:ContentTextSize="16sp"
        app:ContentTextColor ="@color/black"
        app:WeekBackground = "@color/blue"
        app:SelectContentTextColor="@color/white"
        app:SelectContentTextSize = "16sp"
        app:SelectContentBackground = "@color/selectbg"
        app:SlideDirection = "1"/>

</LinearLayout>