自定义日历
日期的绘制日期点击事件日期的事件提醒日期的颜色设置
1. 日历的绘制
这是参考的网上的部分自定义日历加上自己的修改
public class MonthDateView extends View {
private static final int NUM_COLUMNS =
7;
private static final int NUM_ROWS =
6;
private final int touchSlop;
private Paint mPaint;
private int mDayColor = Color.parseColor(
"#000000");
private int mSelectDayColor = Color.parseColor(
"#ffffff");
private int mSelectBGColor = Color.parseColor(
"#1FC2F3");
private int mCurrentColor = Color.parseColor(
"#ff0000");
private int mCurrYear, mCurrMonth, mCurrDay;
private int mSelYear, mSelMonth, mSelDay;
private int mColumnSize, mRowSize;
private DisplayMetrics mDisplayMetrics;
private int mDaySize =
18;
private TextView tv_date, tv_week;
private int weekRow;
private int[][] daysString;
private int mCircleRadius =
4;
private DateClick dateClick;
private int mCircleColor = Color.parseColor(
"#ff0000");
private List<Integer> daysHasThingList;
private List<Integer> grayDayList;
private boolean grayDay =
false;
public MonthDateView(Context context, AttributeSet attrs) {
super(context, attrs);
mDisplayMetrics = getResources().getDisplayMetrics();
Calendar calendar = Calendar.getInstance();
mPaint =
new Paint();
mCurrYear = calendar.get(Calendar.YEAR);
mCurrMonth = calendar.get(Calendar.MONTH)+
1;
mCurrDay = calendar.get(Calendar.DATE);
setSelectYearMonth(mCurrYear, mCurrMonth, mCurrDay);
touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}
@Override
protected void onMeasure(
int widthMeasureSpec,
int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode == MeasureSpec.AT_MOST) {
heightSize = mDisplayMetrics.densityDpi *
200;
}
setMeasuredDimension(widthSize, heightSize);
}
@Override
protected void onDraw(Canvas canvas) {
initSize();
daysString =
new int[
6][
7];
mPaint.setTextSize(mDaySize * mDisplayMetrics.scaledDensity);
String dayString;
int mMonthDays = DateHelper.getMonthDays(mSelYear, mSelMonth);
int weekNumber = DateHelper.getFirstDayWeek(mSelYear, mSelMonth);
Log.d(
"DateView",
"DateView:" + mSelMonth +
"月1号周" + weekNumber);
for (
int day =
0; day < mMonthDays; day++) {
dayString = (day +
1) +
"";
int column = (day + weekNumber -
1) %
7;
int row = (day + weekNumber -
1) /
7;
daysString[row][column] = day +
1;
int startX = (
int) (mColumnSize * column + (mColumnSize - mPaint.measureText(dayString)) /
2);
int startY = (
int) (mRowSize * row + mRowSize /
2 - (mPaint.ascent() + mPaint.descent()) /
2);
drawCircle(row, column, day +
1, canvas);
if (dayString.equals(mSelDay +
"")) {
mPaint.setColor(mSelectDayColor);
}
else if (dayString.equals(mCurrDay +
"") && mCurrDay != mSelDay && mCurrMonth == mSelMonth) {
mPaint.setColor(mDayColor);
}
else {
mPaint.setColor(mDayColor);
}
canvas.drawText(dayString, startX, startY, mPaint);
if (tv_date !=
null) {
tv_date.setText(mSelYear +
"年" + mSelMonth +
"月");
}
if (tv_week !=
null) {
tv_week.setText(
"第" + weekRow +
"周");
}
}
}
private void drawCircle(
int row,
int column,
int day, Canvas canvas) {
if (daysHasThingList !=
null && daysHasThingList.size() >
0) {
if (!daysHasThingList.contains(day)) {
float circleX = (
float) (mColumnSize * column + mColumnSize *
0.5);
float circley = (
float) (mRowSize * row + mRowSize *
0.5);
canvas.drawCircle(circleX, circley, mCircleRadius, mPaint);
return;
}
mPaint.setColor(mCircleColor);
int startRecX = mColumnSize * column;
int endRecX = startRecX + mColumnSize;
mCircleRadius = (Math.abs(endRecX - startRecX)) *
2 /
7;
float circleX = (
float) (mColumnSize * column + mColumnSize *
0.5);
float circley = (
float) (mRowSize * row + mRowSize *
0.5);
canvas.drawCircle(circleX, circley, mCircleRadius, mPaint);
}
}
@Override
public boolean performClick() {
return super.performClick();
}
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:
int upX = (
int) event.getX();
int upY = (
int) event.getY();
if (Math.abs(upX - downX) < touchSlop && Math.abs(upY - downY) < touchSlop) {
performClick();
doClickAction((upX + downX) /
2, (upY + downY) /
2);
}
break;
}
return true;
}
/**
* 初始化列宽行高
*/
private void initSize() {
mColumnSize = getWidth() / NUM_COLUMNS;
mRowSize = getHeight() / NUM_ROWS;
}
/**
* 设置年月
*
* @param year
* @param month
*/
private void setSelectYearMonth(
int year,
int month,
int day) {
mSelYear = year;
mSelMonth = month;
mSelDay = day;
}
/**
* 执行点击事件
*
* @param x
* @param y
*/
private void doClickAction(
int x,
int y) {
int row = y / mRowSize;
int column = x / mColumnSize;
int mMonthDays = DateHelper.getMonthDays(mSelYear, mSelMonth);
setSelectYearMonth(mSelYear, mSelMonth, daysString[row][column]);
invalidate();
if (dateClick !=
null) {
dateClick.onClickOnDate();
}
}
/**
* 左点击,日历向后翻页
*/
public void onLeftClick() {
int year = mSelYear;
int month = mSelMonth;
int day = mSelDay;
if (month ==
1) {
year = mSelYear -
1;
month =
12;
}
else if (DateHelper.getMonthDays(year, month) == day) {
month = month -
1;
day = DateHelper.getMonthDays(year, month);
}
else {
month = month -
1;
}
setSelectYearMonth(year, month, day);
invalidate();
}
/**
* 右点击,日历向前翻页
*/
public void onRightClick() {
int year = mSelYear;
int month = mSelMonth;
int day = mSelDay;
if (month ==
12) {
year = mSelYear +
1;
month =
1;
}
else if (DateHelper.getMonthDays(year, month) == day) {
month = month +
1;
day = DateHelper.getMonthDays(year, month);
}
else {
month = month +
1;
}
setSelectYearMonth(year, month, day);
invalidate();
}
/**
* 获取选择的年份
*
* @return
*/
public int getmSelYear() {
return mSelYear;
}
/**
* 获取选择的月份
*
* @return
*/
public int getmSelMonth() {
return mSelMonth;
}
/**
* 获取选择的日期
*/
public int getmSelDay() {
return this.mSelDay;
}
/**
* 普通日期的字体颜色,默认黑色
*
* @param mDayColor
*/
public void setmDayColor(
int mDayColor) {
this.mDayColor = mDayColor;
}
/**
* 选择日期的颜色,默认为白色
*
* @param mSelectDayColor
*/
public void setmSelectDayColor(
int mSelectDayColor) {
this.mSelectDayColor = mSelectDayColor;
}
/**
* 选中日期的背景颜色,默认蓝色
*
* @param mSelectBGColor
*/
public void setmSelectBGColor(
int mSelectBGColor) {
this.mSelectBGColor = mSelectBGColor;
}
/**
* 当前日期不是选中的颜色,默认红色
*
* @param mCurrentColor
*/
public void setmCurrentColor(
int mCurrentColor) {
this.mCurrentColor = mCurrentColor;
}
/**
* 日期的大小,默认18sp
*
* @param mDaySize
*/
public void setmDaySize(
int mDaySize) {
this.mDaySize = mDaySize;
}
/**
* 设置显示当前日期的控件
*
* @param tv_date 显示日期
*/
public void setTextView(TextView tv_date) {
this.tv_date = tv_date;
invalidate();
}
/**
* 设置事务天数
*
* @param daysHasThingList
*/
public void setDaysHasThingList(List<Integer> daysHasThingList) {
this.daysHasThingList = daysHasThingList;
}
/**
* 设置事务天数
*
* @param grayDayList
*/
public void setGrayDayList(List<Integer> grayDayList) {
this.grayDayList = grayDayList;
grayDay =
true;
}
/***
* 设置圆圈的半径,默认为6
*
* @param mCircleRadius
*/
public void setmCircleRadius(
int mCircleRadius) {
this.mCircleRadius = mCircleRadius;
}
/**
* 设置圆圈的半径
*
* @param mCircleColor
*/
public void setmCircleColor(
int mCircleColor) {
this.mCircleColor = mCircleColor;
}
/**
* 设置日期的点击回调事件
*
* @author shiwei.deng
*/
public interface DateClick {
public void onClickOnDate();
}
/**
* 设置日期点击事件
*
* @param dateClick
*/
public void setDateClick(DateClick dateClick) {
this.dateClick = dateClick;
}
/**
* 跳转至今天
*/
public void setTodayToView() {
setSelectYearMonth(mCurrYear, mCurrMonth, mCurrDay);
invalidate();
}
绘制周一 -周日
public class WeekDayView extends View {
private int mWeedayColor = Color.parseColor(
"#000000");
private int mWeekendColor = Color.parseColor(
"#000000");
private int mWeekSize =
12;
private Paint paint;
private DisplayMetrics mDisplayMetrics;
private String[] weekString =
new String[]{
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat"};
public WeekDayView(Context context, AttributeSet attrs) {
super(context, attrs);
mDisplayMetrics = getResources().getDisplayMetrics();
paint =
new Paint();
}
@Override
protected void onMeasure(
int widthMeasureSpec,
int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if(heightMode == MeasureSpec.AT_MOST){
heightSize = mDisplayMetrics.densityDpi *
30;
}
setMeasuredDimension(widthSize, heightSize);
}
@Override
protected void onDraw(Canvas canvas) {
int width = getWidth();
int height = getHeight();
paint.setStyle(Paint.Style.FILL);
paint.setTextSize(mWeekSize * mDisplayMetrics.scaledDensity);
int columnWidth = width /
7;
for(
int i=
0;i < weekString.length;i++){
String text = weekString[i];
int fontWidth = (
int) paint.measureText(text);
int startX = columnWidth * i + (columnWidth - fontWidth)/
2;
int startY = (
int) (height/
2 - (paint.ascent() + paint.descent())/
2);
if(text.indexOf(
"日") > -
1|| text.indexOf(
"六") > -
1){
paint.setColor(mWeekendColor);
}
else{
paint.setColor(mWeedayColor);
}
canvas.drawText(text, startX, startY, paint);
}
}
/**
* 设置周一-五的颜色
* @return
*/
public void setmWeedayColor(
int mWeedayColor) {
this.mWeedayColor = mWeedayColor;
}
/**
* 设置周六、周日的颜色
* @param mWeekendColor
*/
public void setmWeekendColor(
int mWeekendColor) {
this.mWeekendColor = mWeekendColor;
}
/**
* 设置字体的大小
* @param mWeekSize
*/
public void setmWeekSize(
int mWeekSize) {
this.mWeekSize = mWeekSize;
}
/**
* 设置星期的形式
* @param weekString
* 默认值 "日","一","二","三","四","五","六"
*/
public void setWeekString(String[] weekString) {
this.weekString = weekString;
}
}
日期帮助类
public class DateHelper {
/**
* 默认的日期样式:yyyy-MM-dd
*/
public static final String DEFAULT_DATE_FORMAT =
"yyyy-MM-dd";
public static final String DATE_TIME_FORMAT_SHORT=
"yyyy-M-d H:m";
public static final String DATE_TIME_FORMAT_BIG_SHORT=
"yyyy-MM-dd HH:mm";
public static final String DATE_TIME_FORMAT=
"yyyy-MM-dd HH:mm:ss";
public static final int YEAR =
1;
public static final int MONTH =
2;
public static final int DAY =
3;
public static final int HOUR =
4;
public static final int MINUTE =
5;
public static final int SECOND =
6;
public static final int MILLISECOND =
7;
public DateHelper(){
}
public static int getMonthDays(
int year,
int month) {
if (month >
12) {
month =
1;
year +=
1;
}
else if (month <
1) {
month =
12;
year -=
1;
}
int[] arr = {
31,
28,
31,
30,
31,
30,
31,
31,
30,
31,
30,
31 };
int days =
0;
if ((year %
4 ==
0 && year %
100 !=
0) || year %
400 ==
0) {
arr[
1] =
29;
}
try {
days = arr[month -
1];
}
catch (Exception e) {
e.getStackTrace();
}
return days;
}
public static int getYear() {
return Calendar.getInstance().get(Calendar.YEAR);
}
public static int getMonth() {
return Calendar.getInstance().get(Calendar.MONTH) +
1;
}
public static int getCurrentMonthDay() {
return Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
}
public static int getWeekDay() {
return Calendar.getInstance().get(Calendar.DAY_OF_WEEK);
}
/**
* 返回当前月份1号位于周几
* @param year
* 年份
* @param month
* 这个地方是我在绘制日历时候传入的正常的月份
* 需要做一个减1处理,这又有个地方是周日为第一天和周一为第一天是不一样的,需要自己做处理
* @return
* 日:1 一:2 二:3 三:4 四:5 五:6 六:7
*/
public static int getFirstDayWeek(
int year,
int month){
Calendar calendar = Calendar.getInstance();
int firstDayOfWeek = calendar.getFirstDayOfWeek();
Log.e(
"firstDayOfWeek",firstDayOfWeek+
"");
calendar.set(year, month-
1,
1);
int i1 = calendar.get(Calendar.DATE);
int i = calendar.get(Calendar.DAY_OF_WEEK);
return i;
}
}
日期layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.quwanbei.haihuilai.caledertest.MainActivity">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#ffffff"
android:gravity="center_vertical"
android:paddingTop="3dp">
<LinearLayout
android:id="@+id/date_operator_ll"
android:layout_width="fill_parent"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:layout_gravity="center_vertical"
android:gravity="center"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/iv_left"
android:padding="8dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@mipmap/last"
android:contentDescription="@null" />
</RelativeLayout>
<TextView
android:id="@+id/date_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:gravity="center_horizontal"
android:text=""
android:textColor="#1d1d1d"
android:textSize="18sp" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/iv_right"
android:padding="8dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@mipmap/next"
android:contentDescription="@null" />
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffff"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#f3f3f3" />
<com.quwanbei.haihuilai.caledertest.WeekDayView
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_marginTop="14dp" />
<com.quwanbei.haihuilai.caledertest.MonthDateView
android:id="@+id/monthDateView"
android:layout_width="fill_parent"
android:layout_height="200dp" />
</LinearLayout>
</LinearLayout>
Activity设置
public class MainActivity extends AppCompatActivity {
private RelativeLayout iv_left;
private RelativeLayout iv_right;
private MonthDateView monthDateView;
private TextView tv_date;
private ArrayList<String> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list =
new ArrayList<>();
list.add(
10+
"");
list.add(
12+
"");
list.add(
15+
"");
list.add(
16+
"");
iv_left = (RelativeLayout) findViewById(R.id.iv_left);
iv_right = (RelativeLayout) findViewById(R.id.iv_right);
monthDateView = (MonthDateView) findViewById(R.id.monthDateView);
tv_date = (TextView) findViewById(R.id.date_text);
monthDateView.setTextView(tv_date);
monthDateView.setDaysHasThingList(list);
monthDateView.setmCircleRadius(
60);
monthDateView.setmCircleColor(Color.parseColor(
"#ffda8c"));
monthDateView.setmSelectDayColor(Color.parseColor(
"#00beab"));
monthDateView.setmCurrentColor(Color.parseColor(
"#000000"));
monthDateView.setmDaySize(
14);
monthDateView.setDateClick(
new MonthDateView.DateClick() {
@Override
public void onClickOnDate() {
if(!list.contains(monthDateView.getmSelDay()+
"")) {
list.add(monthDateView.getmSelDay()+
"");
Toast.makeText(getApplication(),
"点击了:" + monthDateView.getmSelDay(), Toast.LENGTH_SHORT).show();
}
else{
list.remove(monthDateView.getmSelDay()+
"");
}
}
});
setOnlistener();
}
private void setOnlistener(){
iv_left.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
monthDateView.onLeftClick();
}
});
iv_right.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
monthDateView.onRightClick();
}
});
}
}
需要标注的地方都写有注释,有不明白的地方留言问我 刚开始写,技术不太好,多多指教。