最近公司又要求做一個簽到日歷效果,我為啥加個又是之前我實現了一個日歷簽到效果,而這次我使用的則是RecycleView去實現。
先上效果圖
實現思路
初始化日歷數據,把數據傳入到適配器中并顯示。
至于左右滑動頁面刷新,重寫RecyclerView的onTouchEvent方法,監聽手勢的改變,然后更改list數據,重新顯示UI。
在這里借鑒了一下 ToMyBestLove 所寫的博客,并完善了一下方法,方便定制化處理。
核心代碼
CalendarTool 這個工具類確實不錯,可以獲取正確的日期,很棒的算法可以減少大家不必要的時間。
public class CalendarTool<T extends BaseDateEntity> {private final String TAG = CalendarTool.class.getSimpleName();public static int FLING_MIN_DISTANCE = 100;private final int[] weekDayRow = {0, 1, 2, 3, 4, 5, 6};private ArrayList<DateEntity> mDataList = new ArrayList<>();//日期數組private ArrayList<T> mRecordList;//事件記錄數組private DateEntity mDateEntity;private int mYear;private int mMonth;private boolean mEndBelong;private boolean mStartBelong;private int mStartDay;private int mEndDay;/*** 當前年月日*/private int mCurrenYear;private int mCurrenMonth;private int mCurrenDay;/*** 平年月天數數組*/int commonYearMonthDay[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};/*** 閏年月天數數組*/int leapYearMonthDay[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};public CalendarTool() {/** 初始化當前系統的日期 */Calendar calendar = Calendar.getInstance();mCurrenYear = calendar.get(Calendar.YEAR);mCurrenMonth = calendar.get(Calendar.MONTH) + 1;mCurrenDay = calendar.get(Calendar.DAY_OF_MONTH);this.mYear = mCurrenYear;this.mMonth = mCurrenMonth;}/*** 獲取當前日歷的年月 x為年,y為月*/public Point getNowCalendar() {Point p = new Point(mYear, mMonth);return p;}/*** 判斷第一天屬不屬于本月*/public boolean isStartBelong() {return mStartBelong;}/*** 判斷最后一天屬不屬于本月*/public boolean isEndBelong() {return mEndBelong;}/*** 獲取日歷第一天的日期*/public int getStartDay() {return mStartDay;}/*** 獲取日歷最后一天的日期*/public int getEndDay() {return mEndDay;}public ArrayList<DateEntity> initDateList() {return initDateList(mYear, mMonth);}public void initRecordList(ArrayList<T> recordList) {mRecordList = recordList;}/*** 通過年月獲取當前頁面的日期集合*/private ArrayList<DateEntity> initDateList(int year, int month) {Log.i(TAG, "initDateList: year = " + year + " month = " + month);mDataList.clear();/** 修改部分 */int endDate = 0;// 得到上一個月的天數,作為上一個月在本日歷的結束日期if ((year - 1) == this.mYear || month == 1) {// 說明向前翻了一年,那么上個月的天數就應該是上一年的12月的天數,或者到翻到一月份的時候,那么上一個月的天數也是上一年的12月份的天數endDate = this.getDays(year - 1, 12);} else {// 得到上一個月的天數,作為上一個月在本日歷的結束日期endDate = this.getDays(year, month - 1);}/** 修改部分結束 */this.mYear = year;// 當前日歷上顯示的年this.mMonth = month;// 當前日歷上顯示的月int days = this.getDays(year, month);// 得到本月的總共天數int dayOfWeek = this.getWeekDay(year, month);//得到當前年月的第一天為星期幾int selfDaysEndWeek = 0;// 本月的最后一天是星期幾mStartBelong = true;/** 先添加前面不屬于本月的 */if (dayOfWeek != 0) {int startDate = endDate - dayOfWeek + 1;// 當前月的上一個月在本日歷的開始日期for (int i = startDate, j = 0; i <= endDate; i++, j++) {mDateEntity = new DateEntity(year, month - 1, i);mDateEntity.date = mDateEntity.year * 10000 + mDateEntity.month * 100 + i;if (startDate == i) {mStartBelong = false;mStartDay = mDateEntity.date;}mDateEntity.isSelfMonthDate = false;mDateEntity.weekDay = weekDayRow[j];mDateEntity.hasRecord = hasRecord(mDateEntity.date);mDataList.add(mDateEntity);}}/** 添加本月的 */for (int i = 1, j = dayOfWeek; i <= days; i++, j++) {mDateEntity = new DateEntity(year, month, i);mDateEntity.date = mDateEntity.year * 10000 + mDateEntity.month * 100 + i;if (mStartBelong && i == 1) {mStartDay = mDateEntity.date;}if (i == days) {mEndDay = mDateEntity.date;}mDateEntity.isSelfMonthDate = true;if (j >= 7) {j = 0;}selfDaysEndWeek = j;mDateEntity.weekDay = weekDayRow[j];if (year == mCurrenYear && month == mCurrenMonth && i == mCurrenDay) {mDateEntity.isNowDate = true;}mDateEntity.hasRecord = hasRecord(mDateEntity.date);mDataList.add(mDateEntity);}mEndBelong = true;/*** 添加后面下一個月的 */for (int i = 1, j = selfDaysEndWeek + 1; i < 7; i++, j++) {if (j >= 7) {break;}mEndBelong = false;mDateEntity = new DateEntity(year, month + 1, i);if (mDateEntity.month > 12) {mDateEntity.year = year + 1;mDateEntity.month = 1;}mDateEntity.date = mDateEntity.year * 10000 + mDateEntity.month * 100 + i;mDateEntity.isSelfMonthDate = false;mDateEntity.weekDay = weekDayRow[j];mDateEntity.hasRecord = hasRecord(mDateEntity.date);mDataList.add(mDateEntity);mEndDay = mDateEntity.year * 10000 + mDateEntity.month * 100 + i;}return mDataList;}/*** 通過年月,獲取這個月一共有多少天*/private int getDays(int year, int month) {int days = 0;if ((year % 4 == 0 && (year % 100 != 0)) || (year % 400 == 0)) {if (month > 0 && month <= 12) {days = leapYearMonthDay[month - 1];}} else {if (month > 0 && month <= 12) {days = commonYearMonthDay[month - 1];}}return days;}private boolean hasRecord(int date) {if (mRecordList != null) {for (T baseDateEntity : mRecordList) {if (baseDateEntity.year * 10000 + baseDateEntity.month * 100 + baseDateEntity.day == date) {return true;}}}return false;}/*** 通過年,月獲取當前月的第一天為星期幾 ,返回0是星期天,1是星期一,依次類推*/private int getWeekDay(int year, int month) {int dayOfWeek;int goneYearDays = 0;int thisYearDays = 0;boolean isLeapYear = false;//閏年int commonYearMonthDay[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};int leapYearMonthDay[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};for (int i = 1900; i < year; i++) {// 從1900年開始算起,1900年1月1日為星期一if ((i % 4 == 0 && (i % 100 != 0)) || (i % 400 == 0)) {goneYearDays = goneYearDays + 366;} else {goneYearDays = goneYearDays + 365;}}if ((year % 4 == 0 && (year % 100 != 0)) || (year % 400 == 0)) {isLeapYear = true;for (int i = 0; i < month - 1; i++) {thisYearDays = thisYearDays + leapYearMonthDay[i];}} else {isLeapYear = false;for (int i = 0; i < month - 1; i++) {thisYearDays = thisYearDays + commonYearMonthDay[i];}}dayOfWeek = (goneYearDays + thisYearDays + 1) % 7;Log.d(this.getClass().getName(), "從1990到現在有" + (goneYearDays + thisYearDays + 1) + "天");Log.d(this.getClass().getName(), year + "年" + month + "月" + 1 + "日是星期" + dayOfWeek);return dayOfWeek;}public void flushDate(float distance_x) {if (distance_x < 0) {// Fling rightif (mMonth + 1 > 12) {mDataList = initDateList(mYear + 1, 1);} else {mDataList = initDateList(mYear, mMonth + 1);}} else {// Fling leftif (mMonth - 1 <= 0) {mDataList = initDateList(mYear - 1, 12);} else {mDataList = initDateList(mYear, mMonth - 1);}}}
}
initDateList方法,會根據當前傳入的年月數據來計算當前日歷該顯示的數據。
因為我的需求是點擊按鈕完成簽到即可,不用點擊日歷中的日期(item),只需要把當前的日期傳入即可
Calendar calendar = Calendar.getInstance();list.add(new BaseDateEntity(calendar.get(Calendar.YEAR), (calendar.get(Calendar.MONTH) + 1),calendar.get(Calendar.DAY_OF_MONTH)));rcDate.initRecordList(list);
initRecordList 已經封裝adapter刷新,不用擔心傳值后沒有刷新。
這個Demo即使是新手直接可以使用,省去了大家閱讀的時間,畢竟大家的時間寶貴,干就完了
GitHub源碼地址
如果您覺得功能對您有所幫助,麻煩給我一顆小星星。 謝謝大家
總結
以上是生活随笔為你收集整理的▲ Android 使用RecycleView自定义日历签到效果的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。