18 |

19 |
20 |
21 | * 看到本篇文章的同学估计也是实验课或者项目需求中需要一个日历表,当我接到这个需求的时候,当时脑子压根连想都没想,这么通用的控件,GitHub上一搜一大堆不是嘛。可是等到真正做起来的时候,扎心了老铁,GitHub上的大神居然异常的不给力,都是实现了基本功能,能够滑动切换月份,找实现了周月切换功能的开源库很难。终于我费尽千辛万苦找到一个能够完美切换的项目时,你周月切换之后的数据乱的一塌糊涂啊!!!
22 | * 算了,自己撸一个!!!
23 |
24 | ## 项目链接 [SuperCalendar][Tags]
25 |
26 | [Tags]: https://github.com/MagicMashRoom/SuperCalendar
27 | * 如果你感觉到对你有帮助,欢迎star
28 | * 如果你感觉对代码有疑惑,或者需要修改的地方,欢迎issue
29 |
30 | ## 主要特性
31 | * 日历样式完全自定义,拓展性强
32 | * 左右滑动切换上下周月,上下滑动切换周月模式
33 | * 抽屉式周月切换效果
34 | * 标记指定日期(marker)
35 | * 跳转到指定日期
36 |
37 | ## 思路
38 |
39 | ## 使用方法
40 |
41 | #### XML布局
42 | * 新建XML布局
43 |
44 | RecyclerView的layout_behavior为com.ldf.calendar.behavior.RecyclerViewBehavior
45 |
46 | ```xml
47 |
52 |
53 |
58 |
59 |
60 |
67 |
68 |
69 |
70 | ```
71 | #### 自定义日历样式
72 | * 新建CustomDayView继承自DayView并重写refreshContent 和 copy 两个方法
73 |
74 | ```java
75 | @Override
76 | public void refreshContent() {
77 | //你的代码 你可以在这里定义你的显示规则
78 | super.refreshContent();
79 | }
80 |
81 | @Override
82 | public IDayRenderer copy() {
83 | return new CustomDayView(context , layoutResource);
84 | }
85 | ```
86 |
87 | * 新建CustomDayView实例,并作为参数构建CalendarViewAdapter
88 |
89 |
90 | ```java
91 | CustomDayView customDayView = new CustomDayView(context, R.layout.custom_day);
92 | calendarAdapter = new CalendarViewAdapter(
93 | context,
94 | onSelectDateListener,
95 | CalendarAttr.CalendarType.MONTH,
96 | CalendarAttr.WeekArrayType.Monday,
97 | customDayView);
98 | ```
99 | #### 初始化View
100 |
101 | * 目前来看 相比于Dialog选择日历 我的控件更适合于Activity/Fragment在Activity的`onCreate` 或者Fragment的`onCreateView` 你需要实现这两个方法来启动日历并装填进数据
102 |
103 | ```java
104 | @Override
105 | protected void onCreate(@Nullable Bundle savedInstanceState) {
106 | super.onCreate(savedInstanceState);
107 | setContentView(R.layout.activity_syllabus);
108 | initCalendarView();
109 | }
110 |
111 | private void initCalendarView() {
112 | initListener();
113 | CustomDayView customDayView = new CustomDayView(context, R.layout.custom_day);
114 | calendarAdapter = new CalendarViewAdapter(
115 | context,
116 | onSelectDateListener,
117 | CalendarAttr.CalendarType.MONTH,
118 | CalendarAttr.WeekArrayType.Monday,
119 | customDayView);
120 | initMarkData();
121 | initMonthPager();
122 | }
123 | ```
124 |
125 | 使用此方法回调日历点击事件
126 | ```java
127 | private void initListener() {
128 | onSelectDateListener = new OnSelectDateListener() {
129 | @Override
130 | public void onSelectDate(CalendarDate date) {
131 | //your code
132 | }
133 |
134 | @Override
135 | public void onSelectOtherMonth(int offset) {
136 | //偏移量 -1表示上一个月 , 1表示下一个月
137 | monthPager.selectOtherMonth(offset);
138 | }
139 | };
140 | }
141 | ```
142 |
143 | 使用此方法初始化日历标记数据
144 | ```java
145 | private void initMarkData() {
146 | HashMap markData = new HashMap<>();
147 | //1表示红点,0表示灰点
148 | markData.put("2017-8-9" , "1");
149 | markData.put("2017-7-9" , "0");
150 | markData.put("2017-6-9" , "1");
151 | markData.put("2017-6-10" , "0");
152 | calendarAdapter.setMarkData(markData);
153 | }
154 | ```
155 | 使用此方法给MonthPager添加上相关监听
156 | ```java
157 | monthPager.addOnPageChangeListener(new MonthPager.OnPageChangeListener() {
158 | @Override
159 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
160 | }
161 |
162 | @Override
163 | public void onPageSelected(int position) {
164 | mCurrentPage = position;
165 | currentCalendars = calendarAdapter.getAllItems();
166 | if(currentCalendars.get(position % currentCalendars.size()) instanceof Calendar){
167 | //you code
168 | }
169 | }
170 |
171 | @Override
172 | public void onPageScrollStateChanged(int state) {
173 | }
174 | });
175 | ```
176 |
177 | 重写onWindowFocusChanged方法,使用此方法得知calendar和day的尺寸
178 |
179 | ```java
180 | @Override
181 | public void onWindowFocusChanged(boolean hasFocus) {
182 | super.onWindowFocusChanged(hasFocus);
183 | if(hasFocus && !initiated) {
184 | CalendarDate today = new CalendarDate();
185 | calendarAdapter.notifyDataChanged(today);
186 | initiated = true;
187 | }
188 | }
189 | ```
190 |
191 | * 大功告成,如果还不清晰,请下载DEMO
192 |
193 | ## Download
194 | --------
195 | Gradle:
196 | Step 1. Add it in your root build.gradle at the end of repositories:
197 | ```groovy
198 | allprojects {
199 | repositories {
200 | ...
201 | maven { url 'https://www.jitpack.io' }
202 | }
203 | }
204 | ```
205 | Step 2. Add the dependency
206 |
207 | ```groovy
208 | dependencies {
209 | compile 'com.github.MagicMashRoom:SuperCalendar:1.6'
210 | }
211 |
212 | ```
213 | [](https://www.jitpack.io/#MagicMashRoom/SuperCalendar)
214 |
215 | ## Licence
216 |
217 | Copyright 2017 MagicMashRoom, Inc.
218 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | google()
7 | }
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.0.1'
10 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | jcenter()
19 | maven { url "https://jitpack.io" }
20 | google()
21 | }
22 | }
23 |
24 | task clean(type: Delete) {
25 | delete rootProject.buildDir
26 | }
27 |
--------------------------------------------------------------------------------
/calendar/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### OSX template
3 | *.DS_Store
4 | .AppleDouble
5 | .LSOverride
6 |
7 | # Icon must end with two \r
8 | Icon
9 |
10 | # Thumbnails
11 | ._*
12 |
13 | # Files that might appear in the root of a volume
14 | .DocumentRevisions-V100
15 | .fseventsd
16 | .Spotlight-V100
17 | .TemporaryItems
18 | .Trashes
19 | .VolumeIcon.icns
20 | .com.apple.timemachine.donotpresent
21 |
22 | # Directories potentially created on remote AFP share
23 | .AppleDB
24 | .AppleDesktop
25 | Network Trash Folder
26 | Temporary Items
27 | .apdisk
28 | ### Android template
29 | # Built application files
30 | *.apk
31 | *.ap_
32 |
33 | # Files for the ART/Dalvik VM
34 | *.dex
35 |
36 | # Java class files
37 | *.class
38 |
39 | # Generated files
40 | bin/
41 | gen/
42 | out/
43 |
44 | # Gradle files
45 | .gradle/
46 | build/
47 |
48 | # Local configuration file (sdk path, etc)
49 | local.properties
50 |
51 | # Proguard folder generated by Eclipse
52 | proguard/
53 |
54 | # Log Files
55 | *.log
56 |
57 | # Android Studio Navigation editor temp files
58 | .navigation/
59 |
60 | # Android Studio captures folder
61 | captures/
62 |
63 | # Intellij
64 | *.iml
65 | .idea/workspace.xml
66 |
67 | # Keystore files
68 | *.jks
69 |
70 |
--------------------------------------------------------------------------------
/calendar/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin:'com.github.dcendents.android-maven'
3 |
4 | group='com.github.MagicMashRoom'
5 |
6 | android {
7 | compileSdkVersion 26
8 | buildToolsVersion '26.0.2'
9 |
10 | defaultConfig {
11 | minSdkVersion 16
12 | targetSdkVersion 26
13 | versionCode 1
14 | versionName "1.0"
15 | }
16 |
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 |
24 | lintOptions {
25 | abortOnError false
26 | }
27 | }
28 |
29 | dependencies {
30 | compile fileTree(dir: 'libs', include: ['*.jar'])
31 | testCompile 'junit:junit:4.12'
32 | compile 'com.android.support:appcompat-v7:26.1.0'
33 | compile 'com.android.support:design:26.1.0'
34 | }
35 |
--------------------------------------------------------------------------------
/calendar/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\Tools\Android\studio_sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/calendar/src/androidTest/java/com/ldf/mi/calendar/micalendar/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.ldf.mi.calendar.micalendar;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | *
Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase
{
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/calendar/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/calendar/src/main/java/com/ldf/calendar/Const.java:
--------------------------------------------------------------------------------
1 | package com.ldf.calendar;
2 |
3 | /**
4 | * Created by ldf on 17/6/27.
5 | */
6 |
7 | public class Const {
8 | public final static int TOTAL_COL = 7;
9 | public final static int TOTAL_ROW = 6;
10 | public final static int CURRENT_PAGER_INDEX = 1000;
11 | }
12 |
--------------------------------------------------------------------------------
/calendar/src/main/java/com/ldf/calendar/Utils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016.
3 | * wb-lijinwei.a@alibaba-inc.com
4 | */
5 |
6 | package com.ldf.calendar;
7 |
8 | import android.annotation.SuppressLint;
9 | import android.content.Context;
10 | import android.support.design.widget.CoordinatorLayout;
11 | import android.support.v4.view.ViewCompat;
12 | import android.support.v7.widget.RecyclerView;
13 | import android.view.View;
14 | import android.view.ViewConfiguration;
15 | import android.widget.Scroller;
16 |
17 | import com.ldf.calendar.component.CalendarAttr;
18 | import com.ldf.calendar.model.CalendarDate;
19 |
20 | import java.text.ParseException;
21 | import java.text.SimpleDateFormat;
22 | import java.util.Calendar;
23 | import java.util.Date;
24 | import java.util.HashMap;
25 |
26 | public final class Utils {
27 |
28 | private static HashMap markData = new HashMap<>();
29 |
30 | private Utils() {
31 |
32 | }
33 |
34 | /**
35 | * 得到某一个月的具体天数
36 | *
37 | * @param year 参数月所在年
38 | * @param month 参数月
39 | * @return int 参数月所包含的天数
40 | */
41 | public static int getMonthDays(int year, int month) {
42 | if (month > 12) {
43 | month = 1;
44 | year += 1;
45 | } else if (month < 1) {
46 | month = 12;
47 | year -= 1;
48 | }
49 | int[] monthDays = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
50 | int days = 0;
51 | // 闰年2月29天
52 | if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
53 | monthDays[1] = 29;
54 | }
55 | try {
56 | days = monthDays[month - 1];
57 | } catch (Exception e) {
58 | e.getStackTrace();
59 | }
60 | return days;
61 | }
62 |
63 | public static int getYear() {
64 | return Calendar.getInstance().get(Calendar.YEAR);
65 | }
66 |
67 | public static int getMonth() {
68 | return Calendar.getInstance().get(Calendar.MONTH) + 1;
69 | }
70 |
71 | public static int getDay() {
72 | return Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
73 | }
74 |
75 | /**
76 | * 得到当前月第一天在其周的位置
77 | *
78 | * @param year 当前年
79 | * @param month 当前月
80 | * @param type 周排列方式 0代表周一作为本周的第一天, 2代表周日作为本周的第一天
81 | * @return int 本月第一天在其周的位置
82 | */
83 | public static int getFirstDayWeekPosition(int year, int month, CalendarAttr.WeekArrayType type) {
84 | Calendar cal = Calendar.getInstance();
85 | cal.setTime(getDateFromString(year, month));
86 | int week_index = cal.get(Calendar.DAY_OF_WEEK) - 1;
87 | if (type == CalendarAttr.WeekArrayType.Sunday) {
88 | return week_index;
89 | } else {
90 | week_index = cal.get(Calendar.DAY_OF_WEEK) + 5;
91 | if (week_index >= 7) {
92 | week_index -= 7;
93 | }
94 | }
95 | return week_index;
96 | }
97 |
98 | /**
99 | * 将yyyy-MM-dd类型的字符串转化为对应的Date对象
100 | *
101 | * @param year 当前年
102 | * @param month 当前月
103 | * @return Date 对应的Date对象
104 | */
105 | @SuppressLint("SimpleDateFormat")
106 | public static Date getDateFromString(int year, int month) {
107 | String dateString = year + "-" + (month > 9 ? month : ("0" + month)) + "-01";
108 | Date date = new Date();
109 | try {
110 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
111 | date = sdf.parse(dateString);
112 | } catch (ParseException e) {
113 | System.out.println(e.getMessage());
114 | }
115 | return date;
116 | }
117 |
118 | /**
119 | * 计算参数日期月与当前月相差的月份数
120 | *
121 | * @param year 参数日期所在年
122 | * @param month 参数日期所在月
123 | * @param currentDate 当前月
124 | * @return int offset 相差月份数
125 | */
126 | public static int calculateMonthOffset(int year, int month, CalendarDate currentDate) {
127 | int currentYear = currentDate.getYear();
128 | int currentMonth = currentDate.getMonth();
129 | int offset = (year - currentYear) * 12 + (month - currentMonth);
130 | return offset;
131 | }
132 |
133 | /**
134 | * 删除方法, 这里只会删除某个文件夹下的文件,如果传入的directory是个文件,将不做处理
135 | *
136 | * @param context 上下文
137 | * @param dpi dp为单位的尺寸
138 | * @return int 转化而来的对应像素
139 | */
140 | public static int dpi2px(Context context, float dpi) {
141 | return (int) (context.getResources().getDisplayMetrics().density * dpi + 0.5f);
142 | }
143 |
144 | /**
145 | * 得到标记日期数据,可以通过该数据得到标记日期的信息,开发者可自定义格式
146 | * 目前HashMap的组成仅仅是为了DEMO效果
147 | *
148 | * @return HashMap 标记日期数据
149 | */
150 | public static HashMap loadMarkData() {
151 | return markData;
152 | }
153 |
154 | /**
155 | * 设置标记日期数据
156 | *
157 | * @param data 标记日期数据
158 | * @return void
159 | */
160 | public static void setMarkData(HashMap data) {
161 | markData = data;
162 | }
163 |
164 | public static void cleanMarkData(){
165 | markData.clear();
166 | }
167 |
168 | /**
169 | * 计算偏移距离
170 | *
171 | * @param offset 偏移值
172 | * @param min 最小偏移值
173 | * @param max 最大偏移值
174 | * @return int offset
175 | */
176 | private static int calcOffset(int offset, int min, int max) {
177 | if (offset > max) {
178 | return max;
179 | } else if (offset < min) {
180 | return min;
181 | } else {
182 | return offset;
183 | }
184 | }
185 |
186 | /**
187 | * 删除方法, 这里只会删除某个文件夹下的文件,如果传入的directory是个文件,将不做处理
188 | *
189 | * @param child 需要移动的View
190 | * @param dy 实际偏移量
191 | * @param minOffset 最小偏移量
192 | * @param maxOffset 最大偏移量
193 | * @return void
194 | */
195 | public static int scroll(View child, int dy, int minOffset, int maxOffset) {
196 | final int initOffset = child.getTop();
197 | int offset = calcOffset(initOffset - dy, minOffset, maxOffset) - initOffset;
198 | child.offsetTopAndBottom(offset);
199 | return -offset;
200 | }
201 |
202 | /**
203 | * 得到TouchSlop
204 | *
205 | * @param context 上下文
206 | * @return int touchSlop的具体值
207 | */
208 | public static int getTouchSlop(Context context) {
209 | return ViewConfiguration.get(context).getScaledTouchSlop();
210 | }
211 |
212 | /**
213 | * 得到种子日期所在周的周日
214 | *
215 | * @param seedDate 种子日期
216 | * @return CalendarDate 所在周周日
217 | */
218 | public static CalendarDate getSunday(CalendarDate seedDate) {// TODO: 16/12/12 得到一个CustomDate对象
219 | Calendar c = Calendar.getInstance();
220 | String dateString = seedDate.toString();
221 | Date date = new Date();
222 | try {
223 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-M-d");
224 | date = sdf.parse(dateString);
225 | } catch (ParseException e) {
226 | System.out.println(e.getMessage());
227 | }
228 | c.setTime(date);
229 | if (c.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
230 | c.add(Calendar.DAY_OF_MONTH, 7 - c.get(Calendar.DAY_OF_WEEK) + 1);
231 | }
232 | return new CalendarDate(c.get(Calendar.YEAR),
233 | c.get(Calendar.MONTH) + 1,
234 | c.get(Calendar.DAY_OF_MONTH));
235 | }
236 |
237 | /**
238 | * 得到种子日期所在周的周六
239 | *
240 | * @param seedDate 种子日期
241 | * @return CalendarDate 所在周周六
242 | */
243 | public static CalendarDate getSaturday(CalendarDate seedDate) {// TODO: 16/12/12 得到一个CustomDate对象
244 | Calendar c = Calendar.getInstance();
245 | String dateString = seedDate.toString();
246 | Date date = null;
247 | try {
248 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-M-d");
249 | date = sdf.parse(dateString);
250 | } catch (ParseException e) {
251 | System.out.println(e.getMessage());
252 | }
253 | c.setTime(date);
254 | c.add(Calendar.DAY_OF_MONTH, 7 - c.get(Calendar.DAY_OF_WEEK));
255 | return new CalendarDate(c.get(Calendar.YEAR),
256 | c.get(Calendar.MONTH) + 1,
257 | c.get(Calendar.DAY_OF_MONTH));
258 | }
259 |
260 | private static int top;
261 | private static boolean customScrollToBottom = false;
262 |
263 | /**
264 | * 判断上一次滑动改变周月日历是向下滑还是向上滑 向下滑表示切换为月日历模式 向上滑表示切换为周日历模式
265 | *
266 | * @return boolean 是否是在向下滑动。(true: 已经收缩; false: 已经打开)
267 | */
268 | public static boolean isScrollToBottom() {
269 | return customScrollToBottom;
270 | }
271 |
272 | /**
273 | * 设置上一次滑动改变周月日历是向下滑还是向上滑 向下滑表示切换为月日历模式 向上滑表示切换为周日历模式
274 | *
275 | * @return void
276 | */
277 | public static void setScrollToBottom(boolean customScrollToBottom) {
278 | Utils.customScrollToBottom = customScrollToBottom;
279 | }
280 |
281 | /**
282 | * 通过scrollTo方法完成协调布局的滑动,其中主要使用了ViewCompat.postOnAnimation
283 | *
284 | * @param parent 协调布局parent
285 | * @param child 协调布局协调滑动的child
286 | * @param y 滑动目标位置y轴数值
287 | * @param duration 滑动执行时间
288 | * @return void
289 | */
290 | public static void scrollTo(final CoordinatorLayout parent, final RecyclerView child, final int y, int duration) {
291 | final Scroller scroller = new Scroller(parent.getContext());
292 | scroller.startScroll(0, top, 0, y - top, duration); //设置scroller的滚动偏移量
293 | ViewCompat.postOnAnimation(child, new Runnable() {
294 | @Override
295 | public void run() {
296 | //返回值为boolean,true说明滚动尚未完成,false说明滚动已经完成。
297 | // 这是一个很重要的方法,通常放在View.computeScroll()中,用来判断是否滚动是否结束。
298 | if (scroller.computeScrollOffset()) {
299 | int delta = scroller.getCurrY() - child.getTop();
300 | child.offsetTopAndBottom(delta);
301 | saveTop(child.getTop());
302 | parent.dispatchDependentViewsChanged(child);
303 | ViewCompat.postOnAnimation(child, this);
304 | }
305 | }
306 | });
307 | }
308 |
309 | public static void saveTop(int y) {
310 | top = y;
311 | }
312 |
313 | public static int loadTop() {
314 | return top;
315 | }
316 | }
317 |
--------------------------------------------------------------------------------
/calendar/src/main/java/com/ldf/calendar/behavior/MonthPagerBehavior.java:
--------------------------------------------------------------------------------
1 | package com.ldf.calendar.behavior;
2 |
3 | import android.support.design.widget.CoordinatorLayout;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.util.Log;
6 | import android.view.MotionEvent;
7 | import android.view.View;
8 |
9 | import com.ldf.calendar.Utils;
10 | import com.ldf.calendar.component.CalendarViewAdapter;
11 | import com.ldf.calendar.view.MonthPager;
12 |
13 | /**
14 | * Created by ldf on 17/6/15.
15 | */
16 |
17 | public class MonthPagerBehavior extends CoordinatorLayout.Behavior {
18 | private int top = 0;
19 | private int touchSlop = 1;
20 | private int offsetY = 0;
21 |
22 | @Override
23 | public boolean layoutDependsOn(CoordinatorLayout parent, MonthPager child, View dependency) {
24 | return dependency instanceof RecyclerView;
25 | }
26 |
27 | @Override
28 | public boolean onLayoutChild(CoordinatorLayout parent, MonthPager child, int layoutDirection) {
29 | parent.onLayoutChild(child, layoutDirection);
30 | child.offsetTopAndBottom(top);
31 | return true;
32 | }
33 |
34 | private float downX, downY, lastY, lastTop;
35 | private boolean isVerticalScroll;
36 | private boolean directionUpa;
37 |
38 | @Override
39 | public boolean onTouchEvent(CoordinatorLayout parent, MonthPager child, MotionEvent ev) {
40 | if (downY > lastTop) {
41 | return false;
42 | }
43 | switch (ev.getAction()) {
44 | case MotionEvent.ACTION_DOWN:
45 | break;
46 | case MotionEvent.ACTION_MOVE:
47 | if (isVerticalScroll) {
48 | if (ev.getY() > lastY) {
49 | Utils.setScrollToBottom(true);
50 | directionUpa = false;
51 | } else {
52 | Utils.setScrollToBottom(false);
53 | directionUpa = true;
54 | }
55 |
56 | if (lastTop < child.getViewHeight() / 2 + child.getCellHeight() / 2) {
57 | //这里表示本来是收缩状态
58 | if (ev.getY() - downY <= 0 || Utils.loadTop() >= child.getViewHeight()) {
59 | //向上滑或者已展开了
60 | lastY = ev.getY();
61 | return true;
62 | }
63 | if (ev.getY() - downY + child.getCellHeight() >= child.getViewHeight()) {
64 | //将要滑过头了
65 | saveTop(child.getViewHeight());
66 | Utils.scrollTo(parent, (RecyclerView) parent.getChildAt(1), child.getViewHeight(), 10);
67 | isVerticalScroll = false;
68 | } else {
69 | //正常下滑
70 | saveTop((int) (child.getCellHeight() + ((ev.getY() - downY))));
71 | Utils.scroll(parent.getChildAt(1), (int) (lastY - ev.getY()),
72 | child.getCellHeight(), child.getViewHeight());
73 | }
74 | } else {
75 | if (ev.getY() - downY >= 0 || Utils.loadTop() <= child.getCellHeight()) {
76 | lastY = ev.getY();
77 | return true;
78 | }
79 |
80 | if (ev.getY() - downY + child.getViewHeight() <= child.getCellHeight()) {
81 | //将要滑过头了
82 | saveTop(child.getCellHeight());
83 | Utils.scrollTo(parent, (RecyclerView) parent.getChildAt(1), child.getCellHeight(), 10);
84 | isVerticalScroll = false;
85 | } else {
86 | //正常上滑
87 | saveTop((int) (child.getViewHeight() + ((ev.getY() - downY))));
88 | Utils.scroll(parent.getChildAt(1), (int) (lastY - ev.getY()),
89 | child.getCellHeight(), child.getViewHeight());
90 | }
91 | }
92 |
93 | lastY = ev.getY();
94 | return true;
95 | }
96 | break;
97 | case MotionEvent.ACTION_UP:
98 | if (isVerticalScroll) {
99 |
100 | child.setScrollable(true);
101 |
102 | CalendarViewAdapter calendarViewAdapter =
103 | (CalendarViewAdapter) child.getAdapter();
104 | if (calendarViewAdapter != null) {
105 | if (directionUpa) {
106 | Utils.setScrollToBottom(true);
107 | calendarViewAdapter.switchToWeek(child.getRowIndex());
108 | Utils.scrollTo(parent, (RecyclerView) parent.getChildAt(1), child.getCellHeight(), 300);
109 | } else {
110 | Utils.setScrollToBottom(false);
111 | calendarViewAdapter.switchToMonth();
112 | Utils.scrollTo(parent, (RecyclerView) parent.getChildAt(1), child.getViewHeight(), 300);
113 | }
114 | }
115 |
116 | isVerticalScroll = false;
117 | return true;
118 | }
119 | break;
120 | }
121 | return false;
122 | }
123 |
124 | private void saveTop(int top) {
125 | Utils.saveTop(top);
126 | }
127 |
128 | @Override
129 | public boolean onInterceptTouchEvent(CoordinatorLayout parent, MonthPager child, MotionEvent ev) {
130 | switch (ev.getAction()) {
131 | case MotionEvent.ACTION_DOWN:
132 | downX = ev.getX();
133 | downY = ev.getY();
134 | lastTop = Utils.loadTop();
135 | lastY = downY;
136 | break;
137 | case MotionEvent.ACTION_MOVE:
138 | if (downY > lastTop) {
139 | return false;
140 | }
141 | if (Math.abs(ev.getY() - downY) > 25 && Math.abs(ev.getX() - downX) <= 25
142 | && !isVerticalScroll) {
143 | isVerticalScroll = true;
144 | return true;
145 | }
146 | break;
147 | case MotionEvent.ACTION_UP:
148 | if (isVerticalScroll) {
149 | isVerticalScroll = false;
150 | return true;
151 | }
152 | break;
153 | }
154 | return isVerticalScroll;
155 | }
156 |
157 | private int dependentViewTop = -1;
158 |
159 | @Override
160 | public boolean onDependentViewChanged(CoordinatorLayout parent, MonthPager child, View dependency) {
161 | CalendarViewAdapter calendarViewAdapter = (CalendarViewAdapter) child.getAdapter();
162 | //dependency对其依赖的view(本例依赖的view是RecycleView)
163 | if (dependentViewTop != -1) {
164 | int dy = dependency.getTop() - dependentViewTop;
165 | int top = child.getTop();
166 | if (dy > touchSlop) {
167 | calendarViewAdapter.switchToMonth();
168 | } else if (dy < -touchSlop) {
169 | calendarViewAdapter.switchToWeek(child.getRowIndex());
170 | }
171 |
172 | if (dy > -top) {
173 | dy = -top;
174 | }
175 |
176 | if (dy < -top - child.getTopMovableDistance()) {
177 | dy = -top - child.getTopMovableDistance();
178 | }
179 |
180 | child.offsetTopAndBottom(dy);
181 | Log.e("ldf", "onDependentViewChanged = " + dy);
182 |
183 | }
184 |
185 | dependentViewTop = dependency.getTop();
186 | top = child.getTop();
187 |
188 | if (offsetY > child.getCellHeight()) {
189 | calendarViewAdapter.switchToMonth();
190 | }
191 | if (offsetY < -child.getCellHeight()) {
192 | calendarViewAdapter.switchToWeek(child.getRowIndex());
193 | }
194 |
195 | if (dependentViewTop > child.getCellHeight() - 24
196 | && dependentViewTop < child.getCellHeight() + 24
197 | && top > -touchSlop - child.getTopMovableDistance()
198 | && top < touchSlop - child.getTopMovableDistance()) {
199 | Utils.setScrollToBottom(true);
200 | calendarViewAdapter.switchToWeek(child.getRowIndex());
201 | offsetY = 0;
202 | }
203 | if (dependentViewTop > child.getViewHeight() - 24
204 | && dependentViewTop < child.getViewHeight() + 24
205 | && top < touchSlop
206 | && top > -touchSlop) {
207 | Utils.setScrollToBottom(false);
208 | calendarViewAdapter.switchToMonth();
209 | offsetY = 0;
210 | }
211 |
212 | return true;
213 | // TODO: 16/12/8 dy为负时表示向上滑动,dy为正时表示向下滑动,dy为零时表示滑动停止
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/calendar/src/main/java/com/ldf/calendar/behavior/RecyclerViewBehavior.java:
--------------------------------------------------------------------------------
1 | package com.ldf.calendar.behavior;
2 |
3 | import android.content.Context;
4 | import android.support.design.widget.CoordinatorLayout;
5 | import android.support.v4.view.ViewCompat;
6 | import android.support.v4.view.ViewPager;
7 | import android.support.v7.widget.RecyclerView;
8 | import android.util.AttributeSet;
9 | import android.util.Log;
10 | import android.view.View;
11 | import android.widget.Toast;
12 |
13 | import com.ldf.calendar.Utils;
14 | import com.ldf.calendar.view.MonthPager;
15 |
16 | public class RecyclerViewBehavior extends CoordinatorLayout.Behavior {
17 | private int initOffset = -1;
18 | private int minOffset = -1;
19 | private Context context;
20 | private boolean initiated = false;
21 | boolean hidingTop = false;
22 | boolean showingTop = false;
23 |
24 | public RecyclerViewBehavior(Context context, AttributeSet attrs) {
25 | super(context, attrs);
26 | this.context = context;
27 | }
28 |
29 | @Override
30 | public boolean onLayoutChild(CoordinatorLayout parent, RecyclerView child, int layoutDirection) {
31 | parent.onLayoutChild(child, layoutDirection);
32 | MonthPager monthPager = getMonthPager(parent);
33 | initMinOffsetAndInitOffset(parent, child, monthPager);
34 | return true;
35 | }
36 |
37 | private void initMinOffsetAndInitOffset(CoordinatorLayout parent,
38 | RecyclerView child,
39 | MonthPager monthPager) {
40 | if (monthPager.getBottom() > 0 && initOffset == -1) {
41 | initOffset = monthPager.getViewHeight();
42 | saveTop(initOffset);
43 | }
44 | if (!initiated) {
45 | initOffset = monthPager.getViewHeight();
46 | saveTop(initOffset);
47 | initiated = true;
48 | }
49 | child.offsetTopAndBottom(Utils.loadTop());
50 | minOffset = getMonthPager(parent).getCellHeight();
51 | }
52 |
53 | @Override
54 | public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, RecyclerView child,
55 | View directTargetChild, View target, int nestedScrollAxes) {
56 | Log.e("ldf", "onStartNestedScroll");
57 |
58 | MonthPager monthPager = (MonthPager) coordinatorLayout.getChildAt(0);
59 | monthPager.setScrollable(false);
60 | boolean isVertical = (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;
61 |
62 | return isVertical;
63 | }
64 |
65 | @Override
66 | public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, RecyclerView child,
67 | View target, int dx, int dy, int[] consumed) {
68 | Log.e("ldf", "onNestedPreScroll");
69 | super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
70 | child.setVerticalScrollBarEnabled(true);
71 |
72 | MonthPager monthPager = (MonthPager) coordinatorLayout.getChildAt(0);
73 | if (monthPager.getPageScrollState() != ViewPager.SCROLL_STATE_IDLE) {
74 | consumed[1] = dy;
75 | Log.w("ldf", "onNestedPreScroll: MonthPager dragging");
76 | Toast.makeText(context, "loading month data", Toast.LENGTH_SHORT).show();
77 | return;
78 | }
79 |
80 | // 上滑,正在隐藏顶部的日历
81 | hidingTop = dy > 0 && child.getTop() <= initOffset
82 | && child.getTop() > getMonthPager(coordinatorLayout).getCellHeight();
83 | // 下滑,正在展示顶部的日历
84 | showingTop = dy < 0 && !ViewCompat.canScrollVertically(target, -1);
85 |
86 | if (hidingTop || showingTop) {
87 | consumed[1] = Utils.scroll(child, dy,
88 | getMonthPager(coordinatorLayout).getCellHeight(),
89 | getMonthPager(coordinatorLayout).getViewHeight());
90 | saveTop(child.getTop());
91 | }
92 | }
93 |
94 | @Override
95 | public void onStopNestedScroll(final CoordinatorLayout parent, final RecyclerView child, View target) {
96 | Log.e("ldf", "onStopNestedScroll");
97 | super.onStopNestedScroll(parent, child, target);
98 | MonthPager monthPager = (MonthPager) parent.getChildAt(0);
99 | monthPager.setScrollable(true);
100 | if (!Utils.isScrollToBottom()) {
101 | if (initOffset - Utils.loadTop() > Utils.getTouchSlop(context) && hidingTop) {
102 | Utils.scrollTo(parent, child, getMonthPager(parent).getCellHeight(), 500);
103 | } else {
104 | Utils.scrollTo(parent, child, getMonthPager(parent).getViewHeight(), 150);
105 | }
106 | } else {
107 | if (Utils.loadTop() - minOffset > Utils.getTouchSlop(context) && showingTop) {
108 | Utils.scrollTo(parent, child, getMonthPager(parent).getViewHeight(), 500);
109 | } else {
110 | Utils.scrollTo(parent, child, getMonthPager(parent).getCellHeight(), 150);
111 | }
112 | }
113 | }
114 |
115 | @Override
116 | public boolean onNestedFling(CoordinatorLayout coordinatorLayout, RecyclerView child, View target, float velocityX, float velocityY, boolean consumed) {
117 | Log.d("ldf", "onNestedFling: velocityY: " + velocityY);
118 | return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
119 | }
120 |
121 | @Override
122 | public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, RecyclerView child, View target, float velocityX, float velocityY) {
123 | // 日历隐藏和展示过程,不允许RecyclerView进行fling
124 | if (hidingTop || showingTop) {
125 | return true;
126 | } else {
127 | return false;
128 | }
129 | }
130 |
131 | private MonthPager getMonthPager(CoordinatorLayout coordinatorLayout) {
132 | return (MonthPager) coordinatorLayout.getChildAt(0);
133 | }
134 |
135 | private void saveTop(int top) {
136 | Utils.saveTop(top);
137 | if (Utils.loadTop() == initOffset) {
138 | Utils.setScrollToBottom(false);
139 | } else if (Utils.loadTop() == minOffset) {
140 | Utils.setScrollToBottom(true);
141 | }
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/calendar/src/main/java/com/ldf/calendar/component/CalendarAttr.java:
--------------------------------------------------------------------------------
1 | package com.ldf.calendar.component;
2 |
3 | /**
4 | * Created by ldf on 17/6/26.
5 | */
6 |
7 | public class CalendarAttr {
8 | /**
9 | * 以何种方式排列星期:
10 | * {@link CalendarAttr.WeekArrayType}
11 | */
12 | private WeekArrayType weekArrayType;
13 |
14 | /**
15 | * 日历周布局或者月布局:
16 | * {@link CalendarType} 布局类型
17 | */
18 | private CalendarType calendarType;
19 |
20 | /**
21 | * 日期格子高度
22 | */
23 | private int cellHeight;
24 |
25 | /**
26 | * 日期格子宽度
27 | */
28 | private int cellWidth;
29 |
30 | public WeekArrayType getWeekArrayType() {
31 | return weekArrayType;
32 | }
33 |
34 | public void setWeekArrayType(WeekArrayType weekArrayType) {
35 | this.weekArrayType = weekArrayType;
36 | }
37 |
38 | public CalendarType getCalendarType() {
39 | return calendarType;
40 | }
41 |
42 | public void setCalendarType(CalendarType calendarType) {
43 | this.calendarType = calendarType;
44 | }
45 |
46 | public int getCellHeight() {
47 | return cellHeight;
48 | }
49 |
50 | public void setCellHeight(int cellHeight) {
51 | this.cellHeight = cellHeight;
52 | }
53 |
54 | public int getCellWidth() {
55 | return cellWidth;
56 | }
57 |
58 | public void setCellWidth(int cellWidth) {
59 | this.cellWidth = cellWidth;
60 | }
61 |
62 | public enum WeekArrayType {
63 | /*周日作为本周的第一天*/Sunday,
64 | /*周一作为本周的第一天*/Monday
65 | }
66 |
67 | public enum CalendarType {
68 | WEEK, MONTH
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/calendar/src/main/java/com/ldf/calendar/component/CalendarRenderer.java:
--------------------------------------------------------------------------------
1 | package com.ldf.calendar.component;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.util.Log;
6 |
7 | import com.ldf.calendar.Const;
8 | import com.ldf.calendar.Utils;
9 | import com.ldf.calendar.interf.IDayRenderer;
10 | import com.ldf.calendar.interf.OnSelectDateListener;
11 | import com.ldf.calendar.model.CalendarDate;
12 | import com.ldf.calendar.view.Calendar;
13 | import com.ldf.calendar.view.Day;
14 | import com.ldf.calendar.view.Week;
15 |
16 | /**
17 | * Created by ldf on 17/6/26.
18 | */
19 |
20 | public class CalendarRenderer {
21 | private Week weeks[] = new Week[Const.TOTAL_ROW]; // 行数组,每个元素代表一行
22 | private Calendar calendar;
23 | private CalendarAttr attr;
24 | private IDayRenderer dayRenderer;
25 | private Context context;
26 | private OnSelectDateListener onSelectDateListener; // 单元格点击回调事件
27 | private CalendarDate seedDate; //种子日期
28 | private CalendarDate selectedDate; //被选中的日期
29 | private int selectedRowIndex = 0;
30 |
31 | public CalendarRenderer(Calendar calendar, CalendarAttr attr, Context context) {
32 | this.calendar = calendar;
33 | this.attr = attr;
34 | this.context = context;
35 | }
36 |
37 | /**
38 | * 使用dayRenderer绘制每一天
39 | *
40 | * @return void
41 | */
42 | public void draw(Canvas canvas) {
43 | for (int row = 0; row < Const.TOTAL_ROW; row++) {
44 | if (weeks[row] != null) {
45 | for (int col = 0; col < Const.TOTAL_COL; col++) {
46 | if (weeks[row].days[col] != null) {
47 | dayRenderer.drawDay(canvas, weeks[row].days[col]);
48 | }
49 | }
50 | }
51 | }
52 | }
53 |
54 | /**
55 | * 点击某一天时刷新这一天的状态
56 | *
57 | * @return void
58 | */
59 | public void onClickDate(int col, int row) {
60 | if (col >= Const.TOTAL_COL || row >= Const.TOTAL_ROW)
61 | return;
62 | if (weeks[row] != null) {
63 | if (attr.getCalendarType() == CalendarAttr.CalendarType.MONTH) {
64 | if (weeks[row].days[col].getState() == State.CURRENT_MONTH) {
65 | weeks[row].days[col].setState(State.SELECT);
66 | selectedDate = weeks[row].days[col].getDate();
67 | CalendarViewAdapter.saveSelectedDate(selectedDate);
68 | onSelectDateListener.onSelectDate(selectedDate);
69 | seedDate = selectedDate;
70 | }
71 | // else if (weeks[row].days[col].getState() == State.PAST_MONTH) {
72 | // selectedDate = weeks[row].days[col].getDate();
73 | // CalendarViewAdapter.saveSelectedDate(selectedDate);
74 | // onSelectDateListener.onSelectOtherMonth(-1);
75 | // onSelectDateListener.onSelectDate(selectedDate);
76 | // } else if (weeks[row].days[col].getState() == State.NEXT_MONTH) {
77 | // selectedDate = weeks[row].days[col].getDate();
78 | // CalendarViewAdapter.saveSelectedDate(selectedDate);
79 | // onSelectDateListener.onSelectOtherMonth(1);
80 | // onSelectDateListener.onSelectDate(selectedDate);
81 | // }
82 | } else {
83 | weeks[row].days[col].setState(State.SELECT);
84 | selectedDate = weeks[row].days[col].getDate();
85 | CalendarViewAdapter.saveSelectedDate(selectedDate);
86 | onSelectDateListener.onSelectDate(selectedDate);
87 | seedDate = selectedDate;
88 | }
89 | }
90 | }
91 |
92 | /**
93 | * 刷新指定行的周数据
94 | *
95 | * @param rowIndex 参数月所在年
96 | * @return void
97 | */
98 | public void updateWeek(int rowIndex) {
99 | CalendarDate currentWeekLastDay;
100 | if (attr.getWeekArrayType() == CalendarAttr.WeekArrayType.Sunday) {
101 | currentWeekLastDay = Utils.getSaturday(seedDate);
102 | } else {
103 | currentWeekLastDay = Utils.getSunday(seedDate);
104 | }
105 | int day = currentWeekLastDay.day;
106 | for (int i = Const.TOTAL_COL - 1; i >= 0; i--) {
107 | CalendarDate date = currentWeekLastDay.modifyDay(day);
108 | if (weeks[rowIndex] == null) {
109 | weeks[rowIndex] = new Week(rowIndex);
110 | }
111 | if (weeks[rowIndex].days[i] != null) {
112 | if (date.equals(CalendarViewAdapter.loadSelectedDate())) {
113 | weeks[rowIndex].days[i].setState(State.SELECT);
114 | weeks[rowIndex].days[i].setDate(date);
115 | } else {
116 | weeks[rowIndex].days[i].setState(State.CURRENT_MONTH);
117 | weeks[rowIndex].days[i].setDate(date);
118 | }
119 | } else {
120 | if (date.equals(CalendarViewAdapter.loadSelectedDate())) {
121 | weeks[rowIndex].days[i] = new Day(State.SELECT, date, rowIndex, i);
122 | } else {
123 | weeks[rowIndex].days[i] = new Day(State.CURRENT_MONTH, date, rowIndex, i);
124 | }
125 | }
126 | day--;
127 | }
128 | }
129 |
130 | /**
131 | * 填充月数据
132 | *
133 | * @return void
134 | */
135 | private void instantiateMonth() {
136 | int lastMonthDays = Utils.getMonthDays(seedDate.year, seedDate.month - 1); // 上个月的天数
137 | int currentMonthDays = Utils.getMonthDays(seedDate.year, seedDate.month); // 当前月的天数
138 | int firstDayPosition = Utils.getFirstDayWeekPosition(
139 | seedDate.year,
140 | seedDate.month,
141 | attr.getWeekArrayType());
142 | Log.e("ldf","firstDayPosition = " + firstDayPosition);
143 |
144 | int day = 0;
145 | for (int row = 0; row < Const.TOTAL_ROW; row++) {
146 | day = fillWeek(lastMonthDays, currentMonthDays, firstDayPosition, day, row);
147 | }
148 | }
149 |
150 | public CalendarDate getFirstDate() {
151 | Week week = weeks[0];
152 | Day day = week.days[0];
153 | return day.getDate();
154 | }
155 |
156 | public CalendarDate getLastDate() {
157 | Week week = weeks[weeks.length - 1];
158 | Day day = week.days[week.days.length - 1];
159 | return day.getDate();
160 | }
161 |
162 | /**
163 | * 填充月中周数据
164 | *
165 | * @return void
166 | */
167 | private int fillWeek(int lastMonthDays,
168 | int currentMonthDays,
169 | int firstDayWeek,
170 | int day,
171 | int row) {
172 | for (int col = 0; col < Const.TOTAL_COL; col++) {
173 | int position = col + row * Const.TOTAL_COL;// 单元格位置
174 | if (position >= firstDayWeek && position < firstDayWeek + currentMonthDays) {
175 | day++;
176 | fillCurrentMonthDate(day, row, col);
177 | } else if (position < firstDayWeek) {
178 | instantiateLastMonth(lastMonthDays, firstDayWeek, row, col, position);
179 | } else if (position >= firstDayWeek + currentMonthDays) {
180 | instantiateNextMonth(currentMonthDays, firstDayWeek, row, col, position);
181 | }
182 | }
183 | return day;
184 | }
185 |
186 | private void fillCurrentMonthDate(int day, int row, int col) {
187 | CalendarDate date = seedDate.modifyDay(day);
188 | if (weeks[row] == null) {
189 | weeks[row] = new Week(row);
190 | }
191 | if (weeks[row].days[col] != null) {
192 | if (date.equals(CalendarViewAdapter.loadSelectedDate())) {
193 | weeks[row].days[col].setDate(date);
194 | weeks[row].days[col].setState(State.SELECT);
195 | } else {
196 | weeks[row].days[col].setDate(date);
197 | weeks[row].days[col].setState(State.CURRENT_MONTH);
198 | }
199 | } else {
200 | if (date.equals(CalendarViewAdapter.loadSelectedDate())) {
201 | weeks[row].days[col] = new Day(State.SELECT, date, row, col);
202 | } else {
203 | weeks[row].days[col] = new Day(State.CURRENT_MONTH, date, row, col);
204 | }
205 | }
206 | if (date.equals(seedDate)) {
207 | selectedRowIndex = row;
208 | }
209 | }
210 |
211 | private void instantiateNextMonth(int currentMonthDays,
212 | int firstDayWeek,
213 | int row,
214 | int col,
215 | int position) {
216 | CalendarDate date = new CalendarDate(
217 | seedDate.year,
218 | seedDate.month + 1,
219 | position - firstDayWeek - currentMonthDays + 1);
220 | if (weeks[row] == null) {
221 | weeks[row] = new Week(row);
222 | }
223 | if (weeks[row].days[col] != null) {
224 | weeks[row].days[col].setDate(date);
225 | weeks[row].days[col].setState(State.NEXT_MONTH);
226 | } else {
227 | weeks[row].days[col] = new Day(State.NEXT_MONTH, date, row, col);
228 | }
229 | // TODO: 17/6/27 当下一个月的天数大于七时,说明该月有六周
230 | // if(position - firstDayWeek - currentMonthDays + 1 >= 7) { //当下一个月的天数大于七时,说明该月有六周
231 | // }
232 | }
233 |
234 | private void instantiateLastMonth(int lastMonthDays, int firstDayWeek, int row, int col, int position) {
235 | CalendarDate date = new CalendarDate(
236 | seedDate.year,
237 | seedDate.month - 1,
238 | lastMonthDays - (firstDayWeek - position - 1));
239 | if (weeks[row] == null) {
240 | weeks[row] = new Week(row);
241 | }
242 | if (weeks[row].days[col] != null) {
243 | weeks[row].days[col].setDate(date);
244 | weeks[row].days[col].setState(State.PAST_MONTH);
245 | } else {
246 | weeks[row].days[col] = new Day(State.PAST_MONTH, date, row, col);
247 | }
248 | }
249 |
250 | /**
251 | * 根据种子日期孵化出本日历牌的数据
252 | *
253 | * @return void
254 | */
255 | public void showDate(CalendarDate seedDate) {
256 | if (seedDate != null) {
257 | this.seedDate = seedDate;
258 | } else {
259 | this.seedDate = new CalendarDate();
260 | }
261 | update();
262 | }
263 |
264 | public void update() {
265 | instantiateMonth();
266 | calendar.invalidate();
267 | }
268 |
269 | public CalendarDate getSeedDate() {
270 | return this.seedDate;
271 | }
272 |
273 | public void cancelSelectState() {
274 | for (int i = 0; i < Const.TOTAL_ROW; i++) {
275 | if (weeks[i] != null) {
276 | for (int j = 0; j < Const.TOTAL_COL; j++) {
277 | if (weeks[i].days[j].getState() == State.SELECT) {
278 | weeks[i].days[j].setState(State.CURRENT_MONTH);
279 | resetSelectedRowIndex();
280 | break;
281 | }
282 | }
283 | }
284 | }
285 | }
286 |
287 | public void resetSelectedRowIndex() {
288 | selectedRowIndex = 0;
289 | }
290 |
291 | public int getSelectedRowIndex() {
292 | return selectedRowIndex;
293 | }
294 |
295 | public void setSelectedRowIndex(int selectedRowIndex) {
296 | this.selectedRowIndex = selectedRowIndex;
297 | }
298 |
299 | public Calendar getCalendar() {
300 | return calendar;
301 | }
302 |
303 | public void setCalendar(Calendar calendar) {
304 | this.calendar = calendar;
305 | }
306 |
307 | public CalendarAttr getAttr() {
308 | return attr;
309 | }
310 |
311 | public void setAttr(CalendarAttr attr) {
312 | this.attr = attr;
313 | }
314 |
315 | public Context getContext() {
316 | return context;
317 | }
318 |
319 | public void setContext(Context context) {
320 | this.context = context;
321 | }
322 |
323 | public void setOnSelectDateListener(OnSelectDateListener onSelectDateListener) {
324 | this.onSelectDateListener = onSelectDateListener;
325 | }
326 |
327 | public void setDayRenderer(IDayRenderer dayRenderer) {
328 | this.dayRenderer = dayRenderer;
329 | }
330 | }
331 |
--------------------------------------------------------------------------------
/calendar/src/main/java/com/ldf/calendar/component/CalendarViewAdapter.java:
--------------------------------------------------------------------------------
1 | package com.ldf.calendar.component;
2 |
3 | import android.content.Context;
4 | import android.support.v4.view.PagerAdapter;
5 | import android.util.Log;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import com.ldf.calendar.interf.OnAdapterSelectListener;
10 | import com.ldf.calendar.interf.IDayRenderer;
11 | import com.ldf.calendar.interf.OnSelectDateListener;
12 | import com.ldf.calendar.Utils;
13 | import com.ldf.calendar.view.MonthPager;
14 | import com.ldf.calendar.model.CalendarDate;
15 | import com.ldf.calendar.view.Calendar;
16 |
17 | import java.util.ArrayList;
18 | import java.util.HashMap;
19 |
20 | public class CalendarViewAdapter extends PagerAdapter {
21 |
22 | private static CalendarDate date = new CalendarDate();
23 | private ArrayList calendars = new ArrayList<>();
24 | private int currentPosition = MonthPager.CURRENT_DAY_INDEX;
25 | private CalendarAttr.CalendarType calendarType = CalendarAttr.CalendarType.MONTH;
26 | private int rowCount = 0;
27 | private CalendarDate seedDate;
28 | private OnCalendarTypeChanged onCalendarTypeChangedListener;
29 | //周排列方式 1:代表周日显示为本周的第一天
30 | //0:代表周一显示为本周的第一天
31 | private CalendarAttr.WeekArrayType weekArrayType = CalendarAttr.WeekArrayType.Monday;
32 |
33 | public CalendarViewAdapter(Context context,
34 | OnSelectDateListener onSelectDateListener,
35 | CalendarAttr.WeekArrayType weekArrayType,
36 | IDayRenderer dayView) {
37 | super();
38 | this.weekArrayType = weekArrayType;
39 | init(context, onSelectDateListener);
40 | setCustomDayRenderer(dayView);
41 | }
42 |
43 | public static void saveSelectedDate(CalendarDate calendarDate) {
44 | date = calendarDate;
45 | }
46 |
47 | public static CalendarDate loadSelectedDate() {
48 | return date;
49 | }
50 |
51 | private void init(Context context, OnSelectDateListener onSelectDateListener) {
52 | saveSelectedDate(new CalendarDate());
53 | //初始化的种子日期为今天
54 | seedDate = new CalendarDate();
55 | for (int i = 0; i < 3; i++) {
56 | CalendarAttr calendarAttr = new CalendarAttr();
57 | calendarAttr.setCalendarType(CalendarAttr.CalendarType.MONTH);
58 | calendarAttr.setWeekArrayType(weekArrayType);
59 | Calendar calendar = new Calendar(context, onSelectDateListener, calendarAttr);
60 | calendar.setOnAdapterSelectListener(new OnAdapterSelectListener() {
61 | @Override
62 | public void cancelSelectState() {
63 | cancelOtherSelectState();
64 | }
65 |
66 | @Override
67 | public void updateSelectState() {
68 | invalidateCurrentCalendar();
69 | }
70 | });
71 | calendars.add(calendar);
72 | }
73 | }
74 |
75 | @Override
76 | public void setPrimaryItem(ViewGroup container, int position, Object object) {
77 | Log.e("ldf", "setPrimaryItem");
78 | super.setPrimaryItem(container, position, object);
79 | this.currentPosition = position;
80 | }
81 |
82 | @Override
83 | public Object instantiateItem(ViewGroup container, int position) {
84 | Log.e("ldf", "instantiateItem");
85 | if (position < 2) {
86 | return null;
87 | }
88 | Calendar calendar = calendars.get(position % calendars.size());
89 | if (calendarType == CalendarAttr.CalendarType.MONTH) {
90 | CalendarDate current = seedDate.modifyMonth(position - MonthPager.CURRENT_DAY_INDEX);
91 | current.setDay(1);//每月的种子日期都是1号
92 | calendar.showDate(current);
93 | } else {
94 | CalendarDate current = seedDate.modifyWeek(position - MonthPager.CURRENT_DAY_INDEX);
95 | if (weekArrayType == CalendarAttr.WeekArrayType.Sunday) {
96 | calendar.showDate(Utils.getSaturday(current));
97 | } else {
98 | calendar.showDate(Utils.getSunday(current));
99 | }//每周的种子日期为这一周的最后一天
100 | calendar.updateWeek(rowCount);
101 | }
102 | if (container.getChildCount() == calendars.size()) {
103 | container.removeView(calendars.get(position % 3));
104 | }
105 | if (container.getChildCount() < calendars.size()) {
106 | container.addView(calendar, 0);
107 | } else {
108 | container.addView(calendar, position % 3);
109 | }
110 | return calendar;
111 | }
112 |
113 | @Override
114 | public int getCount() {
115 | return Integer.MAX_VALUE;
116 | }
117 |
118 | @Override
119 | public boolean isViewFromObject(View view, Object object) {
120 | return view == ((View) object);
121 | }
122 |
123 | @Override
124 | public void destroyItem(ViewGroup container, int position, Object object) {
125 | container.removeView(container);
126 | }
127 |
128 | public ArrayList getPagers() {
129 | return calendars;
130 | }
131 |
132 | public CalendarDate getFirstVisibleDate() {
133 | return calendars.get(currentPosition % 3).getFirstDate();
134 | }
135 |
136 | public CalendarDate getLastVisibleDate() {
137 | return calendars.get(currentPosition % 3).getLastDate();
138 | }
139 |
140 | public void cancelOtherSelectState() {
141 | for (int i = 0; i < calendars.size(); i++) {
142 | Calendar calendar = calendars.get(i);
143 | calendar.cancelSelectState();
144 | }
145 | }
146 |
147 | public void invalidateCurrentCalendar() {
148 | for (int i = 0; i < calendars.size(); i++) {
149 | Calendar calendar = calendars.get(i);
150 | calendar.update();
151 | if (calendar.getCalendarType() == CalendarAttr.CalendarType.WEEK) {
152 | calendar.updateWeek(rowCount);
153 | }
154 | }
155 | }
156 |
157 | public void setMarkData(HashMap markData) {
158 | Utils.setMarkData(markData);
159 | notifyDataChanged();
160 | }
161 |
162 | public void switchToMonth() {
163 | if (calendars != null && calendars.size() > 0 && calendarType != CalendarAttr.CalendarType.MONTH) {
164 | if (onCalendarTypeChangedListener != null) {
165 | onCalendarTypeChangedListener.onCalendarTypeChanged(CalendarAttr.CalendarType.MONTH);
166 | }
167 | calendarType = CalendarAttr.CalendarType.MONTH;
168 | MonthPager.CURRENT_DAY_INDEX = currentPosition;
169 | Calendar v = calendars.get(currentPosition % 3);//0
170 | seedDate = v.getSeedDate();
171 |
172 | Calendar v1 = calendars.get(currentPosition % 3);//0
173 | v1.switchCalendarType(CalendarAttr.CalendarType.MONTH);
174 | v1.showDate(seedDate);
175 |
176 | Calendar v2 = calendars.get((currentPosition - 1) % 3);//2
177 | v2.switchCalendarType(CalendarAttr.CalendarType.MONTH);
178 | CalendarDate last = seedDate.modifyMonth(-1);
179 | last.setDay(1);
180 | v2.showDate(last);
181 |
182 | Calendar v3 = calendars.get((currentPosition + 1) % 3);//1
183 | v3.switchCalendarType(CalendarAttr.CalendarType.MONTH);
184 | CalendarDate next = seedDate.modifyMonth(1);
185 | next.setDay(1);
186 | v3.showDate(next);
187 | }
188 | }
189 |
190 | public void switchToWeek(int rowIndex) {
191 | rowCount = rowIndex;
192 | if (calendars != null && calendars.size() > 0 && calendarType != CalendarAttr.CalendarType.WEEK) {
193 | if (onCalendarTypeChangedListener != null) {
194 | onCalendarTypeChangedListener.onCalendarTypeChanged(CalendarAttr.CalendarType.WEEK);
195 | }
196 | calendarType = CalendarAttr.CalendarType.WEEK;
197 | MonthPager.CURRENT_DAY_INDEX = currentPosition;
198 | Calendar v = calendars.get(currentPosition % 3);
199 | seedDate = v.getSeedDate();
200 |
201 | rowCount = v.getSelectedRowIndex();
202 |
203 | Calendar v1 = calendars.get(currentPosition % 3);
204 | v1.switchCalendarType(CalendarAttr.CalendarType.WEEK);
205 | v1.showDate(seedDate);
206 | v1.updateWeek(rowIndex);
207 |
208 | Calendar v2 = calendars.get((currentPosition - 1) % 3);
209 | v2.switchCalendarType(CalendarAttr.CalendarType.WEEK);
210 | CalendarDate last = seedDate.modifyWeek(-1);
211 | if (weekArrayType == CalendarAttr.WeekArrayType.Sunday) {
212 | v2.showDate(Utils.getSaturday(last));
213 | } else {
214 | v2.showDate(Utils.getSunday(last));
215 | }//每周的种子日期为这一周的最后一天
216 | v2.updateWeek(rowIndex);
217 |
218 | Calendar v3 = calendars.get((currentPosition + 1) % 3);
219 | v3.switchCalendarType(CalendarAttr.CalendarType.WEEK);
220 | CalendarDate next = seedDate.modifyWeek(1);
221 | if (weekArrayType == CalendarAttr.WeekArrayType.Sunday) {
222 | v3.showDate(Utils.getSaturday(next));
223 | } else {
224 | v3.showDate(Utils.getSunday(next));
225 | }//每周的种子日期为这一周的最后一天
226 | v3.updateWeek(rowIndex);
227 | }
228 | }
229 |
230 | public void notifyMonthDataChanged(CalendarDate date) {
231 | seedDate = date;
232 | refreshCalendar();
233 | }
234 |
235 | public void notifyDataChanged(CalendarDate date) {
236 | seedDate = date;
237 | saveSelectedDate(date);
238 | refreshCalendar();
239 | }
240 |
241 | public void notifyDataChanged() {
242 | refreshCalendar();
243 | }
244 |
245 | private void refreshCalendar() {
246 | if (calendarType == CalendarAttr.CalendarType.WEEK) {
247 | MonthPager.CURRENT_DAY_INDEX = currentPosition;
248 | Calendar v1 = calendars.get(currentPosition % 3);
249 | v1.showDate(seedDate);
250 | v1.updateWeek(rowCount);
251 |
252 | Calendar v2 = calendars.get((currentPosition - 1) % 3);
253 | CalendarDate last = seedDate.modifyWeek(-1);
254 | if (weekArrayType == CalendarAttr.WeekArrayType.Sunday) {
255 | v2.showDate(Utils.getSaturday(last));
256 | } else {
257 | v2.showDate(Utils.getSunday(last));
258 | }
259 | v2.updateWeek(rowCount);
260 |
261 | Calendar v3 = calendars.get((currentPosition + 1) % 3);
262 | CalendarDate next = seedDate.modifyWeek(1);
263 | if (weekArrayType == CalendarAttr.WeekArrayType.Sunday) {
264 | v3.showDate(Utils.getSaturday(next));
265 | } else {
266 | v3.showDate(Utils.getSunday(next));
267 | }//每周的种子日期为这一周的最后一天
268 | v3.updateWeek(rowCount);
269 | } else {
270 | MonthPager.CURRENT_DAY_INDEX = currentPosition;
271 |
272 | Calendar v1 = calendars.get(currentPosition % 3);//0
273 | v1.showDate(seedDate);
274 |
275 | Calendar v2 = calendars.get((currentPosition - 1) % 3);//2
276 | CalendarDate last = seedDate.modifyMonth(-1);
277 | last.setDay(1);
278 | v2.showDate(last);
279 |
280 | Calendar v3 = calendars.get((currentPosition + 1) % 3);//1
281 | CalendarDate next = seedDate.modifyMonth(1);
282 | next.setDay(1);
283 | v3.showDate(next);
284 | }
285 | }
286 |
287 | public CalendarAttr.CalendarType getCalendarType() {
288 | return calendarType;
289 | }
290 |
291 | /**
292 | * 为每一个Calendar实例设置renderer对象
293 | *
294 | * @return void
295 | */
296 | public void setCustomDayRenderer(IDayRenderer dayRenderer) {
297 | Calendar c0 = calendars.get(0);
298 | c0.setDayRenderer(dayRenderer);
299 |
300 | Calendar c1 = calendars.get(1);
301 | c1.setDayRenderer(dayRenderer.copy());
302 |
303 | Calendar c2 = calendars.get(2);
304 | c2.setDayRenderer(dayRenderer.copy());
305 | }
306 |
307 | public void setOnCalendarTypeChangedListener(OnCalendarTypeChanged onCalendarTypeChangedListener) {
308 | this.onCalendarTypeChangedListener = onCalendarTypeChangedListener;
309 | }
310 |
311 | public CalendarAttr.WeekArrayType getWeekArrayType() {
312 | return weekArrayType;
313 | }
314 |
315 | public interface OnCalendarTypeChanged {
316 | void onCalendarTypeChanged(CalendarAttr.CalendarType type);
317 | }
318 | }
--------------------------------------------------------------------------------
/calendar/src/main/java/com/ldf/calendar/component/State.java:
--------------------------------------------------------------------------------
1 | package com.ldf.calendar.component;
2 |
3 | /**
4 | * Created by ldf on 17/6/27.
5 | */
6 |
7 | public enum State {
8 | CURRENT_MONTH, PAST_MONTH, NEXT_MONTH, SELECT
9 | }
10 |
--------------------------------------------------------------------------------
/calendar/src/main/java/com/ldf/calendar/interf/IDayRenderer.java:
--------------------------------------------------------------------------------
1 | package com.ldf.calendar.interf;
2 |
3 | import android.graphics.Canvas;
4 |
5 | import com.ldf.calendar.component.State;
6 | import com.ldf.calendar.model.CalendarDate;
7 | import com.ldf.calendar.view.Day;
8 | import com.ldf.calendar.view.DayView;
9 |
10 | /**
11 | * Created by ldf on 17/6/26.
12 | */
13 |
14 | public interface IDayRenderer {
15 |
16 | void refreshContent();
17 |
18 | void drawDay(Canvas canvas, Day day);
19 |
20 | IDayRenderer copy();
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/calendar/src/main/java/com/ldf/calendar/interf/OnAdapterSelectListener.java:
--------------------------------------------------------------------------------
1 | package com.ldf.calendar.interf;
2 |
3 | import com.ldf.calendar.model.CalendarDate;
4 |
5 | /**
6 | * Created by ldf on 17/6/15.
7 | */
8 |
9 | public interface OnAdapterSelectListener {
10 | void cancelSelectState();
11 | void updateSelectState();
12 | }
13 |
--------------------------------------------------------------------------------
/calendar/src/main/java/com/ldf/calendar/interf/OnSelectDateListener.java:
--------------------------------------------------------------------------------
1 | package com.ldf.calendar.interf;
2 |
3 | import com.ldf.calendar.model.CalendarDate;
4 |
5 | /**
6 | * Created by ldf on 17/6/2.
7 | */
8 |
9 | public interface OnSelectDateListener {
10 | void onSelectDate(CalendarDate date);
11 |
12 | void onSelectOtherMonth(int offset);//点击其它月份日期
13 | }
14 |
--------------------------------------------------------------------------------
/calendar/src/main/java/com/ldf/calendar/model/CalendarDate.java:
--------------------------------------------------------------------------------
1 | package com.ldf.calendar.model;
2 |
3 | import android.util.Log;
4 |
5 | import com.ldf.calendar.Utils;
6 |
7 | import java.io.Serializable;
8 | import java.util.Calendar;
9 |
10 | public class CalendarDate implements Serializable {
11 | private static final long serialVersionUID = 1L;
12 | public int year;
13 | public int month; //1~12
14 | public int day;
15 |
16 | public CalendarDate(int year, int month, int day) {
17 | if (month > 12) {
18 | month = 1;
19 | year++;
20 | } else if (month < 1) {
21 | month = 12;
22 | year--;
23 | }
24 | this.year = year;
25 | this.month = month;
26 | this.day = day;
27 | }
28 |
29 | public CalendarDate() {
30 | this.year = Utils.getYear();
31 | this.month = Utils.getMonth();
32 | this.day = Utils.getDay();
33 | }
34 |
35 | /**
36 | * 通过修改当前Date对象的天数返回一个修改后的Date
37 | *
38 | * @return CalendarDate 修改后的日期
39 | */
40 | public CalendarDate modifyDay(int day) {
41 | int lastMonthDays = Utils.getMonthDays(this.year, this.month - 1);
42 | int currentMonthDays = Utils.getMonthDays(this.year, this.month);
43 |
44 | CalendarDate modifyDate;
45 | if (day > currentMonthDays) {
46 | modifyDate = new CalendarDate(this.year, this.month, this.day);
47 | Log.e("ldf", "移动天数过大");
48 | } else if (day > 0) {
49 | modifyDate = new CalendarDate(this.year, this.month, day);
50 | } else if (day > 0 - lastMonthDays) {
51 | modifyDate = new CalendarDate(this.year, this.month - 1, lastMonthDays + day);
52 | } else {
53 | modifyDate = new CalendarDate(this.year, this.month, this.day);
54 | Log.e("ldf", "移动天数过大");
55 | }
56 | return modifyDate;
57 | }
58 |
59 | /**
60 | * 通过修改当前Date对象的所在周返回一个修改后的Date
61 | *
62 | * @return CalendarDate 修改后的日期
63 | */
64 | public CalendarDate modifyWeek(int offset) {
65 | CalendarDate result = new CalendarDate();
66 | Calendar c = Calendar.getInstance();
67 | c.set(Calendar.YEAR, year);
68 | c.set(Calendar.MONTH, month - 1);
69 | c.set(Calendar.DAY_OF_MONTH, day);
70 | c.add(Calendar.DATE, offset * 7);
71 | result.setYear(c.get(Calendar.YEAR));
72 | result.setMonth(c.get(Calendar.MONTH) + 1);
73 | result.setDay(c.get(Calendar.DATE));
74 | return result;
75 | }
76 |
77 | /**
78 | * 通过修改当前Date对象的所在月返回一个修改后的Date
79 | *
80 | * @return CalendarDate 修改后的日期
81 | */
82 | public CalendarDate modifyMonth(int offset) {
83 | CalendarDate result = new CalendarDate();
84 | int addToMonth = this.month + offset;
85 | if (offset > 0) {
86 | if (addToMonth > 12) {
87 | result.setYear(this.year + (addToMonth - 1) / 12);
88 | result.setMonth(addToMonth % 12 == 0 ? 12 : addToMonth % 12);
89 | } else {
90 | result.setYear(this.year);
91 | result.setMonth(addToMonth);
92 | }
93 | } else {
94 | if (addToMonth == 0) {
95 | result.setYear(this.year - 1);
96 | result.setMonth(12);
97 | } else if (addToMonth < 0) {
98 | result.setYear(this.year + addToMonth / 12 - 1);
99 | int month = 12 - Math.abs(addToMonth) % 12;
100 | result.setMonth(month == 0 ? 12 : month);
101 | } else {
102 | result.setYear(this.year);
103 | result.setMonth(addToMonth == 0 ? 12 : addToMonth);
104 | }
105 | }
106 | return result;
107 | }
108 |
109 | @Override
110 | public String toString() {
111 | return year + "-" + month + "-" + day;
112 | }
113 |
114 | public int getYear() {
115 | return year;
116 | }
117 |
118 | public void setYear(int year) {
119 | this.year = year;
120 | }
121 |
122 | public int getMonth() {
123 | return month;
124 | }
125 |
126 | public void setMonth(int month) {
127 | this.month = month;
128 | }
129 |
130 | public int getDay() {
131 | return day;
132 | }
133 |
134 | public void setDay(int day) {
135 | this.day = day;
136 | }
137 |
138 | public boolean equals(CalendarDate date) {
139 | if (date == null) {
140 | return false;
141 | }
142 | if (this.getYear() == date.getYear()
143 | && this.getMonth() == date.getMonth()
144 | && this.getDay() == date.getDay()) {
145 | return true;
146 | }
147 | return false;
148 | }
149 |
150 | public CalendarDate cloneSelf() {
151 | return new CalendarDate(year, month, day);
152 | }
153 |
154 | }
--------------------------------------------------------------------------------
/calendar/src/main/java/com/ldf/calendar/view/Calendar.java:
--------------------------------------------------------------------------------
1 | package com.ldf.calendar.view;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.graphics.Canvas;
6 | import android.view.MotionEvent;
7 | import android.view.View;
8 |
9 | import com.ldf.calendar.Const;
10 | import com.ldf.calendar.interf.IDayRenderer;
11 | import com.ldf.calendar.interf.OnAdapterSelectListener;
12 | import com.ldf.calendar.component.CalendarAttr;
13 | import com.ldf.calendar.component.CalendarRenderer;
14 | import com.ldf.calendar.interf.OnSelectDateListener;
15 | import com.ldf.calendar.model.CalendarDate;
16 | import com.ldf.calendar.Utils;
17 |
18 | @SuppressLint("ViewConstructor")
19 | public class Calendar extends View {
20 | /**
21 | * 日历列数
22 | */
23 | private CalendarAttr.CalendarType calendarType;
24 | private int cellHeight; // 单元格高度
25 | private int cellWidth; // 单元格宽度
26 |
27 | private OnSelectDateListener onSelectDateListener; // 单元格点击回调事件
28 | private Context context;
29 | private CalendarAttr calendarAttr;
30 | private CalendarRenderer renderer;
31 |
32 | private OnAdapterSelectListener onAdapterSelectListener;
33 | private float touchSlop;
34 |
35 | public Calendar(Context context,
36 | OnSelectDateListener onSelectDateListener,
37 | CalendarAttr attr) {
38 | super(context);
39 | this.onSelectDateListener = onSelectDateListener;
40 | calendarAttr = attr;
41 | init(context);
42 | }
43 |
44 | private void init(Context context) {
45 | this.context = context;
46 | touchSlop = Utils.getTouchSlop(context);
47 | initAttrAndRenderer();
48 | }
49 |
50 | private void initAttrAndRenderer() {
51 | renderer = new CalendarRenderer(this, calendarAttr, context);
52 | renderer.setOnSelectDateListener(onSelectDateListener);
53 | }
54 |
55 | @Override
56 | protected void onDraw(Canvas canvas) {
57 | super.onDraw(canvas);
58 | renderer.draw(canvas);
59 | }
60 |
61 | @Override
62 | protected void onSizeChanged(int w, int h, int oldW, int oldH) {
63 | super.onSizeChanged(w, h, oldW, oldH);
64 | cellHeight = h / Const.TOTAL_ROW;
65 | cellWidth = w / Const.TOTAL_COL;
66 | calendarAttr.setCellHeight(cellHeight);
67 | calendarAttr.setCellWidth(cellWidth);
68 | renderer.setAttr(calendarAttr);
69 | }
70 |
71 | private float posX = 0;
72 | private float posY = 0;
73 |
74 | /*
75 | * 触摸事件为了确定点击的位置日期
76 | */
77 | @Override
78 | public boolean onTouchEvent(MotionEvent event) {
79 | switch (event.getAction()) {
80 | case MotionEvent.ACTION_DOWN:
81 | posX = event.getX();
82 | posY = event.getY();
83 | break;
84 | case MotionEvent.ACTION_UP:
85 | float disX = event.getX() - posX;
86 | float disY = event.getY() - posY;
87 | if (Math.abs(disX) < touchSlop && Math.abs(disY) < touchSlop) {
88 | int col = (int) (posX / cellWidth);
89 | int row = (int) (posY / cellHeight);
90 | onAdapterSelectListener.cancelSelectState();
91 | renderer.onClickDate(col, row);
92 | onAdapterSelectListener.updateSelectState();
93 | invalidate();
94 | }
95 | break;
96 | }
97 | return true;
98 | }
99 |
100 | public CalendarAttr.CalendarType getCalendarType() {
101 | return calendarAttr.getCalendarType();
102 | }
103 |
104 | public void switchCalendarType(CalendarAttr.CalendarType calendarType) {
105 | calendarAttr.setCalendarType(calendarType);
106 | renderer.setAttr(calendarAttr);
107 | }
108 |
109 | public int getCellHeight() {
110 | return cellHeight;
111 | }
112 |
113 | public void resetSelectedRowIndex() {
114 | renderer.resetSelectedRowIndex();
115 | }
116 |
117 | public int getSelectedRowIndex() {
118 | return renderer.getSelectedRowIndex();
119 | }
120 |
121 | public void setSelectedRowIndex(int selectedRowIndex) {
122 | renderer.setSelectedRowIndex(selectedRowIndex);
123 | }
124 |
125 | public void setOnAdapterSelectListener(OnAdapterSelectListener onAdapterSelectListener) {
126 | this.onAdapterSelectListener = onAdapterSelectListener;
127 | }
128 |
129 | public void showDate(CalendarDate current) {
130 | renderer.showDate(current);
131 | }
132 |
133 | public void updateWeek(int rowCount) {
134 | renderer.updateWeek(rowCount);
135 | invalidate();
136 | }
137 |
138 | public void update() {
139 | renderer.update();
140 | }
141 |
142 | public void cancelSelectState() {
143 | renderer.cancelSelectState();
144 | }
145 |
146 | public CalendarDate getSeedDate() {
147 | return renderer.getSeedDate();
148 | }
149 |
150 | public CalendarDate getFirstDate() {
151 | return renderer.getFirstDate();
152 | }
153 |
154 | public CalendarDate getLastDate() {
155 | return renderer.getLastDate();
156 | }
157 |
158 | public void setDayRenderer(IDayRenderer dayRenderer) {
159 | renderer.setDayRenderer(dayRenderer);
160 | }
161 | }
--------------------------------------------------------------------------------
/calendar/src/main/java/com/ldf/calendar/view/Day.java:
--------------------------------------------------------------------------------
1 | package com.ldf.calendar.view;
2 |
3 | import android.os.Parcel;
4 | import android.os.Parcelable;
5 |
6 | import com.ldf.calendar.component.State;
7 | import com.ldf.calendar.model.CalendarDate;
8 |
9 | /**
10 | * Created by ldf on 17/7/5.
11 | */
12 |
13 | public class Day implements Parcelable {
14 | private State state;
15 | private CalendarDate date;
16 | private int posRow;
17 | private int posCol;
18 |
19 | public Day(State state , CalendarDate date , int posRow , int posCol) {
20 | this.state = state;
21 | this.date = date;
22 | this.posRow = posRow;
23 | this.posCol = posCol;
24 | }
25 |
26 | public State getState() {
27 | return state;
28 | }
29 |
30 | public void setState(State state) {
31 | this.state = state;
32 | }
33 |
34 | public CalendarDate getDate() {
35 | return date;
36 | }
37 |
38 | public void setDate(CalendarDate date) {
39 | this.date = date;
40 | }
41 |
42 | public int getPosRow() {
43 | return posRow;
44 | }
45 |
46 | public void setPosRow(int posRow) {
47 | this.posRow = posRow;
48 | }
49 |
50 | public int getPosCol() {
51 | return posCol;
52 | }
53 |
54 | public void setPosCol(int posCol) {
55 | this.posCol = posCol;
56 | }
57 |
58 | @Override
59 | public int describeContents() {
60 | return 0;
61 | }
62 |
63 | @Override
64 | public void writeToParcel(Parcel dest, int flags) {
65 | dest.writeInt(this.state == null ? -1 : this.state.ordinal());
66 | dest.writeSerializable(this.date);
67 | dest.writeInt(this.posRow);
68 | dest.writeInt(this.posCol);
69 | }
70 |
71 | protected Day(Parcel in) {
72 | int tmpState = in.readInt();
73 | this.state = tmpState == -1 ? null : State.values()[tmpState];
74 | this.date = (CalendarDate) in.readSerializable();
75 | this.posRow = in.readInt();
76 | this.posCol = in.readInt();
77 | }
78 |
79 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
80 | @Override
81 | public Day createFromParcel(Parcel source) {
82 | return new Day(source);
83 | }
84 |
85 | @Override
86 | public Day[] newArray(int size) {
87 | return new Day[size];
88 | }
89 | };
90 | }
91 |
--------------------------------------------------------------------------------
/calendar/src/main/java/com/ldf/calendar/view/DayView.java:
--------------------------------------------------------------------------------
1 | package com.ldf.calendar.view;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.util.Log;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.widget.RelativeLayout;
9 |
10 | import com.ldf.calendar.Utils;
11 | import com.ldf.calendar.component.State;
12 | import com.ldf.calendar.interf.IDayRenderer;
13 | import com.ldf.calendar.model.CalendarDate;
14 |
15 | /**
16 | * Created by ldf on 16/10/19.
17 | */
18 |
19 | public abstract class DayView extends RelativeLayout implements IDayRenderer {
20 |
21 | protected Day day;
22 | protected Context context;
23 | protected int layoutResource;
24 |
25 | /**
26 | * 构造器 传入资源文件创建DayView
27 | *
28 | * @param layoutResource 资源文件
29 | * @param context 上下文
30 | */
31 | public DayView(Context context, int layoutResource) {
32 | super(context);
33 | setupLayoutResource(layoutResource);
34 | this.context = context;
35 | this.layoutResource = layoutResource;
36 | }
37 |
38 | /**
39 | * 为自定义的DayView设置资源文件
40 | *
41 | * @param layoutResource 资源文件
42 | * @return CalendarDate 修改后的日期
43 | */
44 | private void setupLayoutResource(int layoutResource) {
45 | View inflated = LayoutInflater.from(getContext()).inflate(layoutResource, this);
46 | inflated.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
47 | MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
48 | inflated.layout(0, 0, getMeasuredWidth(), getMeasuredHeight());
49 | }
50 |
51 | @Override
52 | public void refreshContent() {
53 | measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
54 | MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
55 | layout(0, 0, getMeasuredWidth(), getMeasuredHeight());
56 | }
57 |
58 | @Override
59 | public void drawDay(Canvas canvas, Day day) {
60 | this.day = day;
61 | refreshContent();
62 | int saveId = canvas.save();
63 | canvas.translate(getTranslateX(canvas, day),
64 | day.getPosRow() * getMeasuredHeight());
65 | draw(canvas);
66 | canvas.restoreToCount(saveId);
67 | }
68 |
69 | private int getTranslateX(Canvas canvas, Day day) {
70 | int dx;
71 | int canvasWidth = canvas.getWidth() / 7;
72 | int viewWidth = getMeasuredWidth();
73 | int moveX = (canvasWidth - viewWidth) / 2;
74 | dx = day.getPosCol() * canvasWidth + moveX;
75 | return dx;
76 | }
77 |
78 | @Override
79 | protected void onDetachedFromWindow() {
80 | super.onDetachedFromWindow();
81 | Utils.cleanMarkData();
82 | }
83 | }
--------------------------------------------------------------------------------
/calendar/src/main/java/com/ldf/calendar/view/MonthPager.java:
--------------------------------------------------------------------------------
1 | package com.ldf.calendar.view;
2 |
3 | import android.content.Context;
4 | import android.support.design.widget.CoordinatorLayout;
5 | import android.support.v4.view.ViewPager;
6 | import android.util.AttributeSet;
7 | import android.util.Log;
8 | import android.view.MotionEvent;
9 |
10 | import com.ldf.calendar.behavior.MonthPagerBehavior;
11 | import com.ldf.calendar.component.CalendarViewAdapter;
12 |
13 | @CoordinatorLayout.DefaultBehavior(MonthPagerBehavior.class)
14 | public class MonthPager extends ViewPager {
15 | public static int CURRENT_DAY_INDEX = 1000;
16 |
17 | private int currentPosition = CURRENT_DAY_INDEX;
18 | private int cellHeight;
19 | private int viewHeight;
20 | private int rowIndex = 6;
21 |
22 | private OnPageChangeListener monthPageChangeListener;
23 | private boolean pageChangeByGesture = false;
24 | private boolean hasPageChangeListener = false;
25 | private boolean scrollable = true;
26 | private int pageScrollState = ViewPager.SCROLL_STATE_IDLE;
27 |
28 | public MonthPager(Context context) {
29 | this(context, null);
30 | }
31 |
32 | public MonthPager(Context context, AttributeSet attrs) {
33 | super(context, attrs);
34 | init();
35 | }
36 |
37 | private void init() {
38 | ViewPager.OnPageChangeListener viewPageChangeListener = new ViewPager.OnPageChangeListener() {
39 | @Override
40 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
41 | if (monthPageChangeListener != null) {
42 | monthPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
43 | }
44 | }
45 |
46 | @Override
47 | public void onPageSelected(int position) {
48 | currentPosition = position;
49 | if (pageChangeByGesture) {
50 | if (monthPageChangeListener != null) {
51 | monthPageChangeListener.onPageSelected(position);
52 | }
53 | pageChangeByGesture = false;
54 | }
55 | }
56 |
57 | @Override
58 | public void onPageScrollStateChanged(int state) {
59 | pageScrollState = state;
60 | if (monthPageChangeListener != null) {
61 | monthPageChangeListener.onPageScrollStateChanged(state);
62 | }
63 | pageChangeByGesture = true;
64 | }
65 | };
66 | addOnPageChangeListener(viewPageChangeListener);
67 | hasPageChangeListener = true;
68 | }
69 |
70 | @Override
71 | public void addOnPageChangeListener(ViewPager.OnPageChangeListener listener) {
72 | if (hasPageChangeListener) {
73 | Log.e("ldf", "MonthPager Just Can Use Own OnPageChangeListener");
74 | } else {
75 | super.addOnPageChangeListener(listener);
76 | }
77 | }
78 |
79 | public void addOnPageChangeListener(OnPageChangeListener listener) {
80 | this.monthPageChangeListener = listener;
81 | Log.e("ldf", "MonthPager Just Can Use Own OnPageChangeListener");
82 | }
83 |
84 | public void setScrollable(boolean scrollable) {
85 | this.scrollable = scrollable;
86 | }
87 |
88 | @Override
89 | public boolean onTouchEvent(MotionEvent me) {
90 | if (!scrollable)
91 | return false;
92 | else
93 | return super.onTouchEvent(me);
94 | }
95 |
96 | @Override
97 | public boolean onInterceptTouchEvent(MotionEvent me) {
98 | if (!scrollable)
99 | return false;
100 | else
101 | return super.onInterceptTouchEvent(me);
102 | }
103 |
104 | public void selectOtherMonth(int offset) {
105 | setCurrentItem(currentPosition + offset);
106 | CalendarViewAdapter calendarViewAdapter = (CalendarViewAdapter) getAdapter();
107 | calendarViewAdapter.notifyDataChanged(CalendarViewAdapter.loadSelectedDate());
108 | }
109 |
110 | public int getPageScrollState() {
111 | return pageScrollState;
112 | }
113 |
114 | public interface OnPageChangeListener {
115 | void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);
116 |
117 | void onPageSelected(int position);
118 |
119 | void onPageScrollStateChanged(int state);
120 | }
121 |
122 | public int getTopMovableDistance() {
123 | CalendarViewAdapter calendarViewAdapter = (CalendarViewAdapter) getAdapter();
124 | if(calendarViewAdapter == null) {
125 | return cellHeight;
126 | }
127 | rowIndex = calendarViewAdapter.getPagers().get(currentPosition % 3).getSelectedRowIndex();
128 | return cellHeight * rowIndex;
129 | }
130 |
131 | public int getCellHeight() {
132 | return cellHeight;
133 | }
134 |
135 | public void setViewHeight(int viewHeight) {
136 | cellHeight = viewHeight / 6;
137 | this.viewHeight = viewHeight;
138 | }
139 |
140 | public int getViewHeight() {
141 | return viewHeight;
142 | }
143 |
144 | public int getCurrentPosition() {
145 | return currentPosition;
146 | }
147 |
148 | public void setCurrentPosition(int currentPosition) {
149 | this.currentPosition = currentPosition;
150 | }
151 |
152 | public int getRowIndex() {
153 | CalendarViewAdapter calendarViewAdapter = (CalendarViewAdapter) getAdapter();
154 | rowIndex = calendarViewAdapter.getPagers().get(currentPosition % 3).getSelectedRowIndex();
155 | Log.e("ldf", "getRowIndex = " + rowIndex);
156 | return rowIndex;
157 | }
158 |
159 | public void setRowIndex(int rowIndex) {
160 | this.rowIndex = rowIndex;
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/calendar/src/main/java/com/ldf/calendar/view/Week.java:
--------------------------------------------------------------------------------
1 | package com.ldf.calendar.view;
2 |
3 | import android.graphics.Canvas;
4 |
5 | import com.ldf.calendar.Const;
6 | import com.ldf.calendar.interf.IDayRenderer;
7 |
8 | /**
9 | * Created by ldf on 17/6/27.
10 | */
11 |
12 | public class Week {
13 | public int row;
14 | public Day[] days = new Day[Const.TOTAL_COL];
15 |
16 | public Week(int row) {
17 | this.row = row;
18 | }
19 |
20 | public int getRow() {
21 | return row;
22 | }
23 |
24 | public void setRow(int row) {
25 | this.row = row;
26 | }
27 |
28 | public Day[] getDays() {
29 | return days;
30 | }
31 |
32 | public void setDays(Day[] days) {
33 | this.days = days;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/calendar/src/readme:
--------------------------------------------------------------------------------
1 | 1. 左右滑动的view左边有时候也会显示今天的view,划过去之后才会变 - fixed
2 | 2. 月周切换问题
3 | 3. 收缩后的周日历滑动问题
4 | 4. 下拉时下面的view的滑动问题,能否做成先下拉下面的view, 拉不动时才处理上面的日历的view --fixed
5 | 5. 回到今天的问题(跳转到指定日期) - fixed
6 | 6. 滑动的下一页的选中问题 -- fixed
7 | 7. 自定义日历View的Wrap_content模式 --not fixed full
8 | 8. 日历和RecycleView的依赖关系是什么时候建立的
9 | 9. 不同分辨率的显示问题
--------------------------------------------------------------------------------
/calendar/src/test/java/com/ldf/mi/calendar/micalendar/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.ldf.mi.calendar.micalendar;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/example/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 26
5 | buildToolsVersion '26.0.2'
6 | defaultConfig {
7 | applicationId "com.hqyxjy.ldf.supercalendar"
8 | minSdkVersion 19
9 | targetSdkVersion 26
10 | versionCode 2
11 | versionName "2.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 |
20 | lintOptions {
21 | abortOnError false
22 | }
23 | dexOptions {
24 | incremental true
25 | }
26 | compileOptions {
27 | sourceCompatibility JavaVersion.VERSION_1_8
28 | targetCompatibility JavaVersion.VERSION_1_8
29 | }
30 | }
31 |
32 | dependencies {
33 | compile fileTree(include: ['*.jar'], dir: 'libs')
34 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
35 | exclude group: 'com.android.support', module: 'support-annotations'
36 | })
37 | compile 'com.android.support:appcompat-v7:26.1.0'
38 | testCompile 'junit:junit:4.12'
39 | compile project(path: ':calendar')
40 | }
41 |
--------------------------------------------------------------------------------
/example/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImVeryGood/SuperCalendar-master/1f9bbb256da25587f0cf2a558f0e438e0fb4744a/example/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/example/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Apr 02 11:29:06 GMT+08:00 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
7 |
--------------------------------------------------------------------------------
/example/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/example/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/example/local.properties:
--------------------------------------------------------------------------------
1 | ## This file must *NOT* be checked into Version Control Systems,
2 | # as it contains information specific to your local configuration.
3 | #
4 | # Location of the SDK. This is only used by Gradle.
5 | # For customization when using a Version Control System, please read the
6 | # header note.
7 | #Tue Apr 02 11:29:01 GMT+08:00 2019
8 | sdk.dir=C\:\\Users\\Administrator\\AppData\\Local\\Android\\Sdk
9 |
--------------------------------------------------------------------------------
/example/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/ldf/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/example/src/androidTest/java/com/hqyxjy/ldf/supercalendar/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.hqyxjy.ldf.supercalendar;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.hqyxjy.ldf.fuckcalendar", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/example/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/example/src/main/java/com/hqyxjy/ldf/supercalendar/CustomDayView.java:
--------------------------------------------------------------------------------
1 | package com.hqyxjy.ldf.supercalendar;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.graphics.Color;
6 | import android.util.Log;
7 | import android.view.View;
8 | import android.widget.ImageView;
9 | import android.widget.TextView;
10 |
11 | import com.ldf.calendar.Utils;
12 | import com.ldf.calendar.component.State;
13 | import com.ldf.calendar.interf.IDayRenderer;
14 | import com.ldf.calendar.model.CalendarDate;
15 | import com.ldf.calendar.view.DayView;
16 |
17 | import java.util.HashMap;
18 |
19 | /**
20 | * Created by ldf on 17/6/26.
21 | */
22 |
23 | @SuppressLint("ViewConstructor")
24 | public class CustomDayView extends DayView {
25 |
26 | private TextView dateTv;
27 | private ImageView marker;
28 | private View selectedBackground;
29 | private View todayBackground;
30 | private final CalendarDate today = new CalendarDate();
31 |
32 | /**
33 | * 构造器
34 | *
35 | * @param context 上下文
36 | * @param layoutResource 自定义DayView的layout资源
37 | */
38 | public CustomDayView(Context context, int layoutResource) {
39 | super(context, layoutResource);
40 | dateTv = (TextView) findViewById(R.id.date);
41 | marker = (ImageView) findViewById(R.id.maker);
42 | selectedBackground = findViewById(R.id.selected_background);
43 | todayBackground = findViewById(R.id.today_background);
44 | }
45 |
46 | @Override
47 | public void refreshContent() {
48 | renderToday(day.getDate(), day.getState());
49 | renderMarker(day.getDate(), day.getState());
50 | renderSelect(day.getDate(),day.getState());
51 | super.refreshContent();
52 | }
53 |
54 | private void renderMarker(CalendarDate date, State state) {
55 | //如果是当月,并且包含此Mark
56 | if (Utils.loadMarkData().containsKey(date.toString())&&state==State.CURRENT_MONTH) {
57 | marker.setVisibility(VISIBLE);
58 | if (Utils.loadMarkData().get(date.toString()).equals("0")) {
59 | marker.setEnabled(true);
60 | } else {
61 | marker.setEnabled(false);
62 | }
63 |
64 | } else {
65 | marker.setVisibility(GONE);
66 | }
67 | }
68 | private void renderSelect(CalendarDate date,State state) {
69 | if (state == State.SELECT) {
70 | // 本月
71 | selectedBackground.setVisibility(VISIBLE);
72 | dateTv.setTextColor(Color.WHITE);
73 | // 如果是是Mark就显示
74 | if (Utils.loadMarkData().containsKey(date.toString())){
75 | marker.setVisibility(VISIBLE);
76 | }
77 |
78 | } else if (state == State.NEXT_MONTH || state == State.PAST_MONTH) {
79 | // 不是本月
80 | selectedBackground.setVisibility(GONE);
81 | // dateTv.setTextColor(Color.parseColor("#5b5b5b"));
82 | dateTv.setText("");
83 | } else {
84 | selectedBackground.setVisibility(GONE);
85 | dateTv.setTextColor(Color.parseColor("#111111"));
86 | }
87 | }
88 |
89 | private void renderToday(CalendarDate date, State state) {
90 | if (date != null) {
91 | // 只渲染本月的
92 | if (date.equals(today) && state == State.SELECT) {
93 | dateTv.setText(date.day + "");
94 | todayBackground.setVisibility(VISIBLE);
95 | } else {
96 | dateTv.setText(date.day + "");
97 | todayBackground.setVisibility(GONE);
98 | }
99 | }
100 |
101 | }
102 |
103 | @Override
104 | public IDayRenderer copy() {
105 | return new CustomDayView(context, layoutResource);
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/example/src/main/java/com/hqyxjy/ldf/supercalendar/ExampleAdapter.java:
--------------------------------------------------------------------------------
1 | package com.hqyxjy.ldf.supercalendar;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.util.Log;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.TextView;
10 |
11 | /**
12 | * Created by ldf on 17/6/14.
13 | */
14 |
15 | public class ExampleAdapter extends RecyclerView.Adapter {
16 |
17 | private final LayoutInflater layoutInflater;
18 | private final Context context;
19 | private String[] titles;
20 |
21 | public ExampleAdapter(Context context) {
22 | titles = context.getResources().getStringArray(R.array.titles);
23 | this.context = context;
24 | layoutInflater = LayoutInflater.from(context);
25 | }
26 |
27 | @Override
28 | public ExampleAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
29 | return new ViewHolder(layoutInflater.inflate(R.layout.item, parent, false));
30 | }
31 |
32 | @Override
33 | public void onBindViewHolder(ViewHolder holder, int position) {
34 | holder.textView.setText(titles[position]);
35 | }
36 |
37 | @Override
38 | public int getItemCount() {
39 | return titles == null ? 0 : titles.length;
40 | }
41 |
42 | public static class ViewHolder extends RecyclerView.ViewHolder {
43 | TextView textView;
44 |
45 | ViewHolder(View view) {
46 | super(view);
47 | textView = (TextView) view.findViewById(R.id.text_view);
48 | view.setOnClickListener(new View.OnClickListener() {
49 | @Override
50 | public void onClick(View v) {
51 | Log.d("ViewHolder", "onClick--> position = " + getPosition());
52 | }
53 | });
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/example/src/main/java/com/hqyxjy/ldf/supercalendar/SyllabusActivity.java:
--------------------------------------------------------------------------------
1 | package com.hqyxjy.ldf.supercalendar;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.os.Bundle;
6 | import android.support.annotation.Nullable;
7 | import android.support.design.widget.CoordinatorLayout;
8 | import android.support.v4.view.ViewPager;
9 | import android.support.v7.app.AppCompatActivity;
10 | import android.support.v7.widget.LinearLayoutManager;
11 | import android.support.v7.widget.RecyclerView;
12 | import android.util.Log;
13 | import android.view.View;
14 | import android.widget.Button;
15 | import android.widget.TextView;
16 | import android.widget.Toast;
17 |
18 | import com.ldf.calendar.Utils;
19 | import com.ldf.calendar.component.CalendarAttr;
20 | import com.ldf.calendar.view.MonthPager;
21 | import com.ldf.calendar.interf.OnSelectDateListener;
22 | import com.ldf.calendar.component.CalendarViewAdapter;
23 | import com.ldf.calendar.model.CalendarDate;
24 | import com.ldf.calendar.view.Calendar;
25 |
26 | import java.text.SimpleDateFormat;
27 | import java.util.ArrayList;
28 | import java.util.Date;
29 | import java.util.HashMap;
30 |
31 | /**
32 | * Created by ldf on 16/11/4.
33 | */
34 |
35 | @SuppressLint("SetTextI18n")
36 | public class SyllabusActivity extends AppCompatActivity implements View.OnClickListener {
37 | TextView tvYear;
38 | TextView tvMonth;
39 | TextView backToday;
40 | CoordinatorLayout content;
41 | MonthPager monthPager;
42 | RecyclerView rvToDoList;
43 | TextView scrollSwitch;
44 | TextView themeSwitch;
45 | TextView nextMonthBtn;
46 | TextView lastMonthBtn;
47 | Button mark;
48 | CustomDayView customDayView;
49 | private ArrayList currentCalendars = new ArrayList<>();
50 | private CalendarViewAdapter calendarAdapter;
51 | private OnSelectDateListener onSelectDateListener;
52 | private int mCurrentPage = MonthPager.CURRENT_DAY_INDEX;
53 | private Context context;
54 | private CalendarDate currentDate;
55 | private boolean initiated = false;
56 |
57 | @Override
58 | protected void onCreate(@Nullable Bundle savedInstanceState) {
59 | super.onCreate(savedInstanceState);
60 | setContentView(R.layout.activity_syllabus);
61 | context = this;
62 | content = (CoordinatorLayout) findViewById(R.id.content);
63 | monthPager = (MonthPager) findViewById(R.id.calendar_view);
64 | //此处强行setViewHeight,毕竟你知道你的日历牌的高度
65 | monthPager.setViewHeight(Utils.dpi2px(context, 270));
66 | tvYear = (TextView) findViewById(R.id.show_year_view);
67 | tvMonth = (TextView) findViewById(R.id.show_month_view);
68 | backToday = (TextView) findViewById(R.id.back_today_button);
69 | scrollSwitch = (TextView) findViewById(R.id.scroll_switch);
70 | themeSwitch = (TextView) findViewById(R.id.theme_switch);
71 | nextMonthBtn = (TextView) findViewById(R.id.next_month);
72 | lastMonthBtn = (TextView) findViewById(R.id.last_month);
73 | rvToDoList = (RecyclerView) findViewById(R.id.list);
74 | mark=findViewById(R.id.marks);
75 | mark.setOnClickListener(this);
76 | rvToDoList.setHasFixedSize(true);
77 | //这里用线性显示 类似于listview
78 | rvToDoList.setLayoutManager(new LinearLayoutManager(this));
79 | rvToDoList.setAdapter(new ExampleAdapter(this));
80 | initCurrentDate();
81 | initCalendarView();
82 | initToolbarClickListener();
83 | Log.e("ldf","OnCreated");
84 | }
85 |
86 | /**
87 | * onWindowFocusChanged回调时,将当前月的种子日期修改为今天
88 | *
89 | * @return void
90 | */
91 | @Override
92 | public void onWindowFocusChanged(boolean hasFocus) {
93 | super.onWindowFocusChanged(hasFocus);
94 | if (hasFocus && !initiated) {
95 | refreshMonthPager();
96 | initiated = true;
97 | }
98 | }
99 |
100 | /*
101 | * 如果你想以周模式启动你的日历,请在onResume是调用
102 | * Utils.scrollTo(content, rvToDoList, monthPager.getCellHeight(), 200);
103 | * calendarAdapter.switchToWeek(monthPager.getRowIndex());
104 | * */
105 | @Override
106 | protected void onResume() {
107 | super.onResume();
108 | }
109 |
110 | /**
111 | * 初始化对应功能的listener
112 | *
113 | * @return void
114 | */
115 | private void initToolbarClickListener() {
116 | backToday.setOnClickListener(new View.OnClickListener() {
117 | @Override
118 | public void onClick(View view) {
119 | onClickBackToDayBtn();
120 | }
121 | });
122 | scrollSwitch.setOnClickListener(new View.OnClickListener() {
123 | @Override
124 | public void onClick(View view) {
125 | if (calendarAdapter.getCalendarType() == CalendarAttr.CalendarType.WEEK) {
126 | Utils.scrollTo(content, rvToDoList, monthPager.getViewHeight(), 200);
127 | calendarAdapter.switchToMonth();
128 | } else {
129 | Utils.scrollTo(content, rvToDoList, monthPager.getCellHeight(), 200);
130 | calendarAdapter.switchToWeek(monthPager.getRowIndex());
131 | }
132 | }
133 | });
134 | themeSwitch.setOnClickListener(new View.OnClickListener() {
135 | @Override
136 | public void onClick(View view) {
137 | refreshSelectBackground();
138 | }
139 | });
140 | nextMonthBtn.setOnClickListener(new View.OnClickListener() {
141 | @Override
142 | public void onClick(View view) {
143 | monthPager.setCurrentItem(monthPager.getCurrentPosition() + 1);
144 | }
145 | });
146 | lastMonthBtn.setOnClickListener(new View.OnClickListener() {
147 | @Override
148 | public void onClick(View view) {
149 | monthPager.setCurrentItem(monthPager.getCurrentPosition() - 1);
150 | }
151 | });
152 | }
153 |
154 | /**
155 | * 初始化currentDate
156 | *
157 | * @return void
158 | */
159 | private void initCurrentDate() {
160 | currentDate = new CalendarDate();
161 | tvYear.setText(currentDate.getYear() + "年");
162 | tvMonth.setText(currentDate.getMonth() + "");
163 | }
164 |
165 | /**
166 | * 初始化CustomDayView,并作为CalendarViewAdapter的参数传入
167 | */
168 | private void initCalendarView() {
169 | initListener();
170 | CustomDayView customDayView = new CustomDayView(context, R.layout.custom_day);
171 | calendarAdapter = new CalendarViewAdapter(
172 | context,
173 | onSelectDateListener,
174 | CalendarAttr.WeekArrayType.Monday,
175 | customDayView);
176 | calendarAdapter.setOnCalendarTypeChangedListener(new CalendarViewAdapter.OnCalendarTypeChanged() {
177 | @Override
178 | public void onCalendarTypeChanged(CalendarAttr.CalendarType type) {
179 | rvToDoList.scrollToPosition(0);
180 | }
181 | });
182 | initMarkData();
183 | initMonthPager();
184 | }
185 | public static String getDate(Long time){
186 | String ret = null;
187 | SimpleDateFormat format = new SimpleDateFormat("y-M-d");
188 | ret = format.format(new Date(time));
189 | return ret;
190 | }
191 | /**
192 | * 初始化标记数据,HashMap的形式,可自定义
193 | * 如果存在异步的话,在使用setMarkData之后调用 calendarAdapter.notifyDataChanged();
194 | */
195 | private void initMarkData() {
196 | HashMap markData = new HashMap<>();
197 | markData.put("2019-4-2", "0");
198 | markData.put("2019-4-1", "0");
199 | markData.put("2019-4-20", "0");
200 | markData.put("2019-4-30", "0");
201 | markData.put("2019-5-25", "0");
202 | markData.put("2019-5-28", "0");
203 | markData.put("2019-3-25", "0");
204 | markData.put("2019-3-24", "0");
205 | calendarAdapter.setMarkData(markData);
206 | calendarAdapter.notifyDataChanged();
207 | }
208 |
209 | private void initListener() {
210 | onSelectDateListener = new OnSelectDateListener() {
211 | @Override
212 | public void onSelectDate(CalendarDate date) {
213 | refreshClickDate(date);
214 | }
215 |
216 | @Override
217 | public void onSelectOtherMonth(int offset) {
218 | //偏移量 -1表示刷新成上一个月数据 , 1表示刷新成下一个月数据
219 | monthPager.selectOtherMonth(offset);
220 | }
221 | };
222 | }
223 |
224 |
225 | private void refreshClickDate(CalendarDate date) {
226 | currentDate = date;
227 | tvYear.setText(date.getYear() + "年");
228 | tvMonth.setText(date.getMonth() + "");
229 | }
230 |
231 | /**
232 | * 初始化monthPager,MonthPager继承自ViewPager
233 | *
234 | * @return void
235 | */
236 | private void initMonthPager() {
237 | monthPager.setAdapter(calendarAdapter);
238 | monthPager.setCurrentItem(MonthPager.CURRENT_DAY_INDEX);
239 | monthPager.setPageTransformer(false, new ViewPager.PageTransformer() {
240 | @Override
241 | public void transformPage(View page, float position) {
242 | position = (float) Math.sqrt(1 - Math.abs(position));
243 | page.setAlpha(position);
244 | }
245 | });
246 | monthPager.addOnPageChangeListener(new MonthPager.OnPageChangeListener() {
247 | @Override
248 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
249 | }
250 |
251 | @Override
252 | public void onPageSelected(int position) {
253 | Log.d("SSSSSSs", "onPageSelected: "+position);
254 | mCurrentPage = position;
255 | currentCalendars = calendarAdapter.getPagers();
256 | if (currentCalendars.get(position % currentCalendars.size()) != null) {
257 | CalendarDate date = currentCalendars.get(position % currentCalendars.size()).getSeedDate();
258 | currentDate = date;
259 | tvYear.setText(date.getYear() + "年");
260 | tvMonth.setText(date.getMonth() + "");
261 | }
262 | }
263 |
264 | @Override
265 | public void onPageScrollStateChanged(int state) {
266 | }
267 | });
268 | }
269 |
270 | public void onClickBackToDayBtn() {
271 | refreshMonthPager();
272 | }
273 |
274 | private void refreshMonthPager() {
275 | CalendarDate today = new CalendarDate();
276 | calendarAdapter.notifyDataChanged(today);
277 | tvYear.setText(today.getYear() + "年");
278 | tvMonth.setText(today.getMonth() + "");
279 | }
280 |
281 | private void refreshSelectBackground() {
282 | ThemeDayView themeDayView = new ThemeDayView(context, R.layout.custom_day_focus);
283 | calendarAdapter.setCustomDayRenderer(themeDayView);
284 | calendarAdapter.notifyDataSetChanged();
285 | calendarAdapter.notifyDataChanged(new CalendarDate());
286 | }
287 |
288 | @Override
289 | public void onClick(View v) {
290 | initMarkData();
291 | }
292 | }
293 |
294 |
--------------------------------------------------------------------------------
/example/src/main/java/com/hqyxjy/ldf/supercalendar/ThemeDayView.java:
--------------------------------------------------------------------------------
1 | package com.hqyxjy.ldf.supercalendar;
2 |
3 | import android.content.Context;
4 | import android.view.View;
5 | import android.widget.ImageView;
6 | import android.widget.TextView;
7 |
8 | import com.ldf.calendar.component.State;
9 | import com.ldf.calendar.interf.IDayRenderer;
10 | import com.ldf.calendar.model.CalendarDate;
11 | import com.ldf.calendar.view.DayView;
12 |
13 | /**
14 | * Created by ldf on 17/6/27.
15 | */
16 |
17 | public class ThemeDayView extends DayView {
18 | private TextView dateTv;
19 | private ImageView marker;
20 | private View selectedBackground;
21 | private View todayBackground;
22 | private final CalendarDate today = new CalendarDate();
23 |
24 | /**
25 | * Constructor. Sets up the MarkerView with a custom layout resource.
26 | *
27 | * @param context
28 | * @param layoutResource the layout resource to use for the MarkerView
29 | */
30 | public ThemeDayView(Context context, int layoutResource) {
31 | super(context, layoutResource);
32 | dateTv = (TextView) findViewById(R.id.date);
33 | marker = (ImageView) findViewById(R.id.maker);
34 | selectedBackground = findViewById(R.id.selected_background);
35 | todayBackground = findViewById(R.id.today_background);
36 | }
37 |
38 | @Override
39 | public void refreshContent() {
40 | CalendarDate date = day.getDate();
41 | State state = day.getState();
42 | if (date != null) {
43 | if (state!=null){
44 | if (date.equals(today)) {
45 | dateTv.setText("今");
46 | todayBackground.setVisibility(VISIBLE);
47 | } else {
48 | dateTv.setText(date.day + "");
49 | todayBackground.setVisibility(GONE);
50 | }
51 | }else {
52 | dateTv.setText("");
53 | todayBackground.setVisibility(GONE);
54 | }
55 | }
56 | if (state == State.SELECT) {
57 | selectedBackground.setVisibility(VISIBLE);
58 | } else {
59 | selectedBackground.setVisibility(GONE);
60 | }
61 | super.refreshContent();
62 | }
63 |
64 | @Override
65 | public IDayRenderer copy() {
66 | return new ThemeDayView(context, layoutResource);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/example/src/main/res/drawable-xxhdpi/select_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImVeryGood/SuperCalendar-master/1f9bbb256da25587f0cf2a558f0e438e0fb4744a/example/src/main/res/drawable-xxhdpi/select_background.png
--------------------------------------------------------------------------------
/example/src/main/res/drawable/background_white_3dp_corner.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/example/src/main/res/drawable/button_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/example/src/main/res/drawable/selected_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
9 |
--------------------------------------------------------------------------------
/example/src/main/res/drawable/selected_background_custom.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
9 |
--------------------------------------------------------------------------------
/example/src/main/res/drawable/today_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
12 |
--------------------------------------------------------------------------------
/example/src/main/res/drawable/view_syllabus_active_mark_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
9 |
--------------------------------------------------------------------------------
/example/src/main/res/drawable/view_syllabus_mark_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
--------------------------------------------------------------------------------
/example/src/main/res/drawable/view_syllabus_unactive_mark_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
9 |
--------------------------------------------------------------------------------
/example/src/main/res/layout/activity_syllabus.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
16 |
23 |
24 |
30 |
39 |
48 |
56 |
57 |
58 |
64 |
78 |
79 |
93 |
94 |
108 |
122 |
136 |
137 |
138 |
143 |
146 |
149 |
152 |
155 |
158 |
161 |
164 |
165 |
166 |
171 |
172 |
177 |
178 |
179 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
--------------------------------------------------------------------------------
/example/src/main/res/layout/custom_day.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
20 |
21 |
28 |
29 |
35 |
36 |
37 |
46 |
--------------------------------------------------------------------------------
/example/src/main/res/layout/custom_day_focus.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
13 |
20 |
26 |
33 |
--------------------------------------------------------------------------------
/example/src/main/res/layout/item.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
19 |
--------------------------------------------------------------------------------
/example/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImVeryGood/SuperCalendar-master/1f9bbb256da25587f0cf2a558f0e438e0fb4744a/example/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImVeryGood/SuperCalendar-master/1f9bbb256da25587f0cf2a558f0e438e0fb4744a/example/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImVeryGood/SuperCalendar-master/1f9bbb256da25587f0cf2a558f0e438e0fb4744a/example/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImVeryGood/SuperCalendar-master/1f9bbb256da25587f0cf2a558f0e438e0fb4744a/example/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImVeryGood/SuperCalendar-master/1f9bbb256da25587f0cf2a558f0e438e0fb4744a/example/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImVeryGood/SuperCalendar-master/1f9bbb256da25587f0cf2a558f0e438e0fb4744a/example/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImVeryGood/SuperCalendar-master/1f9bbb256da25587f0cf2a558f0e438e0fb4744a/example/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImVeryGood/SuperCalendar-master/1f9bbb256da25587f0cf2a558f0e438e0fb4744a/example/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImVeryGood/SuperCalendar-master/1f9bbb256da25587f0cf2a558f0e438e0fb4744a/example/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImVeryGood/SuperCalendar-master/1f9bbb256da25587f0cf2a558f0e438e0fb4744a/example/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/src/main/res/values/array.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - Android
5 | - IOS
6 | - JAVA
7 | - C++
8 | - Ruby
9 | - WEB
10 | - HTML
11 | - PERL
12 | - C
13 | - SWIFT
14 | - Python
15 | - C
16 | - C#
17 | - JS
18 |
19 |
20 |
21 | - Normal List
22 | - Normal Grid
23 | - Normal Staggered
24 | - Multiple List
25 | - Multiple Grid
26 | - Header Bottom List
27 | - Header Bottom Grid
28 | - Anim List
29 | - Anim Grid
30 | - Expended List
31 | - Expended Grid
32 | - Single Select
33 | - Multiple Select
34 |
35 |
--------------------------------------------------------------------------------
/example/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #677df7
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/example/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | SuperCalendar
3 |
4 |
--------------------------------------------------------------------------------
/example/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/example/src/test/java/com/hqyxjy/ldf/supercalendar/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.hqyxjy.ldf.supercalendar;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImVeryGood/SuperCalendar-master/1f9bbb256da25587f0cf2a558f0e438e0fb4744a/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Dec 19 11:23:56 CST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/raw/examples.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ImVeryGood/SuperCalendar-master/1f9bbb256da25587f0cf2a558f0e438e0fb4744a/raw/examples.gif
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':example', ':calendar'
2 |
--------------------------------------------------------------------------------