package com.future.driver.utils.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
* Created by zhouyou on 2016/7/25.
* Class desc:
*
* 自定义日历View,可多选
*
*
*/
public class CalendarView extends View {
// 列的数量
private static final int NUM_COLUMNS = 7;
// 行的数量
private static final int NUM_ROWS = 6;
/**
* 可选日期数据
*/
private List mOptionalDates = new ArrayList<>();
private int nowDay = 0;
/**
* 以选日期数据
*/
private List mSelectedDates = new ArrayList<>();
/**
* 异常日期数据
*/
private List mErrorDates = new ArrayList<>();
// 分割线颜色
private int mDividerColor = Color.parseColor("#DEDEDE");
// 默认背景颜色和不可选背景色
private int mBgColor = Color.parseColor("#ffffff");
// 选中背景颜色
private int mSelectedColor = Color.parseColor("#F07207");
// 可选背景颜色
private int mAbleColor = Color.parseColor("#FFFFFF");
// 天数默认颜色
private int mDayNormalColor = Color.parseColor("#27282D");
//异常日期
private int mErrorColor = Color.parseColor("#FF5C5C");
// 天数不可选颜色
private int mDayNotOptColor = Color.parseColor("#BEBEC0");
// 天数选择后颜色
private int mDayPressedColor = Color.WHITE;
// 天数字体大小
private int mDayTextSize = 14;
// 是否可以被点击状态
private boolean mClickable = true;
//是否单选
private boolean mSingle = true;
private DisplayMetrics mMetrics;
private Paint mPaint;
private int mCurYear;
private int mCurMonth;
private int mCurDate;
private int mSelYear;
private int mSelMonth;
private int mSelDate;
private int mColumnSize;
private int mRowSize;
private int[][] mDays = new int[6][7];
// 当月一共有多少天
private int mMonthDays;
// 当月第一天位于周几
private int mWeekNumber;
public CalendarView(Context context) {
super(context);
init();
}
public CalendarView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CalendarView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
// 获取手机屏幕参数
mMetrics = getResources().getDisplayMetrics();
// 创建画笔
mPaint = new Paint();
mPaint.setAntiAlias(true);
// 获取当前日期
Calendar calendar = Calendar.getInstance();
mCurYear = calendar.get(Calendar.YEAR);
mCurMonth = calendar.get(Calendar.MONTH);
mCurDate = calendar.get(Calendar.DATE);
setSelYTD(mCurYear, mCurMonth, mCurDate);
nowDay = Integer.parseInt(getSelData(mCurYear, mCurMonth, mCurDate));
mSelectedDates.add(getSelData(mCurYear, mCurMonth, mCurDate));
}
@Override
protected void onDraw(Canvas canvas) {
initSize();
// 绘制背景
mPaint.setColor(mBgColor);
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), mPaint);
// 设置绘制字体大小
mPaint.setTextSize(mDayTextSize * mMetrics.scaledDensity);
// 绘制分割线
// mPaint.setColor(mDividerColor);
// for (int i = 1;i= nowDay) {
// 可选,继续判断是否是点击过的
if (!mSelectedDates.contains(getSelData(mSelYear, mSelMonth, mDays[row][column]))) {
// 没有点击过,绘制默认背景
// canvas.drawBitmap(mBgNotOptBitmap, startX - (mBgNotOptBitmap.getWidth() / 3), startY - (mBgNotOptBitmap.getHeight() / 2), mPaint);
mPaint.setColor(mAbleColor);
canvas.drawRect(column * mColumnSize, row * mRowSize, column * mColumnSize + mColumnSize, row * mRowSize + mRowSize, mPaint);
mPaint.setColor(mDayNormalColor);
} else {
// 点击过,绘制点击过的背景
// canvas.drawBitmap(mBgOptBitmap, startX - (mBgOptBitmap.getWidth() / 3), startY - (mBgOptBitmap.getHeight() / 2), mPaint);
mPaint.setColor(mSelectedColor);
// canvas.drawRect(column*mColumnSize,row*mRowSize,column*mColumnSize+mColumnSize,row*mRowSize+mRowSize,mPaint);
canvas.drawCircle(column * mColumnSize + 0.5f * mColumnSize, row * mRowSize + 0.5f * mRowSize, 0.4f * mColumnSize, mPaint);
mPaint.setColor(mDayPressedColor);
}
//是异常天数
if (mErrorDates.contains(getSelData(mSelYear, mSelMonth, mDays[row][column]))) {
mPaint.setColor(mErrorColor);
}
// 绘制天数
canvas.drawText(dayStr, startX, startY, mPaint);
} else {
//是异常天数
if (mErrorDates.contains(getSelData(mSelYear, mSelMonth, mDays[row][column]))) {
mPaint.setColor(mErrorColor);
} else
mPaint.setColor(mDayNotOptColor);
canvas.drawText(dayStr, startX, startY, mPaint);
}
}
}
private int downX = 0, downY = 0;
@Override
public boolean onTouchEvent(MotionEvent event) {
int eventCode = event.getAction();
switch (eventCode) {
case MotionEvent.ACTION_DOWN:
downX = (int) event.getX();
downY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
if (!mClickable) return true;
int upX = (int) event.getX();
int upY = (int) event.getY();
if (Math.abs(upX - downX) < 10 && Math.abs(upY - downY) < 10) {
performClick();
onClick((upX + downX) / 2, (upY + downY) / 2);
}
break;
}
return true;
}
public void setErrorDays(List errorDates){
this.mErrorDates = errorDates;
invalidate();
}
/**
* 点击事件
*/
private void onClick(int x, int y) {
int row = y / mRowSize;
int column = x / mColumnSize;
setSelYTD(mSelYear, mSelMonth, mDays[row][column]);
// 判断是否点击过
boolean isSelected = mSelectedDates.contains(getSelData(mSelYear, mSelMonth, mSelDate));
// 判断是否可以添加
boolean isCanAdd = Integer.parseInt(getSelData(mSelYear, mSelMonth, mDays[row][column])) >= nowDay;
if (isSelected) {
mSelectedDates.remove(getSelData(mSelYear, mSelMonth, mSelDate));
} else if (isCanAdd) {
if (mSingle)
mSelectedDates.clear();
mSelectedDates.add(getSelData(mSelYear, mSelMonth, mSelDate));
}
invalidate();
if (mListener != null && isCanAdd) {
// 执行回调
String dateStr = mSelYear + "-";
if (mSelMonth + 1 < 10)
dateStr = dateStr + "0" + (mSelMonth + 1) + "-";
else
dateStr = dateStr + (mSelMonth + 1) + "-";
if (mSelDate < 10)
dateStr = dateStr + "0" + mSelDate;
else
dateStr = dateStr + mSelDate;
mListener.onClickDateListener(dateStr);
}
}
public String getCurrent() {
String dateStr = mCurYear + "-";
if (mCurMonth + 1 < 10)
dateStr = dateStr + "0" + (mCurMonth + 1) + "-";
else
dateStr = dateStr + (mCurMonth + 1) + "-";
if (mCurDate < 10)
dateStr = dateStr + "0" + mCurDate;
else
dateStr = dateStr + mCurDate;
return dateStr;
}
public String getYM() {
String dateStr = mSelYear + "-";
if (mSelMonth + 1 < 10)
dateStr = dateStr + "0" + (mSelMonth + 1) ;
else
dateStr = dateStr + (mSelMonth + 1);
return dateStr;
}
/**
* 初始化列宽和高
*/
private void initSize() {
// 初始化每列的大小
mColumnSize = getWidth() / NUM_COLUMNS;
// 初始化每行的大小
mRowSize = getHeight() / NUM_ROWS;
}
/**
* 设置可选择日期
*
* @param dates 日期数据
*/
public void setOptionalDate(List dates) {
this.mOptionalDates = dates;
invalidate();
}
/**
* 设置已选日期数据
*/
public void setSelectedDates(List dates) {
this.mSelectedDates = dates;
}
/**
* 获取已选日期数据
*/
public List getSelectedDates() {
return mSelectedDates;
}
/**
* 设置日历是否可以点击
*/
@Override
public void setClickable(boolean clickable) {
this.mClickable = clickable;
}
/**
* 设置年月日
*
* @param year 年
* @param month 月
* @param date 日
*/
private void setSelYTD(int year, int month, int date) {
this.mSelYear = year;
this.mSelMonth = month;
this.mSelDate = date;
}
/**
* 设置上一个月日历
*/
public void setLastMonth() {
int year = mSelYear;
int month = mSelMonth;
int day = mSelDate;
// 如果是1月份,则变成12月份
if (month == 0) {
year = mSelYear - 1;
month = 11;
} else if (getMonthDays(year, month) == day) {
// 如果当前日期为该月最后一点,当向前推的时候,就需要改变选中的日期
month = month - 1;
day = getMonthDays(year, month);
} else {
month = month - 1;
}
setSelYTD(year, month, day);
invalidate();
}
/**
* 设置下一个日历
*/
public void setNextMonth() {
int year = mSelYear;
int month = mSelMonth;
int day = mSelDate;
// 如果是12月份,则变成1月份
if (month == 11) {
year = mSelYear + 1;
month = 0;
} else if (getMonthDays(year, month) == day) {
// 如果当前日期为该月最后一点,当向前推的时候,就需要改变选中的日期
month = month + 1;
day = getMonthDays(year, month);
} else {
month = month + 1;
}
setSelYTD(year, month, day);
invalidate();
}
/**
* 获取当前展示的年和月份
*
* @return 格式:2016年06月
*/
public String getDate() {
return mSelYear + "年" + (mSelMonth + 1) + "月";
}
/**
* 获取当前展示的日期
*
* @return 格式:20160606
*/
private String getSelData(int year, int month, int date) {
String monty, day;
month = (month + 1);
// 判断月份是否有非0情况
if ((month) < 10) {
monty = "0" + month;
} else {
monty = String.valueOf(month);
}
// 判断天数是否有非0情况
if ((date) < 10) {
day = "0" + (date);
} else {
day = String.valueOf(date);
}
return year + monty + day;
}
private OnClickListener mListener;
public interface OnClickListener {
void onClickDateListener(String date);
}
/**
* 设置点击回调
*/
public void setOnClickDate(OnClickListener listener) {
this.mListener = listener;
}
/**
* 通过年份和月份 得到当月的日子
*/
public static int getMonthDays(int year, int month) {
month++;
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
return 31;
case 4:
case 6:
case 9:
case 11:
return 30;
case 2:
if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) {
return 29;
} else {
return 28;
}
default:
return -1;
}
}
/**
* 返回当前月份1号位于周几
*
* @param year 年份
* @param month 月份,传入系统获取的,不需要正常的
* @return 日:1 一:2 二:3 三:4 四:5 五:6 六:7
*/
public static int getFirstDayWeek(int year, int month) {
Calendar calendar = Calendar.getInstance();
calendar.set(year, month, 1);
return calendar.get(Calendar.DAY_OF_WEEK);
}
/**
* 查询当前日期前(后)x天的日期
*
* @param date 当前日期
* @param day 天数(如果day数为负数,说明是此日期前的天数)
* @return yyyyMMdd
*/
private static String beforNumberDay(Date date, int day) {
Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(Calendar.DAY_OF_YEAR, day);
return new SimpleDateFormat("yyyyMMdd").format(c.getTime());
}
}