自定义日历

    xiaoxiao2026-03-19  9

    自定义日历

    日期的绘制日期点击事件日期的事件提醒日期的颜色设置

    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); //这地方+1是由于系统默认的月份是0-11月 和传统的1-12月有误差 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; } // if(widthMode == MeasureSpec.AT_MOST){ // widthSize = mDisplayMetrics.densityDpi * 300; // } 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); // 这个地方可以对背景色进行设置,形状和颜色可以按照自己定义的来 // if(dayString.equals(mSelDay+"")){ // //绘制背景色矩形 // int startRecX = mColumnSize * column; // int startRecY = mRowSize * row; // int endRecX = startRecX + mColumnSize; // int endRecY = startRecY + mRowSize; // mPaint.setColor(mSelectBGColor); // canvas.drawRect(startRecX, startRecY, endRecX, endRecY, mPaint); // //记录第几行,即第几周 // weekRow = row + 1; // } //绘制事务圆形标志 我这边是由于公司要点击背景色发生变化,所以设置为背 //景色为空,通过事务来描绘背景的黄色圆圈 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)) { //设置事务标志颜色 mPaint.setColor(Color.parseColor("#ffffff")); 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(); //执行activity发送过来的点击处理事件 if (dateClick != null) { dateClick.onClickOnDate(); } } /** * 左点击,日历向后翻页 */ public void onLeftClick() { int year = mSelYear; int month = mSelMonth; int day = mSelDay; if (month == 1) {//若果是1月份,则变成12月份 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) {//若果是12月份,则变成1月份 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; } // if(widthMode == MeasureSpec.AT_MOST){ // widthSize = mDisplayMetrics.densityDpi * 300; // } 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; // 闰年2月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(); } }); } }

    需要标注的地方都写有注释,有不明白的地方留言问我 刚开始写,技术不太好,多多指教。


    转载请注明原文地址: https://ju.6miu.com/read-1308126.html
    最新回复(0)