1、引用: implementation 'com.haibin:calendarview:3.6.8'
2、xml
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context=".MainActivity">
<!-- navigation toolbar -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:background="#fff"
android:orientation="horizontal">
<TextView
android:id="@+id/iv_pre"
android:layout_width="64dp"
android:layout_height="64dp"
android:text="上月"
android:gravity="center"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true" />
<TextView
android:id="@+id/month_year_text_view"
android:layout_width="wrap_content"
android:layout_height="64dp"
android:layout_centerInParent="true"
android:layout_centerVertical="true"
android:gravity="center"
android:textSize="24sp"
android:textStyle="bold" />
<TextView
android:id="@+id/iv_next"
android:layout_width="64dp"
android:layout_height="64dp"
android:text="下月"
android:gravity="center"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" />
</RelativeLayout>
<com.haibin.calendarview.CalendarLayout
android:id="@+id/calendar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:orientation="vertical"
app:calendar_show_mode="only_month_view"
app:default_status="expand">
<!--current_day_text_color设置当天的文字颜色-->
<com.haibin.calendarview.CalendarView
android:id="@+id/calendar_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
app:calendar_match_parent="false"
app:calendar_padding="12dp"
app:day_text_size="16sp"
app:current_day_text_color="#00FF00"
app:current_day_lunar_text_color="#00FF00"
app:month_view_scrollable="true"
app:month_view_show_mode="mode_only_current"
app:month_view="com.demo.CustomMonthView"
app:week_bar_height="46dp"
app:week_start_with="sun"
app:select_mode="single_mode"
app:week_view_scrollable="false"
app:year_view_scrollable="false" />
</com.haibin.calendarview.CalendarLayout>
</LinearLayout>
3、Activity
public class MainActivity extends AppCompatActivity implements View.OnClickListener, CalendarView.OnCalendarSelectListener, CalendarView.OnCalendarInterceptListener {
private CalendarView mCalendarView;
private TextView mCurrentMonth;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
findViewById(R.id.iv_next).setOnClickListener(this);
findViewById(R.id.iv_pre).setOnClickListener(this);
mCalendarView = findViewById(R.id.calendar_view);
mCurrentMonth = findViewById(R.id.month_year_text_view);
mCurrentMonth.setText(mCalendarView.getCurYear() + "-" + mCalendarView.getCurMonth());
mCalendarView.setOnCalendarSelectListener(this);
//设置日期拦截事件,当前有效
mCalendarView.setOnCalendarInterceptListener(this);
Map<String, Calendar> map = new HashMap<>();
map.put(getSchemeCalendar(2021, 3, 18, 0xFFFF0000, "火").toString(),
getSchemeCalendar(2021, 3, 18, 0xFFFF0000, "火"));
//28560 数据量增长不会影响UI响应速度,请使用这个API替换
mCalendarView.setSchemeDate(map);
}
private Calendar getSchemeCalendar(int year, int month, int day, int color, String text) {
Calendar calendar = new Calendar();
calendar.setYear(year);
calendar.setMonth(month);
calendar.setDay(day);
calendar.setSchemeColor(color);//如果单独标记颜色、则会使用这个颜色
calendar.setScheme(text);
return calendar;
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.iv_next:
mCalendarView.scrollToNext(true);
Log.d("zz", "getCurMonth:" + mCalendarView.getCurMonth());
break;
case R.id.iv_pre:
mCalendarView.scrollToPre(false);
break;
}
}
@Override
public void onCalendarOutOfRange(Calendar calendar) {
}
/**
* 日历选中的监听
*
* @param calendar
* @param isClick
*/
@Override
public void onCalendarSelect(Calendar calendar, boolean isClick) {
String tempYearMonth = mCurrentMonth.getText().toString().trim();
if (tempYearMonth.equals(calendar.getYear() + "-" + calendar.getMonth())) {//年月相等
LogUtil.d("aaaa", "111111");
//日点击
} else {
//切换月份
LogUtil.d("aaaa", "222222");
}
mCurrentMonth.setText(calendar.getYear() + "-" + calendar.getMonth());
}
/**
* 屏蔽某些不可点击的日期,可根据自己的业务自行修改
* 如 calendar > 2018年1月1日 && calendar <= 2020年12月31日
*
* @param calendar calendar
* @return 是否屏蔽某些不可点击的日期,MonthView和WeekView有类似的API可调用
*/
@Override
public boolean onCalendarIntercept(Calendar calendar) {
int day = calendar.getDay();
return day == 1 || day == 3 || day == 6 || day == 11 ||
day == 12 || day == 15 || day == 20 || day == 26;
// return calendar.hasScheme();
// return calendar.getYear()<= mCalendarView.getCurYear() &&
// calendar.getMonth() <= mCalendarView.getCurMonth() &&
// calendar.getDay() < mCalendarView.getCurDay();
}
@Override
public void onCalendarInterceptClick(Calendar calendar, boolean isClick) {
LogUtil.d("InterceptClick:" + isClick);
Toast.makeText(this,
calendar.toString() + (isClick ? "拦截不可点击" : "拦截设定为无效日期"),
Toast.LENGTH_SHORT).show();
}
4、CustomMonthView
package com.zswl.demo;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import com.haibin.calendarview.Calendar;
import com.haibin.calendarview.MonthView;
/**
* 演示月视图
*/
public class CustomMonthView extends MonthView {
private int mRadius;
/**
* 自定义魅族标记的文本画笔
*/
private Paint mTextPaint = new Paint();
/**
* 24节气画笔
*/
private Paint mSolarTermTextPaint = new Paint();
/**
* 背景圆点
*/
private Paint mPointPaint = new Paint();
/**
* 今天的背景色
*/
private Paint mCurrentDayPaint = new Paint();
/**
* 圆点半径
*/
private float mPointRadius;
private int mPadding;
private float mCircleRadius;
/**
* 自定义魅族标记的圆形背景
*/
private Paint mSchemeBasicPaint = new Paint();
private float mSchemeBaseLine;
public CustomMonthView(Context context) {
super(context);
mTextPaint.setTextSize(dipToPx(context, 8));
mTextPaint.setColor(0xffffffff);
mTextPaint.setAntiAlias(true);
mTextPaint.setFakeBoldText(true);
mSolarTermTextPaint.setColor(0xff489dff);
mSolarTermTextPaint.setAntiAlias(true);
mSolarTermTextPaint.setTextAlign(Paint.Align.CENTER);
mSchemeBasicPaint.setAntiAlias(true);
mSchemeBasicPaint.setStyle(Paint.Style.FILL);
mSchemeBasicPaint.setTextAlign(Paint.Align.CENTER);
mSchemeBasicPaint.setFakeBoldText(true);
mSchemeBasicPaint.setColor(Color.WHITE);
mCurrentDayPaint.setAntiAlias(true);
mCurrentDayPaint.setStyle(Paint.Style.FILL);
mCurrentDayPaint.setColor(0xFFff5a00);//设置当天的背景
mPointPaint.setAntiAlias(true);
mPointPaint.setStyle(Paint.Style.FILL);
mPointPaint.setTextAlign(Paint.Align.CENTER);
mPointPaint.setColor(Color.RED);
mCircleRadius = dipToPx(getContext(), 7);
mPadding = dipToPx(getContext(), 3);
mPointRadius = dipToPx(context, 2);
Paint.FontMetrics metrics = mSchemeBasicPaint.getFontMetrics();
mSchemeBaseLine = mCircleRadius - metrics.descent + (metrics.bottom - metrics.top) / 2 + dipToPx(getContext(), 1);
}
@Override
protected void onPreviewHook() {
mSolarTermTextPaint.setTextSize(mCurMonthLunarTextPaint.getTextSize());
mRadius = Math.min(mItemWidth, mItemHeight) / 11 * 5;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
@Override
protected boolean onDrawSelected(Canvas canvas, Calendar calendar, int x, int y, boolean hasScheme) {
int cx = x + mItemWidth / 2;
int cy = y + mItemHeight / 2;
canvas.drawCircle(cx, cy, mRadius, mSelectedPaint);
return true;
}
@Override
protected void onDrawScheme(Canvas canvas, Calendar calendar, int x, int y) {
//画日历下方标记物圈圈
canvas.drawCircle(x + mItemWidth / 2, y + mItemHeight / 2 + mPadding * 3, mPointRadius, mSchemePaint);
}
@SuppressWarnings("IntegerDivisionInFloatingPointContext")
@Override
protected void onDrawText(Canvas canvas, Calendar calendar, int x, int y, boolean hasScheme, boolean isSelected) {
// LogUtil.d("isSelected:"+isSelected);
int cx = x + mItemWidth / 2;
int cy = y + mItemHeight / 2;
int top = y - mItemHeight / 6;
LogUtil.d("cx:" + cx);
LogUtil.d("cy:" + cy);
LogUtil.d("top:" + top);
float baselineY = mTextBaseLine + y;
boolean isEnable = !onCalendarIntercept(calendar);
if (calendar.isCurrentDay() && !isSelected) {
canvas.drawCircle(cx, cy, mRadius, mCurrentDayPaint);
}
// if (hasScheme) {
// canvas.drawCircle(x + mItemWidth - mPadding - mCircleRadius / 2, y + mPadding + mCircleRadius, mCircleRadius, mSchemeBasicPaint);
// mTextPaint.setColor(calendar.getSchemeColor());
// canvas.drawText(calendar.getScheme(), x + mItemWidth - mPadding - mCircleRadius, y + mPadding + mSchemeBaseLine, mTextPaint);
// }
//当然可以换成其它对应的画笔就不麻烦,
if (calendar.isWeekend() && calendar.isCurrentMonth()) {//周末变颜色
// mCurMonthTextPaint.setColor(0xFF489dff);
// mCurMonthLunarTextPaint.setColor(0xFF489dff);
// mSchemeTextPaint.setColor(0xFF489dff);
// mSchemeLunarTextPaint.setColor(0xFF489dff);
// mOtherMonthLunarTextPaint.setColor(0xFF489dff);
// mOtherMonthTextPaint.setColor(0xFF489dff);
} else {
mCurMonthTextPaint.setColor(0xff333333);
mCurMonthLunarTextPaint.setColor(0xffCFCFCF);
mSchemeTextPaint.setColor(0xff333333);
mSchemeLunarTextPaint.setColor(0xffCFCFCF);
mOtherMonthTextPaint.setColor(0xFFe1e1e1);
mOtherMonthLunarTextPaint.setColor(0xFFe1e1e1);
}
//y:mTextBaseLine + top
if (isSelected) {
canvas.drawText(String.valueOf(calendar.getDay()), cx, cy, mSelectTextPaint);
// canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + y + mItemHeight / 10, mSelectedLunarTextPaint);
} else if (hasScheme) {
canvas.drawText(String.valueOf(calendar.getDay()), cx, cy,
calendar.isCurrentMonth() && isEnable ? mSchemeTextPaint : mOtherMonthTextPaint);
// canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + y + mItemHeight / 10,
// !TextUtils.isEmpty(calendar.getSolarTerm()) ? mSolarTermTextPaint : mSchemeLunarTextPaint);
} else {
canvas.drawText(String.valueOf(calendar.getDay()), cx, cy,
calendar.isCurrentDay() ? mCurDayTextPaint :
calendar.isCurrentMonth() && isEnable ? mCurMonthTextPaint : mOtherMonthTextPaint);
// canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + y + mItemHeight / 10,
// calendar.isCurrentDay() ? mCurDayLunarTextPaint :
// calendar.isCurrentMonth() ? !TextUtils.isEmpty(calendar.getSolarTerm()) ? mSolarTermTextPaint :
// mCurMonthLunarTextPaint : mOtherMonthLunarTextPaint);
}
}
/**
* dp转px
*
* @param context context
* @param dpValue dp
* @return px
*/
private static int dipToPx(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}