//日历calendar
implementation 'com.haibin:calendarview:3.6.8'
/**
* 演示一个变态需求的月视图
* Created by huanghaibin on 2018/2/9.
*/
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(0xFFeaeaea);
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 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) {
boolean isSelected = isSelected(calendar);
if (isSelected) {
mPointPaint.setColor(Color.WHITE);
} else {
mPointPaint.setColor(Color.GRAY);
}
canvas.drawCircle(x + mItemWidth / 2, y + mItemHeight - 3 * mPadding, mPointRadius, mPointPaint);
}
@SuppressWarnings("IntegerDivisionInFloatingPointContext")
@Override
protected void onDrawText(Canvas canvas, Calendar calendar, int x, int y, boolean hasScheme, boolean isSelected) {
int cx = x + mItemWidth / 2;
int cy = y + mItemHeight / 2;
int top = y - mItemHeight / 6;
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);
}
if (isSelected) {
canvas.drawText(String.valueOf(calendar.getDay()), cx, mTextBaseLine + top,
mSelectTextPaint);
canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + y + mItemHeight / 10, mSelectedLunarTextPaint);
} else if (hasScheme) {
canvas.drawText(String.valueOf(calendar.getDay()), cx, mTextBaseLine + top,
calendar.isCurrentMonth() ? 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, mTextBaseLine + top,
calendar.isCurrentDay() ? mCurDayTextPaint :
calendar.isCurrentMonth() ? 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);
}
}
public class CustomWeekView extends WeekView {
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 CustomWeekView(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);
mPointPaint.setAntiAlias(true);
mPointPaint.setStyle(Paint.Style.FILL);
mPointPaint.setTextAlign(Paint.Align.CENTER);
mPointPaint.setColor(Color.RED);
mCurrentDayPaint.setAntiAlias(true);
mCurrentDayPaint.setStyle(Paint.Style.FILL);
mCurrentDayPaint.setColor(0xFFeaeaea);
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 boolean onDrawSelected(Canvas canvas, Calendar calendar, int x, boolean hasScheme) {
int cx = x + mItemWidth / 2;
int cy = mItemHeight / 2;
canvas.drawCircle(cx, cy, mRadius, mSelectedPaint);
return true;
}
@Override
protected void onDrawScheme(Canvas canvas, Calendar calendar, int x) {
boolean isSelected = isSelected(calendar);
if (isSelected) {
mPointPaint.setColor(Color.WHITE);
} else {
mPointPaint.setColor(Color.GRAY);
}
canvas.drawCircle(x + mItemWidth / 2, mItemHeight - 3 * mPadding, mPointRadius, mPointPaint);
}
@SuppressWarnings("IntegerDivisionInFloatingPointContext")
@Override
protected void onDrawText(Canvas canvas, Calendar calendar, int x, boolean hasScheme, boolean isSelected) {
int cx = x + mItemWidth / 2;
int cy = mItemHeight / 2;
int top = -mItemHeight / 6;
if (calendar.isCurrentDay() && !isSelected) {
canvas.drawCircle(cx, cy, mRadius, mCurrentDayPaint);
}
if(hasScheme){
canvas.drawCircle(x + mItemWidth - mPadding - mCircleRadius / 2, mPadding + mCircleRadius, mCircleRadius, mSchemeBasicPaint);
mTextPaint.setColor(calendar.getSchemeColor());
canvas.drawText(calendar.getScheme(), x + mItemWidth - mPadding - mCircleRadius, 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);
}
if (isSelected) {
canvas.drawText(String.valueOf(calendar.getDay()), cx, mTextBaseLine + top,
mSelectTextPaint);
canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + mItemHeight / 10, mSelectedLunarTextPaint);
} else if (hasScheme) {
canvas.drawText(String.valueOf(calendar.getDay()), cx, mTextBaseLine + top,
calendar.isCurrentMonth() ? mSchemeTextPaint : mOtherMonthTextPaint);
canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + mItemHeight / 10,
!TextUtils.isEmpty(calendar.getSolarTerm()) ? mSolarTermTextPaint : mSchemeLunarTextPaint);
} else {
canvas.drawText(String.valueOf(calendar.getDay()), cx, mTextBaseLine + top,
calendar.isCurrentDay() ? mCurDayTextPaint :
calendar.isCurrentMonth() ? mCurMonthTextPaint : mOtherMonthTextPaint);
canvas.drawText(calendar.getLunar(), cx, mTextBaseLine + mItemHeight / 10,
calendar.isCurrentDay() ? mCurDayLunarTextPaint :
!TextUtils.isEmpty(calendar.getSolarTerm()) ? mSolarTermTextPaint :
calendar.isCurrentMonth() ?
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);
}
}
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CalendarView">
<attr name="calendar_padding" format="dimension" /><!--日历内部左右padding-->
<attr name="calendar_padding_left" format="dimension" /><!--日历内部左padding-->
<attr name="calendar_padding_right" format="dimension" /><!--日历内部右padding-->
<attr name="week_background" format="color" /><!--周背景-->
<attr name="week_line_background" format="color" /><!--线条颜色-->
<attr name="week_text_color" format="color" /><!--周栏字体颜色-->
<attr name="week_text_size" format="dimension" /><!--周栏字体大小-->
<attr name="week_line_margin" format="dimension" /><!--线条margin-->
<attr name="month_view" format="string" /><!--完全自定义月视图-->
<attr name="week_view" format="string" /> <!--完全自定义周视图-->
<attr name="year_view" format="string" /> <!--完全自定义年视图-->
<attr name="week_bar_height" format="dimension" /> <!--星期栏的高度-->
<attr name="week_bar_view" format="string" /> <!--如果需要的话使用自定义星期栏-->
<attr name="scheme_text" format="string" />
<attr name="day_text_size" format="dimension" />
<attr name="lunar_text_size" format="dimension" />
<attr name="calendar_height" format="dimension" />
<attr name="calendar_match_parent" format="boolean" /> <!-- 全屏日历 -->
<attr name="scheme_text_color" format="color" />
<attr name="scheme_month_text_color" format="color" />
<attr name="scheme_lunar_text_color" format="color" />
<attr name="scheme_theme_color" format="color" />
<attr name="selected_theme_color" format="color" />
<attr name="selected_text_color" format="color" />
<attr name="selected_lunar_text_color" format="color" />
<attr name="current_day_text_color" format="color" />
<attr name="current_day_lunar_text_color" format="color" />
<attr name="current_month_text_color" format="color" />
<attr name="other_month_text_color" format="color" />
<attr name="current_month_lunar_text_color" format="color" />
<attr name="other_month_lunar_text_color" format="color" />
<!-- 年视图相关 -->
<attr name="year_view_month_text_size" format="dimension" />
<attr name="year_view_day_text_size" format="dimension" />
<attr name="year_view_month_text_color" format="color" />
<attr name="year_view_current_day_text_color" format="color" />
<attr name="year_view_day_text_color" format="color" />
<attr name="year_view_select_text_color" format="color" />
<attr name="year_view_scheme_color" format="color" />
<attr name="year_view_background" format="color" />
<attr name="year_view_month_height" format="dimension" />
<attr name="year_view_week_height" format="dimension" />
<attr name="year_view_week_text_size" format="dimension" />
<attr name="year_view_week_text_color" format="color" />
<attr name="year_view_padding" format="dimension" />
<attr name="year_view_padding_left" format="dimension" />
<attr name="year_view_padding_right" format="dimension" />
<attr name="year_view_month_padding_top" format="dimension" />
<attr name="year_view_month_padding_left" format="dimension" />
<attr name="year_view_month_padding_right" format="dimension" />
<attr name="year_view_month_padding_bottom" format="dimension" />
<!--日期范围-->
<attr name="min_year" format="integer" />
<attr name="max_year" format="integer" />
<attr name="min_year_month" format="integer" />
<attr name="max_year_month" format="integer" />
<attr name="min_year_day" format="integer" />
<attr name="max_year_day" format="integer" />
<!--月视图是否可滚动-->
<attr name="month_view_scrollable" format="boolean" />
<!--周视图是否可滚动-->
<attr name="week_view_scrollable" format="boolean" />
<!--年视图是否可滚动-->
<attr name="year_view_scrollable" format="boolean" />
<!-- 月份显示模式 -->
<attr name="month_view_show_mode">
<enum name="mode_all" value="0" />
<enum name="mode_only_current" value="1" />
<enum name="mode_fix" value="2" />
</attr>
<!-- 自定义周起始 -->
<attr name="week_start_with">
<enum name="sun" value="1" />
<enum name="mon" value="2" />
<enum name="sat" value="7" />
</attr>
<!-- 自定义选择模式 -->
<attr name="select_mode">
<enum name="default_mode" value="0" />
<enum name="single_mode" value="1" />
<enum name="range_mode" value="2" />
<enum name="multi_mode" value="3" />
</attr>
<!-- when select_mode = multi_mode -->
<attr name="max_multi_select_size" format="integer" />
<!-- when select_mode = range_mode -->
<attr name="min_select_range" format="integer" />
<attr name="max_select_range" format="integer" />
<!-- auto select day -->
<attr name="month_view_auto_select_day">
<enum name="first_day_of_month" value="0" />
<enum name="last_select_day" value="1" />
<enum name="last_select_day_ignore_current" value="2" />
</attr>
</declare-styleable>
<declare-styleable name="CalendarLayout">
<attr name="default_status">
<enum name="expand" value="0" />
<enum name="shrink" value="1" />
</attr>
<!-- 手势模式 -->
<attr name="gesture_mode">
<enum name="default_mode" value="0" />
<!--<enum name="only_calendar" value="1" />-->
<enum name="disabled" value="2" />
</attr>
<attr name="calendar_show_mode">
<enum name="both_month_week_view" value="0" />
<enum name="only_week_view" value="1" />
<enum name="only_month_view" value="2" />
</attr>
<attr name="calendar_content_view_id" format="integer" />
</declare-styleable>
</resources>
其中下面两个时我们自定义的
app:month_view=“com.netease.calendar.CustomMonthView”
app:week_view=“com.netease.calendar.CustomWeekView”
<com.haibin.calendarview.CalendarView
app:month_view="com.netease.calendar.CustomMonthView"
app:week_view="com.netease.calendar.CustomWeekView"
android:id="@+id/calendarView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fff"
app:calendar_padding_left="22dp"
app:calendar_padding_right="10dp"
app:current_day_lunar_text_color="#ff0000"
app:current_day_text_color="#ff0000"
app:current_month_lunar_text_color="#CFCFCF"
app:current_month_text_color="#333333"
app:lunar_text_size="10sp"
app:max_year="2050"
app:max_year_day="31"
app:max_year_month="12"
app:min_year="2008"
app:min_year_day="1"
app:min_year_month="1"
app:month_view_show_mode="mode_only_current"
app:other_month_lunar_text_color="#e1e1e1"
app:other_month_text_color="#e1e1e1"
app:scheme_lunar_text_color="#CFCFCF"
app:scheme_text="假"
app:scheme_text_color="#333"
app:scheme_theme_color="#128c4b"
app:selected_lunar_text_color="#128c4b"
app:selected_text_color="#128c4b"
app:selected_theme_color="#B42B34"
app:week_background="#fff"
app:week_bar_height="46dp"
app:week_line_background="#00000000"
app:week_line_margin="16dp"
app:week_start_with="sun"
app:week_text_size="10sp"
app:year_view_background="#f6f6f6"
app:year_view_day_text_color="#333333"
app:year_view_day_text_size="8sp"
app:year_view_month_text_color="#ff0000"
app:year_view_month_text_size="20sp"
app:year_view_scheme_color="#f17706"
app:year_view_week_height="0dp"
app:year_view_week_text_color="#666666"
app:month_view_auto_select_day="last_select_day_ignore_current"
app:year_view_week_text_size="7sp" />
//设置日的辨识变化(假期什么的)
Map<String, Calendar> map=new HashMap<>();
map.put(getSchemeCalendar(2021, 10, 22, 0xFF40db25, "").toString(),
getSchemeCalendar(2021,10, 22, 0xFF40db25, ""));
map.put(getSchemeCalendar(2021, 10, 21, 0xFF40db25, "").toString(),
getSchemeCalendar(2021,10, 21, 0xFF40db25, ""));
map.put(getSchemeCalendar(2021, 10, 20, 0xFF40db25, "").toString(),
getSchemeCalendar(2021,10, 20, 0xFF40db25, ""));
mCalendarView.setSchemeDate(map);
getSchemeCalendar()方法
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;
}
监听时间:
mCalendarView.setOnCalendarSelectListener(new CalendarView.OnCalendarSelectListener() {
@Override
public void onCalendarOutOfRange(Calendar calendar) {
}
@Override
public void onCalendarSelect(Calendar calendar, boolean isClick) {
//日历选择监听,默认会执行一次
Log.d(TAG, "onCalendarSelect: "+calendar.getYear()+calendar.getMonth()+calendar.getDay());
}
});
其他重要方法:上下个月
mCalendarView.scrollToNext(false);//下个月
mCalendarView.scrollToPre(false);//上个月