├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml ├── scopes │ └── scope_settings.xml └── vcs.xml ├── BG.jpg ├── DatePicker.iml ├── DatePicker ├── .gitignore ├── DatePicker-DatePicker.iml ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── cn │ └── aigestudio │ └── datepicker │ ├── bizs │ ├── calendars │ │ ├── DPCManager.java │ │ ├── DPCNCalendar.java │ │ ├── DPCalendar.java │ │ ├── DPUSCalendar.java │ │ └── SolarTerm.java │ ├── decors │ │ └── DPDecor.java │ ├── languages │ │ ├── CN.java │ │ ├── DPLManager.java │ │ └── EN.java │ └── themes │ │ ├── DPBaseTheme.java │ │ ├── DPCNTheme.java │ │ ├── DPTManager.java │ │ └── DPTheme.java │ ├── cons │ └── DPMode.java │ ├── entities │ └── DPInfo.java │ ├── utils │ ├── DataUtils.java │ └── MeasureUtil.java │ └── views │ ├── DatePicker.java │ └── MonthView.java ├── Decor.jpg ├── DecorExample.jpg ├── Demo ├── .gitignore ├── Demo.iml ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── cn │ │ └── aigestudio │ │ └── datepicker │ │ └── demo │ │ └── MainActivity.java │ └── res │ ├── drawable-hdpi │ └── ic_launcher.png │ ├── drawable-mdpi │ └── ic_launcher.png │ ├── drawable-xhdpi │ └── ic_launcher.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ ├── drawable-xxxhdpi │ └── ic_launcher.png │ ├── layout │ └── activity_main.xml │ └── values │ ├── strings.xml │ └── styles.xml ├── LICENSE ├── PreviewGif.gif ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | .DS_Store 6 | /build 7 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | DatePicker -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 25 | 26 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | Groovy 39 | 40 | 41 | Numeric issues 42 | 43 | 44 | Threading issues 45 | 46 | 47 | Threading issuesGroovy 48 | 49 | 50 | 51 | 52 | Abstraction issues 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 74 | 75 | C:\Users\987654\AppData\Roaming\Subversion 76 | 77 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/scopes/scope_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /BG.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devaige/DatePicker/7a4153d2cb17d20c31c6aa83b989f37d4c724bec/BG.jpg -------------------------------------------------------------------------------- /DatePicker.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /DatePicker/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /DatePicker/DatePicker-DatePicker.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /DatePicker/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | version = "2.2.0" 4 | 5 | android { 6 | compileSdkVersion 23 7 | buildToolsVersion "23.0.1" 8 | resourcePrefix "aigestudio_datepicker" 9 | 10 | defaultConfig { 11 | minSdkVersion 1 12 | targetSdkVersion 23 13 | versionCode 9 14 | versionName version 15 | } 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /DatePicker/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 e:/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 | -------------------------------------------------------------------------------- /DatePicker/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /DatePicker/src/main/java/cn/aigestudio/datepicker/bizs/calendars/DPCManager.java: -------------------------------------------------------------------------------- 1 | package cn.aigestudio.datepicker.bizs.calendars; 2 | 3 | import android.text.TextUtils; 4 | 5 | import java.util.HashMap; 6 | import java.util.HashSet; 7 | import java.util.List; 8 | import java.util.Locale; 9 | import java.util.Set; 10 | import java.util.concurrent.ConcurrentHashMap; 11 | 12 | import cn.aigestudio.datepicker.entities.DPInfo; 13 | import cn.aigestudio.datepicker.views.DatePicker; 14 | 15 | /** 16 | * 日期管理器 17 | * The manager of date picker. 18 | * 19 | * @author AigeStudio 2015-06-12 20 | */ 21 | public final class DPCManager { 22 | private static final HashMap> DATE_CACHE = new HashMap<>(); 23 | 24 | private static final HashMap> DECOR_CACHE_BG = new HashMap<>(); 25 | private static final HashMap> DECOR_CACHE_TL = new HashMap<>(); 26 | private static final HashMap> DECOR_CACHE_T = new HashMap<>(); 27 | private static final HashMap> DECOR_CACHE_TR = new HashMap<>(); 28 | private static final HashMap> DECOR_CACHE_L = new HashMap<>(); 29 | private static final HashMap> DECOR_CACHE_R = new HashMap<>(); 30 | 31 | private static DPCManager sManager; 32 | 33 | private DPCalendar c; 34 | 35 | private DPCManager() { 36 | // 默认显示为中文日历 37 | String locale = Locale.getDefault().getCountry().toLowerCase(); 38 | if (locale.equals("cn")) { 39 | initCalendar(new DPCNCalendar()); 40 | } else { 41 | initCalendar(new DPUSCalendar()); 42 | } 43 | } 44 | 45 | /** 46 | * 获取月历管理器 47 | * Get calendar manager 48 | * 49 | * @return 月历管理器 50 | */ 51 | public static DPCManager getInstance() { 52 | if (null == sManager) { 53 | sManager = new DPCManager(); 54 | } 55 | return sManager; 56 | } 57 | 58 | /** 59 | * 初始化日历对象 60 | *

61 | * Initialization Calendar 62 | * 63 | * @param c ... 64 | */ 65 | public void initCalendar(DPCalendar c) { 66 | this.c = c; 67 | } 68 | 69 | /** 70 | * 设置有背景标识物的日期 71 | *

72 | * Set date which has decor of background 73 | * 74 | * @param date 日期列表 List of date 75 | */ 76 | public void setDecorBG(List date) { 77 | setDecor(date, DECOR_CACHE_BG); 78 | } 79 | 80 | /** 81 | * 设置左上角有标识物的日期 82 | *

83 | * Set date which has decor on Top left 84 | * 85 | * @param date 日期列表 List of date 86 | */ 87 | public void setDecorTL(List date) { 88 | setDecor(date, DECOR_CACHE_TL); 89 | } 90 | 91 | /** 92 | * 设置顶部有标识物的日期 93 | *

94 | * Set date which has decor on Top 95 | * 96 | * @param date 日期列表 List of date 97 | */ 98 | public void setDecorT(List date) { 99 | setDecor(date, DECOR_CACHE_T); 100 | } 101 | 102 | /** 103 | * 设置右上角有标识物的日期 104 | *

105 | * Set date which has decor on Top right 106 | * 107 | * @param date 日期列表 List of date 108 | */ 109 | public void setDecorTR(List date) { 110 | setDecor(date, DECOR_CACHE_TR); 111 | } 112 | 113 | /** 114 | * 设置左边有标识物的日期 115 | *

116 | * Set date which has decor on left 117 | * 118 | * @param date 日期列表 List of date 119 | */ 120 | public void setDecorL(List date) { 121 | setDecor(date, DECOR_CACHE_L); 122 | } 123 | 124 | /** 125 | * 设置右上角有标识物的日期 126 | *

127 | * Set date which has decor on right 128 | * 129 | * @param date 日期列表 List of date 130 | */ 131 | public void setDecorR(List date) { 132 | setDecor(date, DECOR_CACHE_R); 133 | } 134 | 135 | /** 136 | * 获取指定年月的日历对象数组 137 | * 138 | * @param year 公历年 139 | * @param month 公历月 140 | * @return 日历对象数组 该数组长度恒为6x7 如果某个下标对应无数据则填充为null 141 | */ 142 | public DPInfo[][] obtainDPInfo(int year, int month) { 143 | HashMap dataOfYear = DATE_CACHE.get(year); 144 | if (null != dataOfYear && dataOfYear.size() != 0) { 145 | DPInfo[][] dataOfMonth = dataOfYear.get(month); 146 | if (dataOfMonth != null) { 147 | return dataOfMonth; 148 | } 149 | dataOfMonth = buildDPInfo(year, month); 150 | dataOfYear.put(month, dataOfMonth); 151 | return dataOfMonth; 152 | } 153 | if (null == dataOfYear) dataOfYear = new HashMap<>(); 154 | DPInfo[][] dataOfMonth = buildDPInfo(year, month); 155 | dataOfYear.put((month), dataOfMonth); 156 | DATE_CACHE.put(year, dataOfYear); 157 | return dataOfMonth; 158 | } 159 | 160 | private void setDecor(List date, HashMap> cache) { 161 | for (String str : date) { 162 | int index = str.lastIndexOf("-"); 163 | String key = str.substring(0, index).replace("-", ":"); 164 | Set days = cache.get(key); 165 | if (null == days) { 166 | days = new HashSet<>(); 167 | } 168 | days.add(str.substring(index + 1, str.length())); 169 | cache.put(key, days); 170 | } 171 | } 172 | 173 | private DPInfo[][] buildDPInfo(int year, int month) { 174 | DPInfo[][] info = new DPInfo[6][7]; 175 | 176 | String[][] strG = c.buildMonthG(year, month); 177 | String[][] strF = c.buildMonthFestival(year, month); 178 | 179 | Set strHoliday = c.buildMonthHoliday(year, month); 180 | Set strWeekend = c.buildMonthWeekend(year, month); 181 | 182 | Set decorBG = DECOR_CACHE_BG.get(year + ":" + month); 183 | Set decorTL = DECOR_CACHE_TL.get(year + ":" + month); 184 | Set decorT = DECOR_CACHE_T.get(year + ":" + month); 185 | Set decorTR = DECOR_CACHE_TR.get(year + ":" + month); 186 | Set decorL = DECOR_CACHE_L.get(year + ":" + month); 187 | Set decorR = DECOR_CACHE_R.get(year + ":" + month); 188 | for (int i = 0; i < info.length; i++) { 189 | for (int j = 0; j < info[i].length; j++) { 190 | DPInfo tmp = new DPInfo(); 191 | tmp.strG = strG[i][j]; 192 | if (c instanceof DPCNCalendar) { 193 | tmp.strF = strF[i][j].replace("F", ""); 194 | } else { 195 | tmp.strF = strF[i][j]; 196 | } 197 | if (!TextUtils.isEmpty(tmp.strG) && strHoliday.contains(tmp.strG)) 198 | tmp.isHoliday = true; 199 | if (!TextUtils.isEmpty(tmp.strG)) tmp.isToday = 200 | c.isToday(year, month, Integer.valueOf(tmp.strG)); 201 | if (strWeekend.contains(tmp.strG)) tmp.isWeekend = true; 202 | if (c instanceof DPCNCalendar) { 203 | if (!TextUtils.isEmpty(tmp.strG)) tmp.isSolarTerms = 204 | ((DPCNCalendar) c).isSolarTerm(year, month, Integer.valueOf(tmp.strG)); 205 | if (!TextUtils.isEmpty(strF[i][j]) && strF[i][j].endsWith("F")) 206 | tmp.isFestival = true; 207 | if (!TextUtils.isEmpty(tmp.strG)) 208 | tmp.isDeferred = ((DPCNCalendar) c) 209 | .isDeferred(year, month, Integer.valueOf(tmp.strG)); 210 | } else { 211 | tmp.isFestival = !TextUtils.isEmpty(strF[i][j]); 212 | } 213 | if (null != decorBG && decorBG.contains(tmp.strG)) tmp.isDecorBG = true; 214 | if (null != decorTL && decorTL.contains(tmp.strG)) tmp.isDecorTL = true; 215 | if (null != decorT && decorT.contains(tmp.strG)) tmp.isDecorT = true; 216 | if (null != decorTR && decorTR.contains(tmp.strG)) tmp.isDecorTR = true; 217 | if (null != decorL && decorL.contains(tmp.strG)) tmp.isDecorL = true; 218 | if (null != decorR && decorR.contains(tmp.strG)) tmp.isDecorR = true; 219 | info[i][j] = tmp; 220 | } 221 | } 222 | return info; 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /DatePicker/src/main/java/cn/aigestudio/datepicker/bizs/calendars/DPCNCalendar.java: -------------------------------------------------------------------------------- 1 | package cn.aigestudio.datepicker.bizs.calendars; 2 | 3 | import android.text.TextUtils; 4 | 5 | import java.util.Collections; 6 | import java.util.HashMap; 7 | import java.util.HashSet; 8 | import java.util.Set; 9 | 10 | /** 11 | * 中国月历 12 | * 13 | * Calendar of China 14 | * 15 | * @author AigeStudio 2015-06-16 16 | */ 17 | public class DPCNCalendar extends DPCalendar { 18 | private static final int[] FIRST_DAY_OF_LUNAR_IN_GREGORIAN = {1897, 0x75aa, 0x156a, 0x1096d, 0x95c, 0x14ae, 0xaa4d, 0x1a4c, 0x1b2a, 0x8d55, 0xad4, 0x135a, 0x495d, 0x95c, 0xd49b, 0x149a, 0x1a4a, 0xbaa5, 0x16a8, 0x1ad4, 0x52da, 0x12b6, 0xe937, 0x92e, 0x1496, 0xb64b, 0xd4a, 0xda8, 0x95b5, 0x56c, 0x12ae, 0x492f, 0x92e, 0xcc96, 0x1a94, 0x1d4a, 0xada9, 0xb5a, 0x56c, 0x726e, 0x125c, 0xf92d, 0x192a, 0x1a94, 0xdb4a, 0x16aa, 0xad4, 0x955b, 0x4ba, 0x125a, 0x592b, 0x152a, 0xf695, 0xd94, 0x16aa, 0xaab5, 0x9b4, 0x14b6, 0x6a57, 0xa56, 0x1152a, 0x1d2a, 0xd54, 0xd5aa, 0x156a, 0x96c, 0x94ae, 0x14ae, 0xa4c, 0x7d26, 0x1b2a, 0xeb55, 0xad4, 0x12da, 0xa95d, 0x95a, 0x149a, 0x9a4d, 0x1a4a, 0x11aa5, 0x16a8, 0x16d4, 0xd2da, 0x12b6, 0x936, 0x9497, 0x1496, 0x1564b, 0xd4a, 0xda8, 0xd5b4, 0x156c, 0x12ae, 0xa92f, 0x92e, 0xc96, 0x6d4a, 0x1d4a, 0x10d65, 0xb58, 0x156c, 0xb26d, 0x125c, 0x192c, 0x9a95, 0x1a94, 0x1b4a, 0x4b55, 0xad4, 0xf55b, 0x4ba, 0x125a, 0xb92b, 0x152a, 0x1694, 0x96aa, 0x15aa, 0x12ab5, 0x974, 0x14b6, 0xca57, 0xa56, 0x1526, 0x8e95, 0xd54, 0x15aa, 0x49b5, 0x96c, 0xd4ae, 0x149c, 0x1a4c, 0xbd26, 0x1aa6, 0xb54, 0x6d6a, 0x12da, 0x1695d, 0x95a, 0x149a, 0xda4b, 0x1a4a, 0x1aa4, 0xbb54, 0x16b4, 0xada, 0x495b, 0x936, 0xf497, 0x1496, 0x154a, 0xb6a5, 0xda4, 0x15b4, 0x6ab6, 0x126e, 0x1092f, 0x92e, 0xc96, 0xcd4a, 0x1d4a, 0xd64, 0x956c, 0x155c, 0x125c, 0x792e, 0x192c, 0xfa95, 0x1a94, 0x1b4a, 0xab55, 0xad4, 0x14da, 0x8a5d, 0xa5a, 0x1152b, 0x152a, 0x1694, 0xd6aa, 0x15aa, 0xab4, 0x94ba, 0x14b6, 0xa56, 0x7527, 0xd26, 0xee53, 0xd54, 0x15aa, 0xa9b5, 0x96c, 0x14ae, 0x8a4e, 0x1a4c, 0x11d26, 0x1aa4, 0x1b54, 0xcd6a, 0xada, 0x95c, 0x949d, 0x149a, 0x1a2a, 0x5b25, 0x1aa4, 0xfb52}; 19 | 20 | private static final int[] DAYS_AND_LEAP_MONTH_OF_LUNAR = {1897, 0xed436, 0xed64a, 0xed83f, 0xeda53, 0xedc48, 0xede3d, 0xee050, 0xee244, 0xee439, 0xee64d, 0xee842, 0xeea36, 0xeec4a, 0xeee3e, 0xef052, 0xef246, 0xef43a, 0xef64e, 0xef843, 0xefa37, 0xefc4b, 0xefe41, 0xf0054, 0xf0248, 0xf043c, 0xf0650, 0xf0845, 0xf0a38, 0xf0c4d, 0xf0e42, 0xf1037, 0xf124a, 0xf143e, 0xf1651, 0xf1846, 0xf1a3a, 0xf1c4e, 0xf1e44, 0xf2038, 0xf224b, 0xf243f, 0xf2653, 0xf2848, 0xf2a3b, 0xf2c4f, 0xf2e45, 0xf3039, 0xf324d, 0xf3442, 0xf3636, 0xf384a, 0xf3a3d, 0xf3c51, 0xf3e46, 0xf403b, 0xf424e, 0xf4443, 0xf4638, 0xf484c, 0xf4a3f, 0xf4c52, 0xf4e48, 0xf503c, 0xf524f, 0xf5445, 0xf5639, 0xf584d, 0xf5a42, 0xf5c35, 0xf5e49, 0xf603e, 0xf6251, 0xf6446, 0xf663b, 0xf684f, 0xf6a43, 0xf6c37, 0xf6e4b, 0xf703f, 0xf7252, 0xf7447, 0xf763c, 0xf7850, 0xf7a45, 0xf7c39, 0xf7e4d, 0xf8042, 0xf8254, 0xf8449, 0xf863d, 0xf8851, 0xf8a46, 0xf8c3b, 0xf8e4f, 0xf9044, 0xf9237, 0xf944a, 0xf963f, 0xf9853, 0xf9a47, 0xf9c3c, 0xf9e50, 0xfa045, 0xfa238, 0xfa44c, 0xfa641, 0xfa836, 0xfaa49, 0xfac3d, 0xfae52, 0xfb047, 0xfb23a, 0xfb44e, 0xfb643, 0xfb837, 0xfba4a, 0xfbc3f, 0xfbe53, 0xfc048, 0xfc23c, 0xfc450, 0xfc645, 0xfc839, 0xfca4c, 0xfcc41, 0xfce36, 0xfd04a, 0xfd23d, 0xfd451, 0xfd646, 0xfd83a, 0xfda4d, 0xfdc43, 0xfde37, 0xfe04b, 0xfe23f, 0xfe453, 0xfe648, 0xfe83c, 0xfea4f, 0xfec44, 0xfee38, 0xff04c, 0xff241, 0xff436, 0xff64a, 0xff83e, 0xffa51, 0xffc46, 0xffe3a, 0x10004e, 0x100242, 0x100437, 0x10064b, 0x100841, 0x100a53, 0x100c48, 0x100e3c, 0x10104f, 0x101244, 0x101438, 0x10164c, 0x101842, 0x101a35, 0x101c49, 0x101e3d, 0x102051, 0x102245, 0x10243a, 0x10264e, 0x102843, 0x102a37, 0x102c4b, 0x102e3f, 0x103053, 0x103247, 0x10343b, 0x10364f, 0x103845, 0x103a38, 0x103c4c, 0x103e42, 0x104036, 0x104249, 0x10443d, 0x104651, 0x104846, 0x104a3a, 0x104c4e, 0x104e43, 0x105038, 0x10524a, 0x10543e, 0x105652, 0x105847, 0x105a3b, 0x105c4f, 0x105e45, 0x106039, 0x10624c, 0x106441, 0x106635, 0x106849, 0x106a3d}; 21 | 22 | private static final String[] NUMBER_CAPITAL = {"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"}; 23 | 24 | private static final String[] LUNAR_HEADER = {"初", "十", "廿", "卅", "正", "腊", "冬", "闰"}; 25 | 26 | private static final String[][] FESTIVAL_G = { 27 | {"元旦"}, 28 | {"世界湿地日", "情人节"}, 29 | {"全国爱耳日", "青年志愿者服务日", "国际妇女节", "保护母亲河日", "中国植树节", "白色情人节&国际警察日", "世界消费者权益日", "世界森林日&世界睡眠日", "世界水日", "世界气象日", "世界防治结核病日"}, 30 | {"愚人节", "清明节", "世界卫生日", "世界地球日", "世界知识产权日"}, 31 | {"国际劳动节", "世界哮喘日", "中国青年节", "世界红十字日", "国际护士节", "国际家庭日", "世界电信日", "全国学生营养日", "国际生物多样性日", "国际牛奶日", "世界无烟日"}, 32 | {"国际儿童节", "世界环境日", "全国爱眼日", "世界防治荒漠化日", "国际奥林匹克日", "全国土地日", "国际禁毒日"}, 33 | {"中国共产党诞生日&国际建筑日", "中国抗战纪念日", "世界人口日"}, 34 | {"中国解放军建军节", "国际青年节"}, 35 | {"抗战胜利日", "国际扫盲日", "中国教师节", "中国脑健康日&臭氧层保护日", "全国爱牙日", "世界停火日", "世界旅游日"}, 36 | {"国庆节&国际老年人日", "世界动物日", "世界教师日", "全国高血压日", "世界邮政日", "世界精神卫生日", "世界标准日", "国际盲人节&世界农村妇女日", "世界粮食日", "国际消除贫困日", "联合国日&世界发展新闻日", "中国男性健康日", "万圣节"}, 37 | {"中国记者节", "消防宣传日", "世界糖尿病日", "国际大学生节", "消除对妇女暴力日"}, 38 | {"世界爱滋病日", "世界残疾人日", "全国法制宣传日", "世界足球日", "圣诞节"}}; 39 | 40 | private static final int[][] FESTIVAL_G_DATE = { 41 | {1}, 42 | {2, 14}, 43 | {3, 5, 8, 9, 12, 14, 15, 21, 22, 23, 24}, 44 | {1, 5, 7, 22, 26}, 45 | {1, 3, 4, 8, 12, 15, 17, 20, 22, 23, 31}, 46 | {1, 5, 6, 17, 23, 25, 26}, 47 | {1, 7, 11}, 48 | {1, 12}, 49 | {3, 8, 10, 16, 20, 21, 27}, 50 | {1, 4, 5, 8, 9, 10, 14, 15, 16, 17, 24, 29, 31}, 51 | {8, 9, 14, 17, 25}, 52 | {1, 3, 4, 9, 25}}; 53 | 54 | private static final String[][] FESTIVAL_L = {{"春节", "元宵节"}, 55 | {}, 56 | {}, 57 | {}, 58 | {"端午节"}, 59 | {}, 60 | {"乞巧节"}, 61 | {"中秋节"}, 62 | {"重阳节"}, 63 | {}, 64 | {}, 65 | {"腊八节", "扫房日"}}; 66 | 67 | private static final int[][] FESTIVAL_L_DATE = { 68 | {1, 15}, 69 | {}, 70 | {}, 71 | {}, 72 | {5}, 73 | {}, 74 | {7}, 75 | {15}, 76 | {9}, 77 | {}, 78 | {}, 79 | {8, 24}}; 80 | 81 | private static final String[][] HOLIDAY = {{"1", "2", "3"}, {"18", "19", "20", "21", "22", "23", "24"}, {""}, {"4", "5", "6"}, {"1", "2", "3"}, {"20", "21", "22"}, {""}, {""}, {"3", "4", "5", "26", "27"}, {"1", "2", "3", "4", "5", "6", "7"}, {""}, {""}}; 82 | 83 | private static final String[][] DEFERRED = {{"4"}, {"15", "16", "17", "25", "26", "27", "28"}, {""}, {""}, {""}, {""}, {""}, {""}, {"6", "28", "29", "30"}, {"8", "9", "10"}, {""}, {""}}; 84 | 85 | private static final String SOLAR_TERM[][] = {{"小寒", "大寒"}, {"立春", "雨水"}, {"惊蛰", "春分"}, {"清明", "谷雨"}, {"立夏", "小满"}, {"芒种", "夏至"}, {"小暑", "大暑"}, {"立秋", "处暑"}, {"白露", "秋分"}, {"寒露", "霜降"}, {"立冬", "小雪"}, {"大雪", "冬至"}}; 86 | 87 | private final HashMap CACHE_SOLAR_TERM = new HashMap<>(); 88 | 89 | private SolarTerm mSolarTerm = new SolarTerm(); 90 | 91 | private class G { 92 | int d; 93 | int m; 94 | int y; 95 | } 96 | 97 | private class L { 98 | int d; 99 | int m; 100 | int y; 101 | 102 | boolean isLeap; 103 | } 104 | 105 | @Override 106 | public String[][] buildMonthFestival(int year, int month) { 107 | return buildMonthL(year, month); 108 | } 109 | 110 | @Override 111 | public Set buildMonthHoliday(int year, int month) { 112 | Set tmp = new HashSet<>(); 113 | if (year == 2015) { 114 | Collections.addAll(tmp, HOLIDAY[month - 1]); 115 | } 116 | return tmp; 117 | } 118 | 119 | private String[][] buildMonthL(int year, int month) { 120 | String[][] gregorianMonth = buildMonthG(year, month); 121 | G g = new G(); 122 | String tmp[][] = new String[6][7]; 123 | for (int i = 0; i < tmp.length; i++) { 124 | for (int j = 0; j < tmp[0].length; j++) { 125 | tmp[i][j] = ""; 126 | if (!TextUtils.isEmpty(gregorianMonth[i][j])) { 127 | g.y = year; 128 | g.m = month; 129 | g.d = Integer.valueOf(gregorianMonth[i][j]); 130 | L l = null; 131 | String result = ""; 132 | if (year >= 1900 && year <= 2100) { 133 | l = GTL(g); 134 | result = getFestivalL(l.m, l.d); 135 | } 136 | if (TextUtils.isEmpty(result)) { 137 | result = getFestivalG(g.m, g.d); 138 | if (TextUtils.isEmpty(result)) { 139 | result = getSolarTerm(year, month, g.d); 140 | if (null != l && TextUtils.isEmpty(result)) { 141 | char[] c = String.valueOf(l.d).toCharArray(); 142 | tmp[i][j] = lNumToStr(c); 143 | } else { 144 | tmp[i][j] = result; 145 | } 146 | } else { 147 | tmp[i][j] = result + "F"; 148 | } 149 | } else { 150 | tmp[i][j] = result + "F"; 151 | } 152 | } 153 | } 154 | } 155 | return tmp; 156 | } 157 | 158 | /** 159 | * 判断某年某月某日是否为节气 160 | * 161 | * @param year 公历年 162 | * @param month 公历月 163 | * @param day 公历日 164 | * @return ... 165 | */ 166 | public boolean isSolarTerm(int year, int month, int day) { 167 | return null == getSolarTerm(year, month, day); 168 | } 169 | 170 | /** 171 | * 判断某月某日是否为补休 172 | * 173 | * @param year 公历年 174 | * @param month 公历月 175 | * @param day 公历日 176 | * @return ... 177 | */ 178 | public boolean isDeferred(int year, int month, int day) { 179 | if (year == 2015) { 180 | String[] deferredOfMonth = DEFERRED[month - 1]; 181 | for (String s : deferredOfMonth) { 182 | if (!TextUtils.isEmpty(s) && Integer.valueOf(s) == day) return true; 183 | } 184 | } 185 | return false; 186 | } 187 | 188 | private String getSolarTerm(int year, int month, int day) { 189 | String[][] tmp = CACHE_SOLAR_TERM.get(year); 190 | if (null == tmp) { 191 | tmp = mSolarTerm.buildSolarTerm(year); 192 | CACHE_SOLAR_TERM.put(year, tmp); 193 | } 194 | String[] STOfMonth = tmp[month - 1]; 195 | if (Integer.valueOf(STOfMonth[0]) == day) { 196 | return SOLAR_TERM[month - 1][0]; 197 | } else if (Integer.valueOf(STOfMonth[1]) == day) { 198 | return SOLAR_TERM[month - 1][1]; 199 | } 200 | return ""; 201 | } 202 | 203 | private String getFestivalL(int month, int day) { 204 | String tmp = ""; 205 | int[] daysInMonth = FESTIVAL_L_DATE[month - 1]; 206 | for (int i = 0; i < daysInMonth.length; i++) { 207 | if (day == daysInMonth[i]) { 208 | tmp = FESTIVAL_L[month - 1][i]; 209 | } 210 | } 211 | return tmp; 212 | } 213 | 214 | private String getFestivalG(int month, int day) { 215 | String tmp = ""; 216 | int[] daysInMonth = FESTIVAL_G_DATE[month - 1]; 217 | for (int i = 0; i < daysInMonth.length; i++) { 218 | if (day == daysInMonth[i]) { 219 | tmp = FESTIVAL_G[month - 1][i]; 220 | } 221 | } 222 | return tmp; 223 | } 224 | 225 | private L GTL(G g) { 226 | int index = g.y - DAYS_AND_LEAP_MONTH_OF_LUNAR[0]; 227 | int data = (g.y << 9) | (g.m << 5) | (g.d); 228 | int lunarFirstDayInGregorian; 229 | if (DAYS_AND_LEAP_MONTH_OF_LUNAR[index] > data) { 230 | index--; 231 | } 232 | lunarFirstDayInGregorian = DAYS_AND_LEAP_MONTH_OF_LUNAR[index]; 233 | 234 | int y = getBitInt(lunarFirstDayInGregorian, 12, 9); 235 | int m = getBitInt(lunarFirstDayInGregorian, 4, 5); 236 | int d = getBitInt(lunarFirstDayInGregorian, 5, 0); 237 | 238 | long offset = GToNum(g.y, g.m, g.d) - GToNum(y, m, d); 239 | int days = FIRST_DAY_OF_LUNAR_IN_GREGORIAN[index]; 240 | int leap = getBitInt(days, 4, 13); 241 | 242 | int lunarY = index + DAYS_AND_LEAP_MONTH_OF_LUNAR[0]; 243 | int lunarM = 1; 244 | int lunarD; 245 | offset += 1; 246 | 247 | for (int i = 0; i < 13; i++) { 248 | int dm = getBitInt(days, 1, 12 - i) == 1 ? 30 : 29; 249 | if (offset > dm) { 250 | lunarM++; 251 | offset -= dm; 252 | } else { 253 | break; 254 | } 255 | } 256 | lunarD = (int) (offset); 257 | L l = new L(); 258 | l.y = lunarY; 259 | l.m = lunarM; 260 | l.isLeap = false; 261 | if (leap != 0 && lunarM > leap) { 262 | l.m = lunarM - 1; 263 | if (lunarM == leap + 1) { 264 | l.isLeap = true; 265 | } 266 | } 267 | l.d = lunarD; 268 | return l; 269 | } 270 | 271 | private String lNumToStr(char[] c) { 272 | String result = ""; 273 | if (c.length == 1) { 274 | for (int i = 1; i < 10; i++) { 275 | if (c[0] == String.valueOf(i).charAt(0)) { 276 | result = LUNAR_HEADER[0] + NUMBER_CAPITAL[i]; 277 | } 278 | } 279 | } else { 280 | if (c[0] == '1') { 281 | if (c[1] == '0') { 282 | result = LUNAR_HEADER[0] + LUNAR_HEADER[1]; 283 | } else { 284 | for (int i = 1; i < 10; i++) { 285 | if (c[1] == String.valueOf(i).charAt(0)) { 286 | result = LUNAR_HEADER[1] + NUMBER_CAPITAL[i]; 287 | } 288 | } 289 | } 290 | } else if (c[0] == '2') { 291 | if (c[1] == '0') { 292 | result = LUNAR_HEADER[2] + LUNAR_HEADER[1]; 293 | } else { 294 | for (int i = 1; i < 10; i++) { 295 | if (c[1] == String.valueOf(i).charAt(0)) { 296 | result = LUNAR_HEADER[2] + NUMBER_CAPITAL[i]; 297 | } 298 | } 299 | } 300 | } else { 301 | if (c[1] == '0') { 302 | result = LUNAR_HEADER[3] + LUNAR_HEADER[1]; 303 | } else { 304 | for (int i = 1; i < 10; i++) { 305 | if (c[1] == String.valueOf(i).charAt(0)) { 306 | result = LUNAR_HEADER[3] + NUMBER_CAPITAL[i]; 307 | } 308 | } 309 | } 310 | } 311 | } 312 | return result; 313 | } 314 | } 315 | -------------------------------------------------------------------------------- /DatePicker/src/main/java/cn/aigestudio/datepicker/bizs/calendars/DPCalendar.java: -------------------------------------------------------------------------------- 1 | package cn.aigestudio.datepicker.bizs.calendars; 2 | 3 | import java.util.Calendar; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | 7 | /** 8 | * 月历抽象父类 9 | * 继承该类可以实现自己的日历对象 10 | *

11 | * Abstract class of Calendar 12 | * 13 | * @author AigeStudio 2015-06-15 14 | */ 15 | public abstract class DPCalendar { 16 | protected final Calendar c = Calendar.getInstance(); 17 | 18 | /** 19 | * 获取某年某月的节日数组 20 | *

21 | * Build the festival date array of given year and month 22 | * 23 | * @param year 某年 24 | * @param month 某月 25 | * @return 该月节日数组 26 | */ 27 | public abstract String[][] buildMonthFestival(int year, int month); 28 | 29 | /** 30 | * 获取某年某月的假期数组 31 | *

32 | * Build the holiday date array of given year and month 33 | * 34 | * @param year 某年 35 | * @param month 某月 36 | * @return 该月假期数组 37 | */ 38 | public abstract Set buildMonthHoliday(int year, int month); 39 | 40 | /** 41 | * 判断某年是否为闰年 42 | * 43 | * @param year ... 44 | * @return true表示闰年 45 | */ 46 | public boolean isLeapYear(int year) { 47 | return (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)); 48 | } 49 | 50 | /** 51 | * 判断给定日期是否为今天 52 | * 53 | * @param year 某年 54 | * @param month 某月 55 | * @param day 某天 56 | * @return ... 57 | */ 58 | public boolean isToday(int year, int month, int day) { 59 | Calendar c1 = Calendar.getInstance(); 60 | Calendar c2 = Calendar.getInstance(); 61 | c1.set(year, month - 1, day); 62 | return (c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR)) && 63 | (c1.get(Calendar.MONTH) == (c2.get(Calendar.MONTH))) && 64 | (c1.get(Calendar.DAY_OF_MONTH) == c2.get(Calendar.DAY_OF_MONTH)); 65 | } 66 | 67 | /** 68 | * 生成某年某月的公历天数数组 69 | * 数组为6x7的二维数组因为一个月的周数永远不会超过六周 70 | * 天数填充对应相应的二维数组下标 71 | * 如果某个数组下标中没有对应天数那么则填充一个空字符串 72 | * 73 | * @param year 某年 74 | * @param month 某月 75 | * @return 某年某月的公历天数数组 76 | */ 77 | public String[][] buildMonthG(int year, int month) { 78 | c.clear(); 79 | String tmp[][] = new String[6][7]; 80 | c.set(year, month - 1, 1); 81 | 82 | int daysInMonth = 0; 83 | if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || 84 | month == 12) { 85 | daysInMonth = 31; 86 | } else if (month == 4 || month == 6 || month == 9 || month == 11) { 87 | daysInMonth = 30; 88 | } else if (month == 2) { 89 | if (isLeapYear(year)) { 90 | daysInMonth = 29; 91 | } else { 92 | daysInMonth = 28; 93 | } 94 | } 95 | int dayOfWeek = c.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY; 96 | int day = 1; 97 | for (int i = 0; i < 6; i++) { 98 | for (int j = 0; j < 7; j++) { 99 | tmp[i][j] = ""; 100 | if (i == 0 && j >= dayOfWeek) { 101 | tmp[i][j] = "" + day; 102 | day++; 103 | } else if (i > 0 && day <= daysInMonth) { 104 | tmp[i][j] = "" + day; 105 | day++; 106 | } 107 | } 108 | } 109 | return tmp; 110 | } 111 | 112 | /** 113 | * 生成某年某月的周末日期集合 114 | * 115 | * @param year 某年 116 | * @param month 某月 117 | * @return 某年某月的周末日期集合 118 | */ 119 | public Set buildMonthWeekend(int year, int month) { 120 | Set set = new HashSet<>(); 121 | c.clear(); 122 | c.set(year, month - 1, 1); 123 | do { 124 | int day = c.get(Calendar.DAY_OF_WEEK); 125 | if (day == Calendar.SATURDAY || day == Calendar.SUNDAY) { 126 | set.add(String.valueOf(c.get(Calendar.DAY_OF_MONTH))); 127 | } 128 | c.add(Calendar.DAY_OF_YEAR, 1); 129 | } while (c.get(Calendar.MONTH) == month - 1); 130 | return set; 131 | } 132 | 133 | protected long GToNum(int year, int month, int day) { 134 | month = (month + 9) % 12; 135 | year = year - month / 10; 136 | return 365 * year + year / 4 - year / 100 + year / 400 + (month * 306 + 5) / 10 + (day - 1); 137 | } 138 | 139 | protected int getBitInt(int data, int length, int shift) { 140 | return (data & (((1 << length) - 1) << shift)) >> shift; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /DatePicker/src/main/java/cn/aigestudio/datepicker/bizs/calendars/DPUSCalendar.java: -------------------------------------------------------------------------------- 1 | package cn.aigestudio.datepicker.bizs.calendars; 2 | 3 | import android.text.TextUtils; 4 | 5 | import java.util.Collections; 6 | import java.util.HashSet; 7 | import java.util.Set; 8 | 9 | /** 10 | * 美国月历 11 | * 12 | * Calendar of America 13 | * 14 | * @author AigeStudio 2015-07-22 15 | */ 16 | public class DPUSCalendar extends DPCalendar { 17 | private static final String[][] FESTIVAL_G = { 18 | {"New Year"}, 19 | {"Lincoln's Birthday", "St.Valentine's Day", "Washington's Birthday"}, 20 | {"St.Patrick's Day"}, 21 | {"All Fools' Day"}, 22 | {}, 23 | {"Flag Day"}, 24 | {"Independence Day"}, 25 | {}, 26 | {}, 27 | {"Columbus Day"}, 28 | {"Halloween"}, 29 | {"Christmas"}}; 30 | 31 | private static final int[][] FESTIVAL_G_DATE = { 32 | {1}, 33 | {12, 14, 18}, 34 | {17}, 35 | {1}, 36 | {}, 37 | {14}, 38 | {4}, 39 | {}, 40 | {}, 41 | {12}, 42 | {1}, 43 | {25}}; 44 | private static final String[][] HOLIDAY = {{"1"}, {""}, {""}, {""}, {"24", "25", "26"}, {""}, {"4", "5", "6"}, {"30"}, {"1", "2"}, {""}, {"27", "28", "29", "30"}, {"25", "26", "27"}}; 45 | 46 | @Override 47 | public String[][] buildMonthFestival(int year, int month) { 48 | String[][] gregorianMonth = buildMonthG(year, month); 49 | String tmp[][] = new String[6][7]; 50 | for (int i = 0; i < tmp.length; i++) { 51 | for (int j = 0; j < tmp[0].length; j++) { 52 | tmp[i][j] = ""; 53 | String day = gregorianMonth[i][j]; 54 | if (!TextUtils.isEmpty(day)) { 55 | tmp[i][j] = getFestivalG(month, Integer.valueOf(day)); 56 | } 57 | } 58 | } 59 | return tmp; 60 | } 61 | 62 | @Override 63 | public Set buildMonthHoliday(int year, int month) { 64 | Set tmp = new HashSet<>(); 65 | if (year == 2015) { 66 | Collections.addAll(tmp, HOLIDAY[month - 1]); 67 | } 68 | return tmp; 69 | } 70 | 71 | private String getFestivalG(int month, int day) { 72 | String tmp = ""; 73 | int[] daysInMonth = FESTIVAL_G_DATE[month - 1]; 74 | for (int i = 0; i < daysInMonth.length; i++) { 75 | if (day == daysInMonth[i]) { 76 | tmp = FESTIVAL_G[month - 1][i]; 77 | } 78 | } 79 | return tmp; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /DatePicker/src/main/java/cn/aigestudio/datepicker/bizs/calendars/SolarTerm.java: -------------------------------------------------------------------------------- 1 | package cn.aigestudio.datepicker.bizs.calendars; 2 | 3 | import cn.aigestudio.datepicker.utils.DataUtils; 4 | 5 | /** 6 | * 农历二十四节气算法 7 | * 该算法目前仅对外提供一个接口方法获取某年的节气数据{@link #buildSolarTerm(int)} 8 | * 9 | * Algorithm of lunar solar term. 10 | * This algorithm provide a public method to get the all solar term of year.{@link #buildSolarTerm(int)} 11 | * 12 | * @author AigeStudio 2015-06-16 13 | */ 14 | final class SolarTerm { 15 | private static final double E10[] = {1.75347045673, 0.00000000000, 0.0000000000, 0.03341656456, 4.66925680417, 6283.0758499914, 0.00034894275, 4.62610241759, 12566.1516999828, 0.00003417571, 2.82886579606, 3.5231183490, 0.00003497056, 2.74411800971, 5753.3848848968, 0.00003135896, 3.62767041758, 77713.7714681205, 0.00002676218, 4.41808351397, 7860.4193924392, 0.00002342687, 6.13516237631, 3930.2096962196, 0.00001273166, 2.03709655772, 529.6909650946, 0.00001324292, 0.74246356352, 11506.7697697936, 0.00000901855, 2.04505443513, 26.2983197998, 0.00001199167, 1.10962944315, 1577.3435424478, 0.00000857223, 3.50849156957, 398.1490034082, 0.00000779786, 1.17882652114, 5223.6939198022, 0.00000990250, 5.23268129594, 5884.9268465832, 0.00000753141, 2.53339053818, 5507.5532386674, 0.00000505264, 4.58292563052, 18849.2275499742, 0.00000492379, 4.20506639861, 775.5226113240, 0.00000356655, 2.91954116867, 0.0673103028, 0.00000284125, 1.89869034186, 796.2980068164, 0.00000242810, 0.34481140906, 5486.7778431750, 0.00000317087, 5.84901952218, 11790.6290886588, 0.00000271039, 0.31488607649, 10977.0788046990, 0.00000206160, 4.80646606059, 2544.3144198834, 0.00000205385, 1.86947813692, 5573.1428014331, 0.00000202261, 2.45767795458, 6069.7767545534, 0.00000126184, 1.08302630210, 20.7753954924, 0.00000155516, 0.83306073807, 213.2990954380, 0.00000115132, 0.64544911683, 0.9803210682, 0.00000102851, 0.63599846727, 4694.0029547076, 0.00000101724, 4.26679821365, 7.1135470008, 0.00000099206, 6.20992940258, 2146.1654164752, 0.00000132212, 3.41118275555, 2942.4634232916, 0.00000097607, 0.68101272270, 155.4203994342, 0.00000085128, 1.29870743025, 6275.9623029906, 0.00000074651, 1.75508916159, 5088.6288397668, 0.00000101895, 0.97569221824, 15720.8387848784, 0.00000084711, 3.67080093025, 71430.6956181291, 0.00000073547, 4.67926565481, 801.8209311238, 0.00000073874, 3.50319443167, 3154.6870848956, 0.00000078756, 3.03698313141, 12036.4607348882, 0.00000079637, 1.80791330700, 17260.1546546904, 0.00000085803, 5.98322631256, 161000.6857376741, 0.00000056963, 2.78430398043, 6286.5989683404, 0.00000061148, 1.81839811024, 7084.8967811152, 0.00000069627, 0.83297596966, 9437.7629348870, 0.00000056116, 4.38694880779, 14143.4952424306, 0.00000062449, 3.97763880587, 8827.3902698748, 0.00000051145, 0.28306864501, 5856.4776591154, 0.00000055577, 3.47006009062, 6279.5527316424, 0.00000041036, 5.36817351402, 8429.2412664666, 0.00000051605, 1.33282746983, 1748.0164130670, 0.00000051992, 0.18914945834, 12139.5535091068, 0.00000049000, 0.48735065033, 1194.4470102246, 0.00000039200, 6.16832995016, 10447.3878396044, 0.00000035566, 1.77597314691, 6812.7668150860, 0.00000036770, 6.04133859347, 10213.2855462110, 0.00000036596, 2.56955238628, 1059.3819301892, 0.00000033291, 0.59309499459, 17789.8456197850, 0.00000035954, 1.70876111898, 2352.8661537718}; 16 | 17 | private static final double E11[] = {6283.31966747491, 0.00000000000, 0.0000000000, 0.00206058863, 2.67823455584, 6283.0758499914, 0.00004303430, 2.63512650414, 12566.1516999828, 0.00000425264, 1.59046980729, 3.5231183490, 0.00000108977, 2.96618001993, 1577.3435424478, 0.00000093478, 2.59212835365, 18849.2275499742, 0.00000119261, 5.79557487799, 26.2983197998, 0.00000072122, 1.13846158196, 529.6909650946, 0.00000067768, 1.87472304791, 398.1490034082, 0.00000067327, 4.40918235168, 5507.5532386674, 0.00000059027, 2.88797038460, 5223.6939198022, 0.00000055976, 2.17471680261, 155.4203994342, 0.00000045407, 0.39803079805, 796.2980068164, 0.00000036369, 0.46624739835, 775.5226113240, 0.00000028958, 2.64707383882, 7.1135470008, 0.00000019097, 1.84628332577, 5486.7778431750, 0.00000020844, 5.34138275149, 0.9803210682, 0.00000018508, 4.96855124577, 213.2990954380, 0.00000016233, 0.03216483047, 2544.3144198834, 0.00000017293, 2.99116864949, 6275.9623029906}; 18 | 19 | private static final double E12[] = {0.00052918870, 0.00000000000, 0.0000000000, 0.00008719837, 1.07209665242, 6283.0758499914, 0.00000309125, 0.86728818832, 12566.1516999828, 0.00000027339, 0.05297871691, 3.5231183490, 0.00000016334, 5.18826691036, 26.2983197998, 0.00000015752, 3.68457889430, 155.4203994342, 0.00000009541, 0.75742297675, 18849.2275499742, 0.00000008937, 2.05705419118, 77713.7714681205, 0.00000006952, 0.82673305410, 775.5226113240, 0.00000005064, 4.66284525271, 1577.3435424478}; 20 | 21 | private static final double E13[] = {0.00000289226, 5.84384198723, 6283.0758499914, 0.00000034955, 0.00000000000, 0.0000000000, 0.00000016819, 5.48766912348, 12566.1516999828}; 22 | 23 | private static final double E14[] = {0.00000114084, 3.14159265359, 0.0000000000, 0.00000007717, 4.13446589358, 6283.0758499914, 0.00000000765, 3.83803776214, 12566.1516999828}; 24 | 25 | private static final double E15[] = {0.00000000878, 3.14159265359, 0.0000000000}; 26 | 27 | private static final double E20[] = {0.00000279620, 3.19870156017, 84334.6615813083, 0.00000101643, 5.42248619256, 5507.5532386674, 0.00000080445, 3.88013204458, 5223.6939198022, 0.00000043806, 3.70444689758, 2352.8661537718, 0.00000031933, 4.00026369781, 1577.3435424478, 0.00000022724, 3.98473831560, 1047.7473117547, 0.00000016392, 3.56456119782, 5856.4776591154, 0.00000018141, 4.98367470263, 6283.0758499914, 0.00000014443, 3.70275614914, 9437.7629348870, 0.00000014304, 3.41117857525, 10213.2855462110}; 28 | 29 | private static final double E21[] = {0.00000009030, 3.89729061890, 5507.5532386674, 0.00000006177, 1.73038850355, 5223.6939198022}; 30 | 31 | private static final double E30[] = {1.00013988799, 0.00000000000, 0.0000000000, 0.01670699626, 3.09846350771, 6283.0758499914, 0.00013956023, 3.05524609620, 12566.1516999828, 0.00003083720, 5.19846674381, 77713.7714681205, 0.00001628461, 1.17387749012, 5753.3848848968, 0.00001575568, 2.84685245825, 7860.4193924392, 0.00000924799, 5.45292234084, 11506.7697697936, 0.00000542444, 4.56409149777, 3930.2096962196}; 32 | 33 | private static final double E31[] = {0.00103018608, 1.10748969588, 6283.0758499914, 0.00001721238, 1.06442301418, 12566.1516999828, 0.00000702215, 3.14159265359, 0.0000000000}; 34 | 35 | private static final double E32[] = {0.00004359385, 5.78455133738, 6283.0758499914}; 36 | 37 | private static final double E33[] = {0.00000144595, 4.27319435148, 6283.0758499914}; 38 | 39 | private static final double M10[] = {22639.5858800, 2.3555545723, 8328.6914247251, 1.5231275E-04, 2.5041111E-07, -1.1863391E-09, 4586.4383203, 8.0413790709, 7214.0628654588, -2.1850087E-04, -1.8646419E-07, 8.7760973E-10, 2369.9139357, 10.3969336431, 15542.7542901840, -6.6188121E-05, 6.3946925E-08, -3.0872935E-10, 769.0257187, 4.7111091445, 16657.3828494503, 3.0462550E-04, 5.0082223E-07, -2.3726782E-09, -666.4175399, -0.0431256817, 628.3019552485, -2.6638815E-06, 6.1639211E-10, -5.4439728E-11, -411.5957339, 3.2558104895, 16866.9323152810, -1.2804259E-04, -9.8998954E-09, 4.0433461E-11, 211.6555524, 5.6858244986, -1114.6285592663, -3.7081362E-04, -4.3687530E-07, 2.0639488E-09, 205.4359530, 8.0845047526, 6585.7609102104, -2.1583699E-04, -1.8708058E-07, 9.3204945E-10, 191.9561973, 12.7524882154, 23871.4457149091, 8.6124629E-05, 3.1435804E-07, -1.4950684E-09, 164.7286185, 10.4400593249, 14914.4523349355, -6.3524240E-05, 6.3330532E-08, -2.5428962E-10, -147.3213842, -2.3986802540, -7700.3894694766, -1.5497663E-04, -2.4979472E-07, 1.1318993E-09, -124.9881185, 5.1984668216, 7771.3771450920, -3.3094061E-05, 3.1973462E-08, -1.5436468E-10, -109.3803637, 2.3124288905, 8956.9933799736, 1.4964887E-04, 2.5102751E-07, -1.2407788E-09, 55.1770578, 7.1411231536, -1324.1780250970, 6.1854469E-05, 7.3846820E-08, -3.4916281E-10, -45.0996092, 5.6113650618, 25195.6237400061, 2.4270161E-05, 2.4051122E-07, -1.1459056E-09, 39.5333010, -0.9002559173, -8538.2408905558, 2.8035534E-04, 2.6031101E-07, -1.2267725E-09, 38.4298346, 18.4383127140, 22756.8171556428, -2.8468899E-04, -1.2251727E-07, 5.6888037E-10, 36.1238141, 7.0666637168, 24986.0742741754, 4.5693825E-04, 7.5123334E-07, -3.5590172E-09, 30.7725751, 16.0827581417, 14428.1257309177, -4.3700174E-04, -3.7292838E-07, 1.7552195E-09, -28.3971008, 7.9982533891, 7842.3648207073, -2.2116475E-04, -1.8584780E-07, 8.2317000E-10, -24.3582283, 10.3538079614, 16171.0562454324, -6.8852003E-05, 6.4563317E-08, -3.6316908E-10, -18.5847068, 2.8429122493, -557.3142796331, -1.8540681E-04, -2.1843765E-07, 1.0319744E-09, 17.9544674, 5.1553411398, 8399.6791003405, -3.5757942E-05, 3.2589854E-08, -2.0880440E-10, 14.5302779, 12.7956138971, 23243.1437596606, 8.8788511E-05, 3.1374165E-07, -1.4406287E-09, 14.3796974, 15.1080427876, 32200.1371396342, 2.3843738E-04, 5.6476915E-07, -2.6814075E-09, 14.2514576, -24.0810366320, -2.3011998397, 1.5231275E-04, 2.5041111E-07, -1.1863391E-09, 13.8990596, 20.7938672862, 31085.5085803679, -1.3237624E-04, 1.2789385E-07, -6.1745870E-10, 13.1940636, 3.3302699264, -9443.3199839914, -5.2312637E-04, -6.8728642E-07, 3.2502879E-09, -9.6790568, -4.7542348263, -16029.0808942018, -3.0728938E-04, -5.0020584E-07, 2.3182384E-09, -9.3658635, 11.2971895604, 24080.9951807398, -3.4654346E-04, -1.9636409E-07, 9.1804319E-10, 8.6055318, 5.7289501804, -1742.9305145148, -3.6814974E-04, -4.3749170E-07, 2.1183885E-09, -8.4530982, 7.5540213938, 16100.0685698171, 1.1921869E-04, 2.8238458E-07, -1.3407038E-09, 8.0501724, 10.4831850066, 14286.1503796870, -6.0860358E-05, 6.2714140E-08, -1.9984990E-10, -7.6301553, 4.6679834628, 17285.6848046987, 3.0196162E-04, 5.0143862E-07, -2.4271179E-09, -7.4474952, -0.0862513635, 1256.6039104970, -5.3277630E-06, 1.2327842E-09, -1.0887946E-10, 7.3712011, 8.1276304344, 5957.4589549619, -2.1317311E-04, -1.8769697E-07, 9.8648918E-10, 7.0629900, 0.9591375719, 33.7570471374, -3.0829302E-05, -3.6967043E-08, 1.7385419E-10, -6.3831491, 9.4966777258, 7004.5133996281, 2.1416722E-04, 3.2425793E-07, -1.5355019E-09, -5.7416071, 13.6527441326, 32409.6866054649, -1.9423071E-04, 5.4047029E-08, -2.6829589E-10, 4.3740095, 18.4814383957, 22128.5152003943, -2.8202511E-04, -1.2313366E-07, 6.2332010E-10, -3.9976134, 7.9669196340, 33524.3151647312, 1.7658291E-04, 4.9092233E-07, -2.3322447E-09, -3.2096876, 13.2398458924, 14985.4400105508, -2.5159493E-04, -1.5449073E-07, 7.2324505E-10, -2.9145404, 12.7093625336, 24499.7476701576, 8.3460748E-05, 3.1497443E-07, -1.5495082E-09, 2.7318890, 16.1258838235, 13799.8237756692, -4.3433786E-04, -3.7354477E-07, 1.8096592E-09, -2.5679459, -2.4418059357, -7072.0875142282, -1.5764051E-04, -2.4917833E-07, 1.0774596E-09, -2.5211990, 7.9551277074, 8470.6667759558, -2.2382863E-04, -1.8523141E-07, 7.6873027E-10, 2.4888871, 5.6426988169, -486.3266040178, -3.7347750E-04, -4.3625891E-07, 2.0095091E-09, 2.1460741, 7.1842488353, -1952.4799803455, 6.4518350E-05, 7.3230428E-08, -2.9472308E-10, 1.9777270, 23.1494218585, 39414.2000050930, 1.9936508E-05, 3.7830496E-07, -1.8037978E-09, 1.9336825, 9.4222182890, 33314.7656989005, 6.0925100E-04, 1.0016445E-06, -4.7453563E-09, 1.8707647, 20.8369929680, 30457.2066251194, -1.2971236E-04, 1.2727746E-07, -5.6301898E-10, -1.7529659, 0.4873576771, -8886.0057043583, -3.3771956E-04, -4.6884877E-07, 2.2183135E-09, -1.4371624, 7.0979974718, -695.8760698485, 5.9190587E-05, 7.4463212E-08, -4.0360254E-10, -1.3725701, 1.4552986550, -209.5494658307, 4.3266809E-04, 5.1072212E-07, -2.4131116E-09, 1.2618162, 7.5108957121, 16728.3705250656, 1.1655481E-04, 2.8300097E-07, -1.3951435E-09}; 40 | 41 | private static final double M11[] = {1.6768000, -0.0431256817, 628.3019552485, -2.6638815E-06, 6.1639211E-10, -5.4439728E-11, 0.5164200, 11.2260974062, 6585.7609102104, -2.1583699E-04, -1.8708058E-07, 9.3204945E-10, 0.4138300, 13.5816519784, 14914.4523349355, -6.3524240E-05, 6.3330532E-08, -2.5428962E-10, 0.3711500, 5.5402729076, 7700.3894694766, 1.5497663E-04, 2.4979472E-07, -1.1318993E-09, 0.2756000, 2.3124288905, 8956.9933799736, 1.4964887E-04, 2.5102751E-07, -1.2407788E-09, 0.2459863, -25.6198212459, -2.3011998397, 1.5231275E-04, 2.5041111E-07, -1.1863391E-09, 0.0711800, 7.9982533891, 7842.3648207073, -2.2116475E-04, -1.8584780E-07, 8.2317000E-10, 0.0612800, 10.3538079614, 16171.0562454324, -6.8852003E-05, 6.4563317E-08, -3.6316908E-10}; 42 | 43 | private static final double M12[] = {0.0048700, -0.0431256817, 628.3019552485, -2.6638815E-06, 6.1639211E-10, -5.4439728E-11, 0.0022800, -27.1705318325, -2.3011998397, 1.5231275E-04, 2.5041111E-07, -1.1863391E-09, 0.0015000, 11.2260974062, 6585.7609102104, -2.1583699E-04, -1.8708058E-07, 9.3204945E-10}; 44 | 45 | private static final double M20[] = {18461.2400600, 1.6279052448, 8433.4661576405, -6.4021295E-05, -4.9499477E-09, 2.0216731E-11, 1010.1671484, 3.9834598170, 16762.1575823656, 8.8291456E-05, 2.4546117E-07, -1.1661223E-09, 999.6936555, 0.7276493275, -104.7747329154, 2.1633405E-04, 2.5536106E-07, -1.2065558E-09, 623.6524746, 8.7690283983, 7109.2881325435, -2.1668263E-06, 6.8896872E-08, -3.2894608E-10, 199.4837596, 9.6692843156, 15647.5290230993, -2.8252217E-04, -1.9141414E-07, 8.9782646E-10, 166.5741153, 6.4134738261, -1219.4032921817, -1.5447958E-04, -1.8151424E-07, 8.5739300E-10, 117.2606951, 12.0248388879, 23976.2204478244, -1.3020942E-04, 5.8996977E-08, -2.8851262E-10, 61.9119504, 6.3390143893, 25090.8490070907, 2.4060421E-04, 4.9587228E-07, -2.3524614E-09, 33.3572027, 11.1245829706, 15437.9795572686, 1.5014592E-04, 3.1930799E-07, -1.5152852E-09, 31.7596709, 3.0832038997, 8223.9166918098, 3.6864680E-04, 5.0577218E-07, -2.3928949E-09, 29.5766003, 8.8121540801, 6480.9861772950, 4.9705523E-07, 6.8280480E-08, -2.7450635E-10, 15.5662654, 4.0579192538, -9548.0947169068, -3.0679233E-04, -4.3192536E-07, 2.0437321E-09, 15.1215543, 14.3803934601, 32304.9118725496, 2.2103334E-05, 3.0940809E-07, -1.4748517E-09, -12.0941511, 8.7259027166, 7737.5900877920, -4.8307078E-06, 6.9513264E-08, -3.8338581E-10, 8.8681426, 9.7124099974, 15019.2270678508, -2.7985829E-04, -1.9203053E-07, 9.5226618E-10, 8.0450400, 0.6687636586, 8399.7091105030, -3.3191993E-05, 3.2017096E-08, -1.5363746E-10, 7.9585542, 12.0679645696, 23347.9184925760, -1.2754553E-04, 5.8380585E-08, -2.3407289E-10, 7.4345550, 6.4565995078, -1847.7052474301, -1.5181570E-04, -1.8213063E-07, 9.1183272E-10, -6.7314363, -4.0265854988, -16133.8556271171, -9.0955337E-05, -2.4484477E-07, 1.1116826E-09, 6.5795750, 16.8104074692, 14323.3509980023, -2.2066770E-04, -1.1756732E-07, 5.4866364E-10, -6.4600721, 1.5847795630, 9061.7681128890, -6.6685176E-05, -4.3335556E-09, -3.4222998E-11, -6.2964773, 4.8837157343, 25300.3984729215, -1.9206388E-04, -1.4849843E-08, 6.0650192E-11, -5.6323538, -0.7707750092, 733.0766881638, -2.1899793E-04, -2.5474467E-07, 1.1521161E-09, -5.3683961, 6.8263720663, 16204.8433027325, -9.7115356E-05, 2.7023515E-08, -1.3414795E-10, -5.3112784, 3.9403341353, 17390.4595376141, 8.5627574E-05, 2.4607756E-07, -1.2205621E-09, -5.0759179, 0.6845236457, 523.5272223331, 2.1367016E-04, 2.5597745E-07, -1.2609955E-09, -4.8396143, -1.6710309265, -7805.1642023920, 6.1357413E-05, 5.5663398E-09, -7.4656459E-11, -4.8057401, 3.5705615768, -662.0890125485, 3.0927234E-05, 3.6923410E-08, -1.7458141E-10, 3.9840545, 8.6945689615, 33419.5404318159, 3.9291696E-04, 7.4628340E-07, -3.5388005E-09, 3.6744619, 19.1659620415, 22652.0424227274, -6.8354947E-05, 1.3284380E-07, -6.3767543E-10, 2.9984815, 20.0662179587, 31190.2833132833, -3.4871029E-04, -1.2746721E-07, 5.8909710E-10, 2.7986413, -2.5281611620, -16971.7070481963, 3.4437664E-04, 2.6526096E-07, -1.2469893E-09, 2.4138774, 17.7106633865, 22861.5918885581, -5.0102304E-04, -3.7787833E-07, 1.7754362E-09, 2.1863132, 5.5132179088, -9757.6441827375, 1.2587576E-04, 7.8796768E-08, -3.6937954E-10, 2.1461692, 13.4801375428, 23766.6709819937, 3.0245868E-04, 5.6971910E-07, -2.7016242E-09, 1.7659832, 11.1677086523, 14809.6776020201, 1.5280981E-04, 3.1869159E-07, -1.4608454E-09, -1.6244212, 7.3137297434, 7318.8375983742, -4.3483492E-04, -4.4182525E-07, 2.0841655E-09, 1.5813036, 5.4387584720, 16552.6081165349, 5.2095955E-04, 7.5618329E-07, -3.5792340E-09, 1.5197528, 16.7359480324, 40633.6032972747, 1.7441609E-04, 5.5981921E-07, -2.6611908E-09, 1.5156341, 1.7023646816, -17876.7861416319, -4.5910508E-04, -6.8233647E-07, 3.2300712E-09, 1.5102092, 5.4977296450, 8399.6847301375, -3.3094061E-05, 3.1973462E-08, -1.5436468E-10, -1.3178223, 9.6261586339, 16275.8309783478, -2.8518605E-04, -1.9079775E-07, 8.4338673E-10, -1.2642739, 11.9817132061, 24604.5224030729, -1.3287330E-04, 5.9613369E-08, -3.4295235E-10, 1.1918723, 22.4217725310, 39518.9747380084, -1.9639754E-04, 1.2294390E-07, -5.9724197E-10, 1.1346110, 14.4235191419, 31676.6099173011, 2.4767216E-05, 3.0879170E-07, -1.4204120E-09, 1.0857810, 8.8552797618, 5852.6842220465, 3.1609367E-06, 6.7664088E-08, -2.2006663E-10, -1.0193852, 7.2392703065, 33629.0898976466, -3.9751134E-05, 2.3556127E-07, -1.1256889E-09, -0.8227141, 11.0814572888, 16066.2815125171, 1.4748204E-04, 3.1992438E-07, -1.5697249E-09, 0.8042238, 3.5274358950, -33.7870573000, 2.8263353E-05, 3.7539802E-08, -2.2902113E-10, 0.8025939, 6.7832463846, 16833.1452579809, -9.9779237E-05, 2.7639907E-08, -1.8858767E-10, -0.7931866, -6.3821400710, -24462.5470518423, -2.4326809E-04, -4.9525589E-07, 2.2980217E-09, -0.7910153, 6.3703481443, -591.1013369332, -1.5714346E-04, -1.8089785E-07, 8.0295327E-10, -0.6674056, 9.1819266386, 24533.5347274576, 5.5197395E-05, 2.7743463E-07, -1.3204870E-09, 0.6502226, 4.1010449356, -10176.3966721553, -3.0412845E-04, -4.3254175E-07, 2.0981718E-09, -0.6388131, 6.2958887075, 25719.1509623392, 2.3794032E-04, 4.9648867E-07, -2.4069012E-09}; 46 | 47 | private static final double M21[] = {0.0743000, 11.9537467337, 6480.9861772950, 4.9705523E-07, 6.8280480E-08, -2.7450635E-10, 0.0304300, 8.7259027166, 7737.5900877920, -4.8307078E-06, 6.9513264E-08, -3.8338581E-10, 0.0222900, 12.8540026510, 15019.2270678508, -2.7985829E-04, -1.9203053E-07, 9.5226618E-10, 0.0199900, 15.2095572232, 23347.9184925760, -1.2754553E-04, 5.8380585E-08, -2.3407289E-10, 0.0186900, 9.5981921614, -1847.7052474301, -1.5181570E-04, -1.8213063E-07, 9.1183272E-10, 0.0169600, 7.1681781524, 16133.8556271171, 9.0955337E-05, 2.4484477E-07, -1.1116826E-09, 0.0162300, 1.5847795630, 9061.7681128890, -6.6685176E-05, -4.3335556E-09, -3.4222998E-11, 0.0141900, -0.7707750092, 733.0766881638, -2.1899793E-04, -2.5474467E-07, 1.1521161E-09}; 48 | 49 | private static final double M30[] = {385000.5290396, 1.5707963268, 0.0000000000, 0.0000000E+00, 0.0000000E+00, 0.0000000E+00, -20905.3551378, 3.9263508990, 8328.6914247251, 1.5231275E-04, 2.5041111E-07, -1.1863391E-09, -3699.1109330, 9.6121753977, 7214.0628654588, -2.1850087E-04, -1.8646419E-07, 8.7760973E-10, -2955.9675626, 11.9677299699, 15542.7542901840, -6.6188121E-05, 6.3946925E-08, -3.0872935E-10, -569.9251264, 6.2819054713, 16657.3828494503, 3.0462550E-04, 5.0082223E-07, -2.3726782E-09, 246.1584797, 7.2566208254, -1114.6285592663, -3.7081362E-04, -4.3687530E-07, 2.0639488E-09, -204.5861179, 12.0108556517, 14914.4523349355, -6.3524240E-05, 6.3330532E-08, -2.5428962E-10, -170.7330791, 14.3232845422, 23871.4457149091, 8.6124629E-05, 3.1435804E-07, -1.4950684E-09, -152.1378118, 9.6553010794, 6585.7609102104, -2.1583699E-04, -1.8708058E-07, 9.3204945E-10, -129.6202242, -0.8278839272, -7700.3894694766, -1.5497663E-04, -2.4979472E-07, 1.1318993E-09, 108.7427014, 6.7692631483, 7771.3771450920, -3.3094061E-05, 3.1973462E-08, -1.5436468E-10, 104.7552944, 3.8832252173, 8956.9933799736, 1.4964887E-04, 2.5102751E-07, -1.2407788E-09, 79.6605685, 0.6705404095, -8538.2408905558, 2.8035534E-04, 2.6031101E-07, -1.2267725E-09, 48.8883284, 1.5276706450, 628.3019552485, -2.6638815E-06, 6.1639211E-10, -5.4439728E-11, -34.7825237, 20.0091090408, 22756.8171556428, -2.8468899E-04, -1.2251727E-07, 5.6888037E-10, 30.8238599, 11.9246042882, 16171.0562454324, -6.8852003E-05, 6.4563317E-08, -3.6316908E-10, 24.2084985, 9.5690497159, 7842.3648207073, -2.2116475E-04, -1.8584780E-07, 8.2317000E-10, -23.2104305, 8.6374600436, 24986.0742741754, 4.5693825E-04, 7.5123334E-07, -3.5590172E-09, -21.6363439, 17.6535544685, 14428.1257309177, -4.3700174E-04, -3.7292838E-07, 1.7552195E-09, -16.6747239, 6.7261374666, 8399.6791003405, -3.5757942E-05, 3.2589854E-08, -2.0880440E-10, 14.4026890, 4.9010662531, -9443.3199839914, -5.2312637E-04, -6.8728642E-07, 3.2502879E-09, -12.8314035, 14.3664102239, 23243.1437596606, 8.8788511E-05, 3.1374165E-07, -1.4406287E-09, -11.6499478, 22.3646636130, 31085.5085803679, -1.3237624E-04, 1.2789385E-07, -6.1745870E-10, -10.4447578, 16.6788391144, 32200.1371396342, 2.3843738E-04, 5.6476915E-07, -2.6814075E-09, 10.3211071, 8.7119194804, -1324.1780250970, 6.1854469E-05, 7.3846820E-08, -3.4916281E-10, 10.0562033, 7.2997465071, -1742.9305145148, -3.6814974E-04, -4.3749170E-07, 2.1183885E-09, -9.8844667, 12.0539813334, 14286.1503796870, -6.0860358E-05, 6.2714140E-08, -1.9984990E-10, 8.7515625, 6.3563649081, -9652.8694498221, -9.0458282E-05, -1.7656429E-07, 8.3717626E-10, -8.3791067, 4.4137085761, -557.3142796331, -1.8540681E-04, -2.1843765E-07, 1.0319744E-09, -7.0026961, -3.1834384995, -16029.0808942018, -3.0728938E-04, -5.0020584E-07, 2.3182384E-09, 6.3220032, 9.1248177206, 16100.0685698171, 1.1921869E-04, 2.8238458E-07, -1.3407038E-09, 5.7508579, 6.2387797896, 17285.6848046987, 3.0196162E-04, 5.0143862E-07, -2.4271179E-09, -4.9501349, 9.6984267611, 5957.4589549619, -2.1317311E-04, -1.8769697E-07, 9.8648918E-10, -4.4211770, 3.0260949818, -209.5494658307, 4.3266809E-04, 5.1072212E-07, -2.4131116E-09, 4.1311145, 11.0674740526, 7004.5133996281, 2.1416722E-04, 3.2425793E-07, -1.5355019E-09, -3.9579827, 20.0522347225, 22128.5152003943, -2.8202511E-04, -1.2313366E-07, 6.2332010E-10, 3.2582371, 14.8106422192, 14985.4400105508, -2.5159493E-04, -1.5449073E-07, 7.2324505E-10, -3.1483020, 4.8266068163, 16866.9323152810, -1.2804259E-04, -9.8998954E-09, 4.0433461E-11, 2.6164092, 14.2801588604, 24499.7476701576, 8.3460748E-05, 3.1497443E-07, -1.5495082E-09, 2.3536310, 9.5259240342, 8470.6667759558, -2.2382863E-04, -1.8523141E-07, 7.6873027E-10, -2.1171283, -0.8710096090, -7072.0875142282, -1.5764051E-04, -2.4917833E-07, 1.0774596E-09, -1.8970368, 17.6966801503, 13799.8237756692, -4.3433786E-04, -3.7354477E-07, 1.8096592E-09, -1.7385258, 2.0581540038, -8886.0057043583, -3.3771956E-04, -4.6884877E-07, 2.2183135E-09, -1.5713944, 22.4077892948, 30457.2066251194, -1.2971236E-04, 1.2727746E-07, -5.6301898E-10, -1.4225541, 24.7202181853, 39414.2000050930, 1.9936508E-05, 3.7830496E-07, -1.8037978E-09, -1.4189284, 17.1661967915, 23314.1314352759, -9.9282182E-05, 9.5920387E-08, -4.6309403E-10, 1.1655364, 3.8400995356, 9585.2953352221, 1.4698499E-04, 2.5164390E-07, -1.2952185E-09, -1.1169371, 10.9930146158, 33314.7656989005, 6.0925100E-04, 1.0016445E-06, -4.7453563E-09, 1.0656723, 1.4845449633, 1256.6039104970, -5.3277630E-06, 1.2327842E-09, -1.0887946E-10, 1.0586190, 11.9220903668, 8364.7398411275, -2.1850087E-04, -1.8646419E-07, 8.7760973E-10, -0.9333176, 9.0816920389, 16728.3705250656, 1.1655481E-04, 2.8300097E-07, -1.3951435E-09, 0.8624328, 12.4550876470, 6656.7485858257, -4.0390768E-04, -4.0490184E-07, 1.9095841E-09, 0.8512404, 4.3705828944, 70.9876756153, -1.8807069E-04, -2.1782126E-07, 9.7753467E-10, -0.8488018, 16.7219647962, 31571.8351843857, 2.4110126E-04, 5.6415276E-07, -2.6269678E-09, -0.7956264, 3.5134526588, -9095.5551701890, 9.4948529E-05, 4.1873358E-08, -1.9479814E-10}; 50 | 51 | private static final double M31[] = {0.5139500, 12.0108556517, 14914.4523349355, -6.3524240E-05, 6.3330532E-08, -2.5428962E-10, 0.3824500, 9.6553010794, 6585.7609102104, -2.1583699E-04, -1.8708058E-07, 9.3204945E-10, 0.3265400, 3.9694765808, 7700.3894694766, 1.5497663E-04, 2.4979472E-07, -1.1318993E-09, 0.2639600, 0.7416325637, 8956.9933799736, 1.4964887E-04, 2.5102751E-07, -1.2407788E-09, 0.1230200, -1.6139220085, 628.3019552485, -2.6638815E-06, 6.1639211E-10, -5.4439728E-11, 0.0775400, 8.7830116346, 16171.0562454324, -6.8852003E-05, 6.4563317E-08, -3.6316908E-10, 0.0606800, 6.4274570623, 7842.3648207073, -2.2116475E-04, -1.8584780E-07, 8.2317000E-10, 0.0497000, 12.0539813334, 14286.1503796870, -6.0860358E-05, 6.2714140E-08, -1.9984990E-10}; 52 | 53 | private static final double M1n[] = {3.81034392032, 8.39968473021E+03, -3.31919929753E-05, 3.20170955005E-08, -1.53637455544E-10}; 54 | 55 | private static final double nutB[] = {2.1824391966, -33.757045954, 0.0000362262, 3.7340E-08, -2.8793E-10, -171996, -1742, 92025, 89, 3.5069406862, 1256.663930738, 0.0000105845, 6.9813E-10, -2.2815E-10, -13187, -16, 5736, -31, 1.3375032491, 16799.418221925, -0.0000511866, 6.4626E-08, -5.3543E-10, -2274, -2, 977, -5, 4.3648783932, -67.514091907, 0.0000724525, 7.4681E-08, -5.7586E-10, 2062, 2, -895, 5, 0.0431251803, -628.301955171, 0.0000026820, 6.5935E-10, 5.5705E-11, -1426, 34, 54, -1, 2.3555557435, 8328.691425719, 0.0001545547, 2.5033E-07, -1.1863E-09, 712, 1, -7, 0, 3.4638155059, 1884.965885909, 0.0000079025, 3.8785E-11, -2.8386E-10, -517, 12, 224, -6, 5.4382493597, 16833.175267879, -0.0000874129, 2.7285E-08, -2.4750E-10, -386, -4, 200, 0, 3.6930589926, 25128.109647645, 0.0001033681, 3.1496E-07, -1.7218E-09, -301, 0, 129, -1, 3.5500658664, 628.361975567, 0.0000132664, 1.3575E-09, -1.7245E-10, 217, -5, -95, 3}; 56 | 57 | private static final double GXC_e[] = {0.016708634, -0.000042037, -0.0000001267}; 58 | 59 | private static final double rad = 180 * 3600 / Math.PI; 60 | 61 | private static final double RAD = 180 / Math.PI; 62 | 63 | private static final double J2000 = 2451545; 64 | 65 | private static final double preceB[] = {0, 50287.92262, 111.24406, 0.07699, -0.23479, -0.00178, 0.00018, 0.00001}; 66 | 67 | private static final double GXC_p[] = {102.93735 / RAD, 1.71946 / RAD, 0.00046 / RAD}; 68 | 69 | private static final double GXC_l[] = {280.4664567 / RAD, 36000.76982779 / RAD, 0.0003032028 / RAD, 1 / 49931000 / RAD, -1 / 153000000 / RAD}; 70 | 71 | private static final double GXC_k = 20.49552 / rad; 72 | 73 | private static final double[] dts = {-4000, 108371.7, -13036.80, 392.000, 0.0000, -500, 17201.0, -627.82, 16.170, -0.3413, -150, 12200.6, -346.41, 5.403, -0.1593, 150, 9113.8, -328.13, -1.647, 0.0377, 500, 5707.5, -391.41, 0.915, 0.3145, 900, 2203.4, -283.45, 13.034, -0.1778, 1300, 490.1, -57.35, 2.085, -0.0072, 1600, 120.0, -9.81, -1.532, 0.1403, 1700, 10.2, -0.91, 0.510, -0.0370, 1800, 13.4, -0.72, 0.202, -0.0193, 1830, 7.8, -1.81, 0.416, -0.0247, 1860, 8.3, -0.13, -0.406, 0.0292, 1880, -5.4, 0.32, -0.183, 0.0173, 1900, -2.3, 2.06, 0.169, -0.0135, 1920, 21.2, 1.69, -0.304, 0.0167, 1940, 24.2, 1.22, -0.064, 0.0031, 1960, 33.2, 0.51, 0.231, -0.0109, 1980, 51.0, 1.29, -0.026, 0.0032, 2000, 64.7, -1.66, 5.224, -0.2905, 2150, 279.4, 732.95, 429.579, 0.0158, 6000}; 74 | 75 | private double EnnT = 0; 76 | private double MnnT = 0; 77 | 78 | private double D = 1; 79 | 80 | private class ZD { 81 | double Lon; 82 | double Obl; 83 | } 84 | 85 | /** 86 | * 生成某年农历二十四节气数组数据 87 | * Create solar term by year. 88 | * 89 | * @param year 某年 90 | * @return ... 91 | */ 92 | String[][] buildSolarTerm(int year) { 93 | String[] tmp = new String[24]; 94 | double jd = 365.2422 * (year - 2000), q; 95 | int j; 96 | for (int i = 0; i < tmp.length; i++) { 97 | j = (i - 5); 98 | q = angleCal(jd + j * 15.2, j * 15, 0); 99 | q = q + J2000 + (double) 8 / 24; 100 | setFromJD(q, true); 101 | tmp[i] = String.valueOf((int) D); 102 | } 103 | return DataUtils.arraysConvert(tmp, 12, 2); 104 | } 105 | 106 | private void setFromJD(double jd, boolean UTC) { 107 | if (UTC) 108 | jd -= this.deltaT2(jd - J2000); 109 | jd += 0.5; 110 | 111 | double A = int2(jd); 112 | double D; 113 | 114 | if (A > 2299161) { 115 | D = int2((A - 1867216.25) / 36524.25); 116 | A += 1 + D - int2(D / 4); 117 | } 118 | A += 1524; 119 | double y = int2((A - 122.1) / 365.25); 120 | D = A - int2(365.25 * y); 121 | double m = int2(D / 30.6001); 122 | this.D = D - int2(m * 30.6001); 123 | y -= 4716; 124 | m--; 125 | if (m > 12) 126 | m -= 12; 127 | if (m <= 2) 128 | //noinspection UnusedAssignment 129 | y++; 130 | } 131 | 132 | private double int2(double v) { 133 | v = Math.floor(v); 134 | if (v < 0) 135 | return v + 1; 136 | return v; 137 | } 138 | 139 | private double deltaT2(double jd) { 140 | return this.deltaT(jd / 365.2425 + 2000) / 86400.0; 141 | } 142 | 143 | private double deltaT(double y) { 144 | int i; 145 | for (i = 0; i < 100; i += 5) 146 | if (y < dts[i + 5] || i == 95) 147 | break; 148 | double t1 = (y - dts[i]) / (dts[i + 5] - dts[i]) * 10; 149 | double t2 = t1 * t1; 150 | double t3 = t2 * t1; 151 | return dts[i + 1] + dts[i + 2] * t1 + dts[i + 3] * t2 + dts[i + 4] * t3; 152 | } 153 | 154 | private double angleCal(double t1, double jiao, int lx) { 155 | double t2 = t1, t = 0, v; 156 | if (lx == 0) 157 | t2 += 360; 158 | else 159 | t2 += 25; 160 | jiao *= Math.PI / 180; 161 | double v1 = jiaoCai(lx, t1, jiao); 162 | double v2 = jiaoCai(lx, t2, jiao); 163 | if (v1 < v2) 164 | v2 -= 2 * Math.PI; 165 | double k = 1, k2; 166 | for (int i = 0; i < 10; i++) { 167 | k2 = (v2 - v1) / (t2 - t1); 168 | if (Math.abs(k2) > 1e-15) 169 | k = k2; 170 | t = t1 - v1 / k; 171 | v = jiaoCai(lx, t, jiao); 172 | if (v > 1) 173 | v -= 2 * Math.PI; 174 | if (Math.abs(v) < 1e-8) 175 | break; 176 | t1 = t2; 177 | v1 = v2; 178 | t2 = t; 179 | v2 = v; 180 | } 181 | return t; 182 | } 183 | 184 | private double jiaoCai(int lx, double t, double jiao) { 185 | double[] sun = earCal(t); 186 | sun[0] += Math.PI; 187 | sun[1] = -sun[1]; 188 | addGxc(t, sun); 189 | if (lx == 0) { 190 | ZD d = nutation(t); 191 | sun[0] += d.Lon; 192 | return rad2mrad(jiao - sun[0]); 193 | } 194 | double[] moon = moonCal(t); 195 | return rad2mrad(jiao - (moon[0] - sun[0])); 196 | } 197 | 198 | private double[] moonCal(double jd) { 199 | MnnT = jd / 36525; 200 | double t1 = MnnT, t2 = t1 * t1, t3 = t2 * t1, t4 = t3 * t1; 201 | double[] llr = new double[3]; 202 | llr[0] = (Mnn(M10) + Mnn(M11) * t1 + Mnn(M12) * t2) / rad; 203 | llr[1] = (Mnn(M20) + Mnn(M21) * t1) / rad; 204 | llr[2] = (Mnn(M30) + Mnn(M31) * t1) * 0.999999949827; 205 | llr[0] = llr[0] + M1n[0] + M1n[1] * t1 + M1n[2] * t2 + M1n[3] * t3 + M1n[4] * t4; 206 | llr[0] = rad2mrad(llr[0]); 207 | addPrece(jd, llr); 208 | return llr; 209 | } 210 | 211 | private void addPrece(double jd, double[] zb) { 212 | int i; 213 | double t = 1, v = 0, t1 = jd / 365250; 214 | for (i = 1; i < 8; i++) { 215 | t *= t1; 216 | v += preceB[i] * t; 217 | } 218 | zb[0] = rad2mrad(zb[0] + (v + 2.9965 * t1) / rad); 219 | } 220 | 221 | private double Mnn(double[] F) { 222 | double v = 0, t1 = MnnT, t2 = t1 * t1, t3 = t2 * t1, t4 = t3 * t1; 223 | for (int i = 0; i < F.length; i += 6) 224 | v += F[i] * Math.sin(F[i + 1] + t1 * F[i + 2] + t2 * F[i + 3] + t3 * F[i + 4] + t4 * F[i + 5]); 225 | return v; 226 | } 227 | 228 | private ZD nutation(double t) { 229 | ZD d = new ZD(); 230 | d.Lon = 0; 231 | d.Obl = 0; 232 | t /= 36525; 233 | double c, t1 = t, t2 = t1 * t1, t3 = t2 * t1, t4 = t3 * t1; 234 | for (int i = 0; i < nutB.length; i += 9) { 235 | c = nutB[i] + nutB[i + 1] * t1 + nutB[i + 2] * t2 + nutB[i + 3] * t3 + nutB[i + 4] * t4; 236 | d.Lon += (nutB[i + 5] + nutB[i + 6] * t / 10) * Math.sin(c); 237 | d.Obl += (nutB[i + 7] + nutB[i + 8] * t / 10) * Math.cos(c); 238 | } 239 | d.Lon /= rad * 10000; 240 | d.Obl /= rad * 10000; 241 | return d; 242 | } 243 | 244 | private void addGxc(double t, double[] zb) { 245 | double t1 = t / 36525; 246 | double t2 = t1 * t1; 247 | double t3 = t2 * t1; 248 | double t4 = t3 * t1; 249 | double L = GXC_l[0] + GXC_l[1] * t1 + GXC_l[2] * t2 + GXC_l[3] * t3 + GXC_l[4] * t4; 250 | double p = GXC_p[0] + GXC_p[1] * t1 + GXC_p[2] * t2; 251 | double e = GXC_e[0] + GXC_e[1] * t1 + GXC_e[2] * t2; 252 | double dL = L - zb[0], dP = p - zb[0]; 253 | zb[0] -= GXC_k * (Math.cos(dL) - e * Math.cos(dP)) / Math.cos(zb[1]); 254 | zb[1] -= GXC_k * Math.sin(zb[1]) * (Math.sin(dL) - e * Math.sin(dP)); 255 | zb[0] = rad2mrad(zb[0]); 256 | } 257 | 258 | private double[] earCal(double jd) { 259 | EnnT = jd / 365250; 260 | double llr[] = new double[3]; 261 | double t1 = EnnT, t2 = t1 * t1, t3 = t2 * t1, t4 = t3 * t1, t5 = t4 * t1; 262 | llr[0] = Enn(E10) + Enn(E11) * t1 + Enn(E12) * t2 + Enn(E13) * t3 + Enn(E14) * t4 + Enn(E15) * t5; 263 | llr[1] = Enn(E20) + Enn(E21) * t1; 264 | llr[2] = Enn(E30) + Enn(E31) * t1 + Enn(E32) * t2 + Enn(E33) * t3; 265 | llr[0] = rad2mrad(llr[0]); 266 | return llr; 267 | } 268 | 269 | private double rad2mrad(double v) { 270 | v = v % (2 * Math.PI); 271 | if (v < 0) 272 | return v + 2 * Math.PI; 273 | return v; 274 | } 275 | 276 | private double Enn(double[] F) { 277 | double v = 0; 278 | for (int i = 0; i < F.length; i += 3) 279 | v += F[i] * Math.cos(F[i + 1] + EnnT * F[i + 2]); 280 | return v; 281 | } 282 | } 283 | -------------------------------------------------------------------------------- /DatePicker/src/main/java/cn/aigestudio/datepicker/bizs/decors/DPDecor.java: -------------------------------------------------------------------------------- 1 | package cn.aigestudio.datepicker.bizs.decors; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Paint; 5 | import android.graphics.Rect; 6 | 7 | /** 8 | * 月历装饰物类 9 | * Decor of Calendar 10 | * 11 | * @author AigeStudio 2015-07-22 12 | * @author AigeStudio 2015-10-29 13 | * 为每一个装饰物的绘制方法增加一个含参data的重载方法 14 | * Add a parameter for each method. 15 | */ 16 | public class DPDecor { 17 | /** 18 | * 绘制当前日期区域左上角的装饰物 19 | * Draw decor on Top left of current date area 20 | * 21 | * @param canvas 绘制图形的画布 Canvas of image drew 22 | * @param rect 可以绘制的区域范围 Area you can draw 23 | * @param paint 画笔对象 Paint 24 | * @param data 日期 25 | */ 26 | public void drawDecorTL(Canvas canvas, Rect rect, Paint paint, String data) { 27 | drawDecorTL(canvas, rect, paint); 28 | } 29 | 30 | /** 31 | * @see #drawDecorTL(Canvas, Rect, Paint, String) 32 | */ 33 | public void drawDecorTL(Canvas canvas, Rect rect, Paint paint) { 34 | 35 | } 36 | 37 | /** 38 | * 绘制当前日期区域顶部的装饰物 39 | * Draw decor on top of current date area 40 | * 41 | * @param canvas 绘制图形的画布 Canvas of image drew 42 | * @param rect 可以绘制的区域范围 Area you can draw 43 | * @param paint 画笔对象 Paint 44 | * @param data 日期 45 | */ 46 | public void drawDecorT(Canvas canvas, Rect rect, Paint paint, String data) { 47 | drawDecorT(canvas, rect, paint); 48 | } 49 | 50 | /** 51 | * @see #drawDecorT(Canvas, Rect, Paint, String) 52 | */ 53 | public void drawDecorT(Canvas canvas, Rect rect, Paint paint) { 54 | 55 | } 56 | 57 | /** 58 | * 绘制当前日期区域右上角的装饰物 59 | * Draw decor on Top right of current date area 60 | * 61 | * @param canvas 绘制图形的画布 Canvas of image drew 62 | * @param rect 可以绘制的区域范围 Area you can draw 63 | * @param paint 画笔对象 Paint 64 | * @param data 日期 65 | */ 66 | public void drawDecorTR(Canvas canvas, Rect rect, Paint paint, String data) { 67 | drawDecorTR(canvas, rect, paint); 68 | } 69 | 70 | /** 71 | * @see #drawDecorTR(Canvas, Rect, Paint, String) 72 | */ 73 | public void drawDecorTR(Canvas canvas, Rect rect, Paint paint) { 74 | 75 | } 76 | 77 | /** 78 | * 绘制当前日期区域左边的装饰物 79 | * Draw decor on left of current date area 80 | * 81 | * @param canvas 绘制图形的画布 Canvas of image drew 82 | * @param rect 可以绘制的区域范围 Area you can draw 83 | * @param paint 画笔对象 Paint 84 | * @param data 日期 85 | */ 86 | public void drawDecorL(Canvas canvas, Rect rect, Paint paint, String data) { 87 | drawDecorL(canvas, rect, paint); 88 | } 89 | 90 | /** 91 | * @see #drawDecorL(Canvas, Rect, Paint, String) 92 | */ 93 | public void drawDecorL(Canvas canvas, Rect rect, Paint paint) { 94 | 95 | } 96 | 97 | /** 98 | * 绘制当前日期区域右边的装饰物 99 | * Draw decor on right of current date area 100 | * 101 | * @param canvas 绘制图形的画布 Canvas of image drew 102 | * @param rect 可以绘制的区域范围 Area you can draw 103 | * @param paint 画笔对象 Paint 104 | * @param data 日期 105 | */ 106 | public void drawDecorR(Canvas canvas, Rect rect, Paint paint, String data) { 107 | drawDecorR(canvas, rect, paint); 108 | } 109 | 110 | /** 111 | * @see #drawDecorR(Canvas, Rect, Paint, String) 112 | */ 113 | public void drawDecorR(Canvas canvas, Rect rect, Paint paint) { 114 | 115 | } 116 | 117 | /** 118 | * 绘制当前日期区域背景的装饰物 119 | * Draw decor of background of current date area 120 | * 121 | * @param canvas 绘制图形的画布 Canvas of image drew 122 | * @param rect 可以绘制的区域范围 Area you can draw 123 | * @param paint 画笔对象 Paint 124 | * @param data 日期 125 | */ 126 | public void drawDecorBG(Canvas canvas, Rect rect, Paint paint, String data) { 127 | drawDecorBG(canvas, rect, paint); 128 | } 129 | 130 | /** 131 | * @see #drawDecorBG(Canvas, Rect, Paint, String) 132 | */ 133 | public void drawDecorBG(Canvas canvas, Rect rect, Paint paint) { 134 | 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /DatePicker/src/main/java/cn/aigestudio/datepicker/bizs/languages/CN.java: -------------------------------------------------------------------------------- 1 | package cn.aigestudio.datepicker.bizs.languages; 2 | 3 | /** 4 | * 中文的默认实现类 5 | * 如果你想实现更多的语言请参考Language{@link DPLManager} 6 | * 7 | * The implementation class of chinese. 8 | * You can refer to Language{@link DPLManager} if you want to define more language. 9 | * 10 | * @author AigeStudio 2015-03-28 11 | */ 12 | public class CN extends DPLManager { 13 | @Override 14 | public String[] titleMonth() { 15 | return new String[]{"一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"}; 16 | } 17 | 18 | @Override 19 | public String titleEnsure() { 20 | return "确定"; 21 | } 22 | 23 | @Override 24 | public String titleBC() { 25 | return "公元前"; 26 | } 27 | 28 | @Override 29 | public String[] titleWeek() { 30 | return new String[]{"日", "一", "二", "三", "四", "五", "六"}; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /DatePicker/src/main/java/cn/aigestudio/datepicker/bizs/languages/DPLManager.java: -------------------------------------------------------------------------------- 1 | package cn.aigestudio.datepicker.bizs.languages; 2 | 3 | import java.util.Locale; 4 | 5 | /** 6 | * 语言对象抽象父类 7 | * DatePicker暂且支持中文和英文两种显示语言 8 | * 如果你需要定义更多的语言可以新建自己的语言类并继承Language重写其方法即可 9 | * 同时你需要在Language的单例方法{@link #getInstance()}的分支语句中添加自己的语言类判断 10 | * 11 | * The abstract of language. 12 | * The current language only two support chinese and english in DatePicker. 13 | * If you need more language you want,you can define your own language class and extends Language 14 | * override all method. 15 | * Also you must add a judge of your language in branching statement of single case method{@link #getInstance()} 16 | * 17 | * @author AigeStudio 2015-03-26 18 | */ 19 | public abstract class DPLManager { 20 | private static DPLManager sLanguage; 21 | 22 | /** 23 | * 获取日历语言管理器 24 | * 25 | * Get DatePicker language manager 26 | * 27 | * @return 日历语言管理器 DatePicker language manager 28 | */ 29 | public static DPLManager getInstance() { 30 | if (null == sLanguage) { 31 | String locale = Locale.getDefault().getLanguage().toLowerCase(); 32 | if (locale.equals("zh")) { 33 | sLanguage = new CN(); 34 | } else { 35 | sLanguage = new EN(); 36 | } 37 | } 38 | return sLanguage; 39 | } 40 | 41 | /** 42 | * 月份标题显示 43 | * 44 | * Titles of month 45 | * 46 | * @return 长度为12的月份标题数组 Array in 12 length of month titles 47 | */ 48 | public abstract String[] titleMonth(); 49 | 50 | /** 51 | * 确定按钮文本 52 | * 53 | * Text of ensure button 54 | * 55 | * @return Text of ensure button 56 | */ 57 | public abstract String titleEnsure(); 58 | 59 | /** 60 | * 公元前文本 61 | * 62 | * Text of B.C. 63 | * 64 | * @return Text of B.C. 65 | */ 66 | public abstract String titleBC(); 67 | 68 | /** 69 | * 星期标题显示 70 | * 71 | * Titles of week 72 | * 73 | * @return 长度为7的星期标题数组 Array in 7 length of week titles 74 | */ 75 | public abstract String[] titleWeek(); 76 | } 77 | -------------------------------------------------------------------------------- /DatePicker/src/main/java/cn/aigestudio/datepicker/bizs/languages/EN.java: -------------------------------------------------------------------------------- 1 | package cn.aigestudio.datepicker.bizs.languages; 2 | 3 | /** 4 | * 英文的默认实现类 5 | * 如果你想实现更多的语言请参考Language{@link DPLManager} 6 | * 7 | * The implementation class of english. 8 | * You can refer to Language{@link DPLManager} if you want to define more language. 9 | * 10 | * @author AigeStudio 2015-03-28 11 | */ 12 | public class EN extends DPLManager { 13 | @Override 14 | public String[] titleMonth() { 15 | return new String[]{"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; 16 | } 17 | 18 | @Override 19 | public String titleEnsure() { 20 | return "Ok"; 21 | } 22 | 23 | @Override 24 | public String titleBC() { 25 | return "B.C."; 26 | } 27 | 28 | @Override 29 | public String[] titleWeek() { 30 | return new String[]{"MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"}; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /DatePicker/src/main/java/cn/aigestudio/datepicker/bizs/themes/DPBaseTheme.java: -------------------------------------------------------------------------------- 1 | package cn.aigestudio.datepicker.bizs.themes; 2 | 3 | /** 4 | * 主题的默认实现类 5 | * 6 | * The default implement of theme 7 | * 8 | * @author AigeStudio 2015-06-17 9 | */ 10 | public class DPBaseTheme extends DPTheme { 11 | @Override 12 | public int colorBG() { 13 | return 0xFFFFFFFF; 14 | } 15 | 16 | @Override 17 | public int colorBGCircle() { 18 | return 0x44000000; 19 | } 20 | 21 | @Override 22 | public int colorTitleBG() { 23 | return 0xFFF37B7A; 24 | } 25 | 26 | @Override 27 | public int colorTitle() { 28 | return 0xEEFFFFFF; 29 | } 30 | 31 | @Override 32 | public int colorToday() { 33 | return 0x88F37B7A; 34 | } 35 | 36 | @Override 37 | public int colorG() { 38 | return 0xEE333333; 39 | } 40 | 41 | @Override 42 | public int colorF() { 43 | return 0xEEC08AA4; 44 | } 45 | 46 | @Override 47 | public int colorWeekend() { 48 | return 0xEEF78082; 49 | } 50 | 51 | @Override 52 | public int colorHoliday() { 53 | return 0x80FED6D6; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /DatePicker/src/main/java/cn/aigestudio/datepicker/bizs/themes/DPCNTheme.java: -------------------------------------------------------------------------------- 1 | package cn.aigestudio.datepicker.bizs.themes; 2 | 3 | /** 4 | * 天朝日历主题类 5 | * 其他国家的主题不需要这样去处理 6 | * 7 | * Theme of china 8 | * You don't need this class for other countries 9 | * 10 | * @author AigeStudio 2015-06-17 11 | */ 12 | public class DPCNTheme extends DPBaseTheme { 13 | /** 14 | * 农历文本颜色 15 | * 16 | * Color of Lunar text 17 | * 18 | * @return 16进制颜色值 hex color 19 | */ 20 | public int colorL() { 21 | return 0xEE888888; 22 | } 23 | 24 | /** 25 | * 补休日期背景颜色 26 | * 27 | * Color of Deferred background 28 | * 29 | * @return 16进制颜色值 hex color 30 | */ 31 | public int colorDeferred() { 32 | return 0x50B48172; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /DatePicker/src/main/java/cn/aigestudio/datepicker/bizs/themes/DPTManager.java: -------------------------------------------------------------------------------- 1 | package cn.aigestudio.datepicker.bizs.themes; 2 | 3 | /** 4 | * 日历主题管理器 5 | * 在DatePicker被实例化前调用{@link #initCalendar(DPTheme)}方法来初始化一个日历主题对象 6 | * 7 | * DatePicker theme manager 8 | * Call {@link #initCalendar(DPTheme)} method to initialization a theme before DatePicker instance 9 | * 10 | * @author AigeStudio 2015-06-30 11 | */ 12 | public final class DPTManager { 13 | private static DPTManager sManager; 14 | 15 | private DPTheme theme;// 主题对象 16 | 17 | private DPTManager() { 18 | initCalendar(new DPCNTheme()); 19 | } 20 | 21 | /** 22 | * 获取日历主题管理器 23 | * 24 | * Get DatePicker theme manager 25 | * 26 | * @return 日历主题管理器 DatePicker theme manager 27 | */ 28 | public static DPTManager getInstance() { 29 | if (null == sManager) { 30 | sManager = new DPTManager(); 31 | } 32 | return sManager; 33 | } 34 | 35 | /** 36 | * 初始化主题对象 37 | * 38 | * Initialization Theme 39 | * 40 | * @param theme ... 41 | */ 42 | public void initCalendar(DPTheme theme) { 43 | this.theme = theme; 44 | } 45 | 46 | /** 47 | * @see DPTheme#colorTitleBG() 48 | */ 49 | public int colorTitleBG() { 50 | return theme.colorTitleBG(); 51 | } 52 | 53 | /** 54 | * @see DPTheme#colorBG() 55 | */ 56 | public int colorBG() { 57 | return theme.colorBG(); 58 | } 59 | 60 | /** 61 | * @see DPTheme#colorBGCircle() 62 | */ 63 | public int colorBGCircle() { 64 | return theme.colorBGCircle(); 65 | } 66 | 67 | /** 68 | * @see DPTheme#colorTitle() 69 | */ 70 | public int colorTitle() { 71 | return theme.colorTitle(); 72 | } 73 | 74 | /** 75 | * @see DPTheme#colorToday() 76 | */ 77 | public int colorToday() { 78 | return theme.colorToday(); 79 | } 80 | 81 | /** 82 | * @see DPTheme#colorG() 83 | */ 84 | public int colorG() { 85 | return theme.colorG(); 86 | } 87 | 88 | /** 89 | * @see DPTheme#colorF() 90 | */ 91 | public int colorF() { 92 | return theme.colorF(); 93 | } 94 | 95 | /** 96 | * @see DPTheme#colorWeekend() 97 | */ 98 | public int colorWeekend() { 99 | return theme.colorWeekend(); 100 | } 101 | 102 | /** 103 | * @see DPTheme#colorHoliday() 104 | */ 105 | public int colorHoliday() { 106 | return theme.colorHoliday(); 107 | } 108 | 109 | /** 110 | * @see DPCNTheme#colorL() 111 | */ 112 | public int colorL() { 113 | if (theme instanceof DPCNTheme) { 114 | return ((DPCNTheme) theme).colorL(); 115 | } 116 | return 0; 117 | } 118 | 119 | /** 120 | * @see DPCNTheme#colorDeferred() 121 | */ 122 | public int colorDeferred() { 123 | if (theme instanceof DPCNTheme) { 124 | return ((DPCNTheme) theme).colorDeferred(); 125 | } 126 | return 0; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /DatePicker/src/main/java/cn/aigestudio/datepicker/bizs/themes/DPTheme.java: -------------------------------------------------------------------------------- 1 | package cn.aigestudio.datepicker.bizs.themes; 2 | 3 | /** 4 | * 主题抽象类 5 | * 你可以继承该类定制自己的颜色主题 6 | * 7 | * Abstract class of theme 8 | * You can extends this class to implement your own theme colors 9 | * 10 | * @author AigeStudio 2015-06-30 11 | */ 12 | public abstract class DPTheme { 13 | /** 14 | * 月视图背景色 15 | * 16 | * Color of MonthView's background 17 | * 18 | * @return 16进制颜色值 hex color 19 | */ 20 | public abstract int colorBG(); 21 | 22 | /** 23 | * 背景圆颜色 24 | * 25 | * Color of MonthView's selected circle 26 | * 27 | * @return 16进制颜色值 hex color 28 | */ 29 | public abstract int colorBGCircle(); 30 | 31 | /** 32 | * 标题栏背景色 33 | * 34 | * Color of TitleBar's background 35 | * 36 | * @return 16进制颜色值 hex color 37 | */ 38 | public abstract int colorTitleBG(); 39 | 40 | /** 41 | * 标题栏文本颜色 42 | * 43 | * Color of TitleBar text 44 | * 45 | * @return 16进制颜色值 hex color 46 | */ 47 | public abstract int colorTitle(); 48 | 49 | /** 50 | * 今天的背景色 51 | * 52 | * Color of Today's background 53 | * 54 | * @return 16进制颜色值 hex color 55 | */ 56 | public abstract int colorToday(); 57 | 58 | /** 59 | * 公历文本颜色 60 | * 61 | * Color of Gregorian text 62 | * 63 | * @return 16进制颜色值 hex color 64 | */ 65 | public abstract int colorG(); 66 | 67 | /** 68 | * 节日文本颜色 69 | * 70 | * Color of Festival text 71 | * 72 | * @return 16进制颜色值 hex color 73 | */ 74 | public abstract int colorF(); 75 | 76 | /** 77 | * 周末文本颜色 78 | * 79 | * Color of Weekend text 80 | * 81 | * @return 16进制颜色值 hex color 82 | */ 83 | public abstract int colorWeekend(); 84 | 85 | /** 86 | * 假期文本颜色 87 | * 88 | * Color of Holiday text 89 | * 90 | * @return 16进制颜色值 hex color 91 | */ 92 | public abstract int colorHoliday(); 93 | } 94 | -------------------------------------------------------------------------------- /DatePicker/src/main/java/cn/aigestudio/datepicker/cons/DPMode.java: -------------------------------------------------------------------------------- 1 | package cn.aigestudio.datepicker.cons; 2 | 3 | /** 4 | * 日期选择模式 5 | * 支持单选和多选和展示 6 | * Date select mode 7 | * Support SINGLE or MULTIPLE or Display only. 8 | * 9 | * @author AigeStudio 2015-07-02 10 | */ 11 | public enum DPMode { 12 | SINGLE, MULTIPLE, NONE 13 | } -------------------------------------------------------------------------------- /DatePicker/src/main/java/cn/aigestudio/datepicker/entities/DPInfo.java: -------------------------------------------------------------------------------- 1 | package cn.aigestudio.datepicker.entities; 2 | 3 | /** 4 | * 日历数据实体 5 | * 封装日历绘制时需要的数据 6 | * 7 | * Entity of calendar 8 | * 9 | * @author AigeStudio 2015-03-26 10 | */ 11 | public class DPInfo { 12 | public String strG, strF; 13 | public boolean isHoliday; 14 | public boolean isToday, isWeekend; 15 | public boolean isSolarTerms, isFestival, isDeferred; 16 | public boolean isDecorBG; 17 | public boolean isDecorTL, isDecorT, isDecorTR, isDecorL, isDecorR; 18 | } -------------------------------------------------------------------------------- /DatePicker/src/main/java/cn/aigestudio/datepicker/utils/DataUtils.java: -------------------------------------------------------------------------------- 1 | package cn.aigestudio.datepicker.utils; 2 | 3 | /** 4 | * 数组操作工具类 5 | * 6 | * Utils of data operation 7 | * 8 | * @author AigeStudio 2015-07-22 9 | */ 10 | public final class DataUtils { 11 | /** 12 | * 一维数组转换为二维数组 13 | * 14 | * @param src ... 15 | * @param row ... 16 | * @param column ... 17 | * @return ... 18 | */ 19 | public static String[][] arraysConvert(String[] src, int row, int column) { 20 | String[][] tmp = new String[row][column]; 21 | for (int i = 0; i < row; i++) { 22 | tmp[i] = new String[column]; 23 | System.arraycopy(src, i * column, tmp[i], 0, column); 24 | } 25 | return tmp; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /DatePicker/src/main/java/cn/aigestudio/datepicker/utils/MeasureUtil.java: -------------------------------------------------------------------------------- 1 | package cn.aigestudio.datepicker.utils; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * 测量工具类 7 | * 8 | * Util of measure. 9 | * 10 | * @author AigeStudio 2015-03-26 11 | */ 12 | public final class MeasureUtil { 13 | public static int dp2px(Context context, float dp) { 14 | float scale = context.getResources().getDisplayMetrics().density; 15 | return (int) (dp * scale + 0.5f); 16 | } 17 | 18 | public static int px2dp(Context context, float px) { 19 | float scale = context.getResources().getDisplayMetrics().density; 20 | return (int) (px / scale + 0.5f); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /DatePicker/src/main/java/cn/aigestudio/datepicker/views/DatePicker.java: -------------------------------------------------------------------------------- 1 | package cn.aigestudio.datepicker.views; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.util.TypedValue; 6 | import android.view.Gravity; 7 | import android.view.View; 8 | import android.widget.LinearLayout; 9 | import android.widget.RelativeLayout; 10 | import android.widget.TextView; 11 | 12 | import java.util.List; 13 | 14 | import cn.aigestudio.datepicker.bizs.decors.DPDecor; 15 | import cn.aigestudio.datepicker.bizs.languages.DPLManager; 16 | import cn.aigestudio.datepicker.bizs.themes.DPTManager; 17 | import cn.aigestudio.datepicker.cons.DPMode; 18 | import cn.aigestudio.datepicker.utils.MeasureUtil; 19 | 20 | import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; 21 | 22 | /** 23 | * DatePicker 24 | * 25 | * @author AigeStudio 2015-06-29 26 | */ 27 | public class DatePicker extends LinearLayout { 28 | private DPTManager mTManager;// 主题管理器 29 | private DPLManager mLManager;// 语言管理器 30 | 31 | private MonthView monthView;// 月视图 32 | private TextView tvYear, tvMonth;// 年份 月份显示 33 | private TextView tvEnsure;// 确定按钮显示 34 | 35 | 36 | private OnDateSelectedListener onDateSelectedListener;// 日期多选后监听 37 | 38 | /** 39 | * 日期单选监听器 40 | */ 41 | public interface OnDatePickedListener { 42 | void onDatePicked(String date); 43 | } 44 | 45 | /** 46 | * 日期多选监听器 47 | */ 48 | public interface OnDateSelectedListener { 49 | void onDateSelected(List date); 50 | } 51 | 52 | public DatePicker(Context context) { 53 | this(context, null); 54 | } 55 | 56 | public DatePicker(Context context, AttributeSet attrs) { 57 | super(context, attrs); 58 | mTManager = DPTManager.getInstance(); 59 | mLManager = DPLManager.getInstance(); 60 | 61 | // 设置排列方向为竖向 62 | setOrientation(VERTICAL); 63 | 64 | LayoutParams llParams = 65 | new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); 66 | 67 | // 标题栏根布局 68 | RelativeLayout rlTitle = new RelativeLayout(context); 69 | rlTitle.setBackgroundColor(mTManager.colorTitleBG()); 70 | int rlTitlePadding = MeasureUtil.dp2px(context, 10); 71 | rlTitle.setPadding(rlTitlePadding, rlTitlePadding, rlTitlePadding, rlTitlePadding); 72 | 73 | // 周视图根布局 74 | LinearLayout llWeek = new LinearLayout(context); 75 | llWeek.setBackgroundColor(mTManager.colorTitleBG()); 76 | llWeek.setOrientation(HORIZONTAL); 77 | int llWeekPadding = MeasureUtil.dp2px(context, 5); 78 | llWeek.setPadding(0, llWeekPadding, 0, llWeekPadding); 79 | LayoutParams lpWeek = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT); 80 | lpWeek.weight = 1; 81 | 82 | // 标题栏子元素布局参数 83 | RelativeLayout.LayoutParams lpYear = 84 | new RelativeLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT); 85 | lpYear.addRule(RelativeLayout.CENTER_VERTICAL); 86 | RelativeLayout.LayoutParams lpMonth = 87 | new RelativeLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT); 88 | lpMonth.addRule(RelativeLayout.CENTER_IN_PARENT); 89 | RelativeLayout.LayoutParams lpEnsure = 90 | new RelativeLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT); 91 | lpEnsure.addRule(RelativeLayout.CENTER_VERTICAL); 92 | lpEnsure.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); 93 | 94 | // --------------------------------------------------------------------------------标题栏 95 | // 年份显示 96 | tvYear = new TextView(context); 97 | tvYear.setText("2015"); 98 | tvYear.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); 99 | tvYear.setTextColor(mTManager.colorTitle()); 100 | 101 | // 月份显示 102 | tvMonth = new TextView(context); 103 | tvMonth.setText("六月"); 104 | tvMonth.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); 105 | tvMonth.setTextColor(mTManager.colorTitle()); 106 | 107 | // 确定显示 108 | tvEnsure = new TextView(context); 109 | tvEnsure.setText(mLManager.titleEnsure()); 110 | tvEnsure.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); 111 | tvEnsure.setTextColor(mTManager.colorTitle()); 112 | tvEnsure.setOnClickListener(new OnClickListener() { 113 | @Override 114 | public void onClick(View v) { 115 | if (null != onDateSelectedListener) { 116 | onDateSelectedListener.onDateSelected(monthView.getDateSelected()); 117 | } 118 | } 119 | }); 120 | 121 | rlTitle.addView(tvYear, lpYear); 122 | rlTitle.addView(tvMonth, lpMonth); 123 | rlTitle.addView(tvEnsure, lpEnsure); 124 | 125 | addView(rlTitle, llParams); 126 | 127 | // --------------------------------------------------------------------------------周视图 128 | for (int i = 0; i < mLManager.titleWeek().length; i++) { 129 | TextView tvWeek = new TextView(context); 130 | tvWeek.setText(mLManager.titleWeek()[i]); 131 | tvWeek.setGravity(Gravity.CENTER); 132 | tvWeek.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); 133 | tvWeek.setTextColor(mTManager.colorTitle()); 134 | llWeek.addView(tvWeek, lpWeek); 135 | } 136 | addView(llWeek, llParams); 137 | 138 | // ------------------------------------------------------------------------------------月视图 139 | monthView = new MonthView(context); 140 | monthView.setOnDateChangeListener(new MonthView.OnDateChangeListener() { 141 | @Override 142 | public void onMonthChange(int month) { 143 | tvMonth.setText(mLManager.titleMonth()[month - 1]); 144 | } 145 | 146 | @Override 147 | public void onYearChange(int year) { 148 | String tmp = String.valueOf(year); 149 | if (tmp.startsWith("-")) { 150 | tmp = tmp.replace("-", mLManager.titleBC()); 151 | } 152 | tvYear.setText(tmp); 153 | } 154 | }); 155 | addView(monthView, llParams); 156 | } 157 | 158 | /** 159 | * 设置初始化年月日期 160 | * 161 | * @param year ... 162 | * @param month ... 163 | */ 164 | public void setDate(int year, int month) { 165 | if (month < 1) { 166 | month = 1; 167 | } 168 | if (month > 12) { 169 | month = 12; 170 | } 171 | monthView.setDate(year, month); 172 | } 173 | 174 | public void setDPDecor(DPDecor decor) { 175 | monthView.setDPDecor(decor); 176 | } 177 | 178 | /** 179 | * 设置日期选择模式 180 | * 181 | * @param mode ... 182 | */ 183 | public void setMode(DPMode mode) { 184 | if (mode != DPMode.MULTIPLE) { 185 | tvEnsure.setVisibility(GONE); 186 | } 187 | monthView.setDPMode(mode); 188 | } 189 | 190 | public void setFestivalDisplay(boolean isFestivalDisplay) { 191 | monthView.setFestivalDisplay(isFestivalDisplay); 192 | } 193 | 194 | public void setTodayDisplay(boolean isTodayDisplay) { 195 | monthView.setTodayDisplay(isTodayDisplay); 196 | } 197 | 198 | public void setHolidayDisplay(boolean isHolidayDisplay) { 199 | monthView.setHolidayDisplay(isHolidayDisplay); 200 | } 201 | 202 | public void setDeferredDisplay(boolean isDeferredDisplay) { 203 | monthView.setDeferredDisplay(isDeferredDisplay); 204 | } 205 | 206 | /** 207 | * 设置单选监听器 208 | * 209 | * @param onDatePickedListener ... 210 | */ 211 | public void setOnDatePickedListener(OnDatePickedListener onDatePickedListener) { 212 | if (monthView.getDPMode() != DPMode.SINGLE) { 213 | throw new RuntimeException( 214 | "Current DPMode does not SINGLE! Please call setMode set DPMode to SINGLE!"); 215 | } 216 | monthView.setOnDatePickedListener(onDatePickedListener); 217 | } 218 | 219 | /** 220 | * 设置多选监听器 221 | * 222 | * @param onDateSelectedListener ... 223 | */ 224 | public void setOnDateSelectedListener(OnDateSelectedListener onDateSelectedListener) { 225 | if (monthView.getDPMode() != DPMode.MULTIPLE) { 226 | throw new RuntimeException( 227 | "Current DPMode does not MULTIPLE! Please call setMode set DPMode to MULTIPLE!"); 228 | } 229 | this.onDateSelectedListener = onDateSelectedListener; 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /DatePicker/src/main/java/cn/aigestudio/datepicker/views/MonthView.java: -------------------------------------------------------------------------------- 1 | package cn.aigestudio.datepicker.views; 2 | 3 | import android.animation.Animator; 4 | import android.animation.AnimatorListenerAdapter; 5 | import android.animation.AnimatorSet; 6 | import android.animation.ObjectAnimator; 7 | import android.animation.ValueAnimator; 8 | import android.annotation.TargetApi; 9 | import android.content.Context; 10 | import android.graphics.Canvas; 11 | import android.graphics.Paint; 12 | import android.graphics.Rect; 13 | import android.graphics.Region; 14 | import android.graphics.drawable.ShapeDrawable; 15 | import android.graphics.drawable.shapes.OvalShape; 16 | import android.os.Build; 17 | import android.os.Parcelable; 18 | import android.text.TextUtils; 19 | import android.view.MotionEvent; 20 | import android.view.View; 21 | import android.view.animation.AccelerateInterpolator; 22 | import android.view.animation.DecelerateInterpolator; 23 | import android.widget.Scroller; 24 | 25 | import java.util.ArrayList; 26 | import java.util.Arrays; 27 | import java.util.HashMap; 28 | import java.util.List; 29 | import java.util.Map; 30 | 31 | import cn.aigestudio.datepicker.bizs.calendars.DPCManager; 32 | import cn.aigestudio.datepicker.bizs.decors.DPDecor; 33 | import cn.aigestudio.datepicker.bizs.themes.DPTManager; 34 | import cn.aigestudio.datepicker.cons.DPMode; 35 | import cn.aigestudio.datepicker.entities.DPInfo; 36 | 37 | /** 38 | * MonthView 39 | * 40 | * @author AigeStudio 2015-06-29 41 | */ 42 | public class MonthView extends View { 43 | private final Region[][] MONTH_REGIONS_4 = new Region[4][7]; 44 | private final Region[][] MONTH_REGIONS_5 = new Region[5][7]; 45 | private final Region[][] MONTH_REGIONS_6 = new Region[6][7]; 46 | 47 | private final DPInfo[][] INFO_4 = new DPInfo[4][7]; 48 | private final DPInfo[][] INFO_5 = new DPInfo[5][7]; 49 | private final DPInfo[][] INFO_6 = new DPInfo[6][7]; 50 | 51 | private final Map> REGION_SELECTED = new HashMap<>(); 52 | 53 | private DPCManager mCManager = DPCManager.getInstance(); 54 | private DPTManager mTManager = DPTManager.getInstance(); 55 | 56 | protected Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG | 57 | Paint.LINEAR_TEXT_FLAG); 58 | private Scroller mScroller; 59 | private DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator(); 60 | private AccelerateInterpolator accelerateInterpolator = new AccelerateInterpolator(); 61 | private OnDateChangeListener onDateChangeListener; 62 | private DatePicker.OnDatePickedListener onDatePickedListener; 63 | private ScaleAnimationListener scaleAnimationListener; 64 | 65 | private DPMode mDPMode = DPMode.MULTIPLE; 66 | private SlideMode mSlideMode; 67 | private DPDecor mDPDecor; 68 | 69 | private int circleRadius; 70 | private int indexYear, indexMonth; 71 | private int centerYear, centerMonth; 72 | private int leftYear, leftMonth; 73 | private int rightYear, rightMonth; 74 | private int topYear, topMonth; 75 | private int bottomYear, bottomMonth; 76 | private int width, height; 77 | private int sizeDecor, sizeDecor2x, sizeDecor3x; 78 | private int lastPointX, lastPointY; 79 | private int lastMoveX, lastMoveY; 80 | private int criticalWidth, criticalHeight; 81 | private int animZoomOut1, animZoomIn1, animZoomOut2; 82 | 83 | private float sizeTextGregorian, sizeTextFestival; 84 | private float offsetYFestival1, offsetYFestival2; 85 | 86 | private boolean isNewEvent, 87 | isFestivalDisplay = true, 88 | isHolidayDisplay = true, 89 | isTodayDisplay = true, 90 | isDeferredDisplay = true; 91 | 92 | private Map cirApr = new HashMap<>(); 93 | private Map cirDpr = new HashMap<>(); 94 | 95 | private List dateSelected = new ArrayList<>(); 96 | 97 | public MonthView(Context context) { 98 | super(context); 99 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 100 | scaleAnimationListener = new ScaleAnimationListener(); 101 | } 102 | mScroller = new Scroller(context); 103 | mPaint.setTextAlign(Paint.Align.CENTER); 104 | } 105 | 106 | @Override 107 | protected Parcelable onSaveInstanceState() { 108 | return super.onSaveInstanceState(); 109 | } 110 | 111 | @Override 112 | protected void onRestoreInstanceState(Parcelable state) { 113 | super.onRestoreInstanceState(state); 114 | } 115 | 116 | @Override 117 | public void computeScroll() { 118 | if (mScroller.computeScrollOffset()) { 119 | scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); 120 | invalidate(); 121 | } else { 122 | requestLayout(); 123 | } 124 | } 125 | 126 | @Override 127 | public boolean onTouchEvent(MotionEvent event) { 128 | switch (event.getAction()) { 129 | case MotionEvent.ACTION_DOWN: 130 | mScroller.forceFinished(true); 131 | mSlideMode = null; 132 | isNewEvent = true; 133 | lastPointX = (int) event.getX(); 134 | lastPointY = (int) event.getY(); 135 | break; 136 | case MotionEvent.ACTION_MOVE: 137 | if (isNewEvent) { 138 | if (Math.abs(lastPointX - event.getX()) > 100) { 139 | mSlideMode = SlideMode.HOR; 140 | isNewEvent = false; 141 | } else if (Math.abs(lastPointY - event.getY()) > 50) { 142 | mSlideMode = SlideMode.VER; 143 | isNewEvent = false; 144 | } 145 | } 146 | if (mSlideMode == SlideMode.HOR) { 147 | int totalMoveX = (int) (lastPointX - event.getX()) + lastMoveX; 148 | smoothScrollTo(totalMoveX, indexYear * height); 149 | } else if (mSlideMode == SlideMode.VER) { 150 | int totalMoveY = (int) (lastPointY - event.getY()) + lastMoveY; 151 | smoothScrollTo(width * indexMonth, totalMoveY); 152 | } 153 | break; 154 | case MotionEvent.ACTION_UP: 155 | if (mSlideMode == SlideMode.VER) { 156 | if (Math.abs(lastPointY - event.getY()) > 25) { 157 | if (lastPointY < event.getY()) { 158 | if (Math.abs(lastPointY - event.getY()) >= criticalHeight) { 159 | indexYear--; 160 | centerYear = centerYear - 1; 161 | } 162 | } else if (lastPointY > event.getY()) { 163 | if (Math.abs(lastPointY - event.getY()) >= criticalHeight) { 164 | indexYear++; 165 | centerYear = centerYear + 1; 166 | } 167 | } 168 | buildRegion(); 169 | computeDate(); 170 | smoothScrollTo(width * indexMonth, height * indexYear); 171 | lastMoveY = height * indexYear; 172 | } else { 173 | defineRegion((int) event.getX(), (int) event.getY()); 174 | } 175 | } else if (mSlideMode == SlideMode.HOR) { 176 | if (Math.abs(lastPointX - event.getX()) > 25) { 177 | if (lastPointX > event.getX() && 178 | Math.abs(lastPointX - event.getX()) >= criticalWidth) { 179 | indexMonth++; 180 | centerMonth = (centerMonth + 1) % 13; 181 | if (centerMonth == 0) { 182 | centerMonth = 1; 183 | centerYear++; 184 | } 185 | } else if (lastPointX < event.getX() && 186 | Math.abs(lastPointX - event.getX()) >= criticalWidth) { 187 | indexMonth--; 188 | centerMonth = (centerMonth - 1) % 12; 189 | if (centerMonth == 0) { 190 | centerMonth = 12; 191 | centerYear--; 192 | } 193 | } 194 | buildRegion(); 195 | computeDate(); 196 | smoothScrollTo(width * indexMonth, indexYear * height); 197 | lastMoveX = width * indexMonth; 198 | } else { 199 | defineRegion((int) event.getX(), (int) event.getY()); 200 | } 201 | } else { 202 | defineRegion((int) event.getX(), (int) event.getY()); 203 | } 204 | break; 205 | } 206 | return true; 207 | } 208 | 209 | @Override 210 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 211 | int measureWidth = MeasureSpec.getSize(widthMeasureSpec); 212 | setMeasuredDimension(measureWidth, (int) (measureWidth * 6F / 7F)); 213 | } 214 | 215 | @Override 216 | protected void onSizeChanged(int w, int h, int oldW, int oldH) { 217 | width = w; 218 | height = h; 219 | 220 | criticalWidth = (int) (1F / 5F * width); 221 | criticalHeight = (int) (1F / 5F * height); 222 | 223 | int cellW = (int) (w / 7F); 224 | int cellH4 = (int) (h / 4F); 225 | int cellH5 = (int) (h / 5F); 226 | int cellH6 = (int) (h / 6F); 227 | 228 | circleRadius = cellW; 229 | 230 | animZoomOut1 = (int) (cellW * 1.2F); 231 | animZoomIn1 = (int) (cellW * 0.8F); 232 | animZoomOut2 = (int) (cellW * 1.1F); 233 | 234 | sizeDecor = (int) (cellW / 3F); 235 | sizeDecor2x = sizeDecor * 2; 236 | sizeDecor3x = sizeDecor * 3; 237 | 238 | sizeTextGregorian = width / 20F; 239 | mPaint.setTextSize(sizeTextGregorian); 240 | 241 | float heightGregorian = mPaint.getFontMetrics().bottom - mPaint.getFontMetrics().top; 242 | sizeTextFestival = width / 40F; 243 | mPaint.setTextSize(sizeTextFestival); 244 | 245 | float heightFestival = mPaint.getFontMetrics().bottom - mPaint.getFontMetrics().top; 246 | offsetYFestival1 = (((Math.abs(mPaint.ascent() + mPaint.descent())) / 2F) + 247 | heightFestival / 2F + heightGregorian / 2F) / 2F; 248 | offsetYFestival2 = offsetYFestival1 * 2F; 249 | 250 | for (int i = 0; i < MONTH_REGIONS_4.length; i++) { 251 | for (int j = 0; j < MONTH_REGIONS_4[i].length; j++) { 252 | Region region = new Region(); 253 | region.set((j * cellW), (i * cellH4), cellW + (j * cellW), 254 | cellW + (i * cellH4)); 255 | MONTH_REGIONS_4[i][j] = region; 256 | } 257 | } 258 | for (int i = 0; i < MONTH_REGIONS_5.length; i++) { 259 | for (int j = 0; j < MONTH_REGIONS_5[i].length; j++) { 260 | Region region = new Region(); 261 | region.set((j * cellW), (i * cellH5), cellW + (j * cellW), 262 | cellW + (i * cellH5)); 263 | MONTH_REGIONS_5[i][j] = region; 264 | } 265 | } 266 | for (int i = 0; i < MONTH_REGIONS_6.length; i++) { 267 | for (int j = 0; j < MONTH_REGIONS_6[i].length; j++) { 268 | Region region = new Region(); 269 | region.set((j * cellW), (i * cellH6), cellW + (j * cellW), 270 | cellW + (i * cellH6)); 271 | MONTH_REGIONS_6[i][j] = region; 272 | } 273 | } 274 | } 275 | 276 | @Override 277 | protected void onDraw(Canvas canvas) { 278 | canvas.drawColor(mTManager.colorBG()); 279 | 280 | draw(canvas, width * indexMonth, (indexYear - 1) * height, topYear, topMonth); 281 | draw(canvas, width * (indexMonth - 1), height * indexYear, leftYear, leftMonth); 282 | draw(canvas, width * indexMonth, indexYear * height, centerYear, centerMonth); 283 | draw(canvas, width * (indexMonth + 1), height * indexYear, rightYear, rightMonth); 284 | draw(canvas, width * indexMonth, (indexYear + 1) * height, bottomYear, bottomMonth); 285 | 286 | drawBGCircle(canvas); 287 | } 288 | 289 | private void drawBGCircle(Canvas canvas) { 290 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 291 | for (String s : cirDpr.keySet()) { 292 | BGCircle circle = cirDpr.get(s); 293 | drawBGCircle(canvas, circle); 294 | } 295 | } 296 | for (String s : cirApr.keySet()) { 297 | BGCircle circle = cirApr.get(s); 298 | drawBGCircle(canvas, circle); 299 | } 300 | } 301 | 302 | private void drawBGCircle(Canvas canvas, BGCircle circle) { 303 | canvas.save(); 304 | canvas.translate(circle.getX() - circle.getRadius() / 2, 305 | circle.getY() - circle.getRadius() / 2); 306 | circle.getShape().getShape().resize(circle.getRadius(), circle.getRadius()); 307 | circle.getShape().draw(canvas); 308 | canvas.restore(); 309 | } 310 | 311 | private void draw(Canvas canvas, int x, int y, int year, int month) { 312 | canvas.save(); 313 | canvas.translate(x, y); 314 | DPInfo[][] info = mCManager.obtainDPInfo(year, month); 315 | DPInfo[][] result; 316 | Region[][] tmp; 317 | if (TextUtils.isEmpty(info[4][0].strG)) { 318 | tmp = MONTH_REGIONS_4; 319 | arrayClear(INFO_4); 320 | result = arrayCopy(info, INFO_4); 321 | } else if (TextUtils.isEmpty(info[5][0].strG)) { 322 | tmp = MONTH_REGIONS_5; 323 | arrayClear(INFO_5); 324 | result = arrayCopy(info, INFO_5); 325 | } else { 326 | tmp = MONTH_REGIONS_6; 327 | arrayClear(INFO_6); 328 | result = arrayCopy(info, INFO_6); 329 | } 330 | for (int i = 0; i < result.length; i++) { 331 | for (int j = 0; j < result[i].length; j++) { 332 | draw(canvas, tmp[i][j].getBounds(), info[i][j]); 333 | } 334 | } 335 | canvas.restore(); 336 | } 337 | 338 | private void draw(Canvas canvas, Rect rect, DPInfo info) { 339 | drawBG(canvas, rect, info); 340 | drawGregorian(canvas, rect, info.strG, info.isWeekend); 341 | if (isFestivalDisplay) drawFestival(canvas, rect, info.strF, info.isFestival); 342 | drawDecor(canvas, rect, info); 343 | } 344 | 345 | private void drawBG(Canvas canvas, Rect rect, DPInfo info) { 346 | if (null != mDPDecor && info.isDecorBG) { 347 | mDPDecor.drawDecorBG(canvas, rect, mPaint, 348 | centerYear + "-" + centerMonth + "-" + info.strG); 349 | } 350 | if (info.isToday && isTodayDisplay) { 351 | drawBGToday(canvas, rect); 352 | } else { 353 | if (isHolidayDisplay) drawBGHoliday(canvas, rect, info.isHoliday); 354 | if (isDeferredDisplay) drawBGDeferred(canvas, rect, info.isDeferred); 355 | } 356 | } 357 | 358 | private void drawBGToday(Canvas canvas, Rect rect) { 359 | mPaint.setColor(mTManager.colorToday()); 360 | canvas.drawCircle(rect.centerX(), rect.centerY(), circleRadius / 2F, mPaint); 361 | } 362 | 363 | private void drawBGHoliday(Canvas canvas, Rect rect, boolean isHoliday) { 364 | mPaint.setColor(mTManager.colorHoliday()); 365 | if (isHoliday) canvas.drawCircle(rect.centerX(), rect.centerY(), circleRadius / 2F, mPaint); 366 | } 367 | 368 | private void drawBGDeferred(Canvas canvas, Rect rect, boolean isDeferred) { 369 | mPaint.setColor(mTManager.colorDeferred()); 370 | if (isDeferred) 371 | canvas.drawCircle(rect.centerX(), rect.centerY(), circleRadius / 2F, mPaint); 372 | } 373 | 374 | private void drawGregorian(Canvas canvas, Rect rect, String str, boolean isWeekend) { 375 | mPaint.setTextSize(sizeTextGregorian); 376 | if (isWeekend) { 377 | mPaint.setColor(mTManager.colorWeekend()); 378 | } else { 379 | mPaint.setColor(mTManager.colorG()); 380 | } 381 | float y = rect.centerY(); 382 | if (!isFestivalDisplay) 383 | y = rect.centerY() + Math.abs(mPaint.ascent()) - (mPaint.descent() - mPaint.ascent()) / 2F; 384 | canvas.drawText(str, rect.centerX(), y, mPaint); 385 | } 386 | 387 | private void drawFestival(Canvas canvas, Rect rect, String str, boolean isFestival) { 388 | mPaint.setTextSize(sizeTextFestival); 389 | if (isFestival) { 390 | mPaint.setColor(mTManager.colorF()); 391 | } else { 392 | mPaint.setColor(mTManager.colorL()); 393 | } 394 | if (str.contains("&")) { 395 | String[] s = str.split("&"); 396 | String str1 = s[0]; 397 | if (mPaint.measureText(str1) > rect.width()) { 398 | float ch = mPaint.measureText(str1, 0, 1); 399 | int length = (int) (rect.width() / ch); 400 | canvas.drawText(str1.substring(0, length), rect.centerX(), 401 | rect.centerY() + offsetYFestival1, mPaint); 402 | canvas.drawText(str1.substring(length), rect.centerX(), 403 | rect.centerY() + offsetYFestival2, mPaint); 404 | } else { 405 | canvas.drawText(str1, rect.centerX(), 406 | rect.centerY() + offsetYFestival1, mPaint); 407 | String str2 = s[1]; 408 | if (mPaint.measureText(str2) < rect.width()) { 409 | canvas.drawText(str2, rect.centerX(), 410 | rect.centerY() + offsetYFestival2, mPaint); 411 | } 412 | } 413 | } else { 414 | if (mPaint.measureText(str) > rect.width()) { 415 | float ch = 0.0F; 416 | for (char c : str.toCharArray()) { 417 | float tmp = mPaint.measureText(String.valueOf(c)); 418 | if (tmp > ch) { 419 | ch = tmp; 420 | } 421 | } 422 | int length = (int) (rect.width() / ch); 423 | canvas.drawText(str.substring(0, length), rect.centerX(), 424 | rect.centerY() + offsetYFestival1, mPaint); 425 | canvas.drawText(str.substring(length), rect.centerX(), 426 | rect.centerY() + offsetYFestival2, mPaint); 427 | } else { 428 | canvas.drawText(str, rect.centerX(), 429 | rect.centerY() + offsetYFestival1, mPaint); 430 | } 431 | } 432 | } 433 | 434 | private void drawDecor(Canvas canvas, Rect rect, DPInfo info) { 435 | if (!TextUtils.isEmpty(info.strG)) { 436 | String data = centerYear + "-" + centerMonth + "-" + info.strG; 437 | if (null != mDPDecor && info.isDecorTL) { 438 | canvas.save(); 439 | canvas.clipRect(rect.left, rect.top, rect.left + sizeDecor, rect.top + sizeDecor); 440 | mDPDecor.drawDecorTL(canvas, canvas.getClipBounds(), mPaint, data); 441 | canvas.restore(); 442 | } 443 | if (null != mDPDecor && info.isDecorT) { 444 | canvas.save(); 445 | canvas.clipRect(rect.left + sizeDecor, rect.top, rect.left + sizeDecor2x, 446 | rect.top + sizeDecor); 447 | mDPDecor.drawDecorT(canvas, canvas.getClipBounds(), mPaint, data); 448 | canvas.restore(); 449 | } 450 | if (null != mDPDecor && info.isDecorTR) { 451 | canvas.save(); 452 | canvas.clipRect(rect.left + sizeDecor2x, rect.top, rect.left + sizeDecor3x, 453 | rect.top + sizeDecor); 454 | mDPDecor.drawDecorTR(canvas, canvas.getClipBounds(), mPaint, data); 455 | canvas.restore(); 456 | } 457 | if (null != mDPDecor && info.isDecorL) { 458 | canvas.save(); 459 | canvas.clipRect(rect.left, rect.top + sizeDecor, rect.left + sizeDecor, 460 | rect.top + sizeDecor2x); 461 | mDPDecor.drawDecorL(canvas, canvas.getClipBounds(), mPaint, data); 462 | canvas.restore(); 463 | } 464 | if (null != mDPDecor && info.isDecorR) { 465 | canvas.save(); 466 | canvas.clipRect(rect.left + sizeDecor2x, rect.top + sizeDecor, 467 | rect.left + sizeDecor3x, rect.top + sizeDecor2x); 468 | mDPDecor.drawDecorR(canvas, canvas.getClipBounds(), mPaint, data); 469 | canvas.restore(); 470 | } 471 | } 472 | } 473 | 474 | List getDateSelected() { 475 | return dateSelected; 476 | } 477 | 478 | void setOnDateChangeListener(OnDateChangeListener onDateChangeListener) { 479 | this.onDateChangeListener = onDateChangeListener; 480 | } 481 | 482 | public void setOnDatePickedListener(DatePicker.OnDatePickedListener onDatePickedListener) { 483 | this.onDatePickedListener = onDatePickedListener; 484 | } 485 | 486 | void setDPMode(DPMode mode) { 487 | this.mDPMode = mode; 488 | } 489 | 490 | void setDPDecor(DPDecor decor) { 491 | this.mDPDecor = decor; 492 | } 493 | 494 | DPMode getDPMode() { 495 | return mDPMode; 496 | } 497 | 498 | void setDate(int year, int month) { 499 | centerYear = year; 500 | centerMonth = month; 501 | indexYear = 0; 502 | indexMonth = 0; 503 | buildRegion(); 504 | computeDate(); 505 | requestLayout(); 506 | invalidate(); 507 | } 508 | 509 | void setFestivalDisplay(boolean isFestivalDisplay) { 510 | this.isFestivalDisplay = isFestivalDisplay; 511 | } 512 | 513 | void setTodayDisplay(boolean isTodayDisplay) { 514 | this.isTodayDisplay = isTodayDisplay; 515 | } 516 | 517 | void setHolidayDisplay(boolean isHolidayDisplay) { 518 | this.isHolidayDisplay = isHolidayDisplay; 519 | } 520 | 521 | void setDeferredDisplay(boolean isDeferredDisplay) { 522 | this.isDeferredDisplay = isDeferredDisplay; 523 | } 524 | 525 | private void smoothScrollTo(int fx, int fy) { 526 | int dx = fx - mScroller.getFinalX(); 527 | int dy = fy - mScroller.getFinalY(); 528 | smoothScrollBy(dx, dy); 529 | } 530 | 531 | private void smoothScrollBy(int dx, int dy) { 532 | mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy, 500); 533 | invalidate(); 534 | } 535 | 536 | private BGCircle createCircle(float x, float y) { 537 | OvalShape circle = new OvalShape(); 538 | circle.resize(0, 0); 539 | ShapeDrawable drawable = new ShapeDrawable(circle); 540 | BGCircle circle1 = new BGCircle(drawable); 541 | circle1.setX(x); 542 | circle1.setY(y); 543 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { 544 | circle1.setRadius(circleRadius); 545 | } 546 | drawable.getPaint().setColor(mTManager.colorBGCircle()); 547 | return circle1; 548 | } 549 | 550 | private void buildRegion() { 551 | String key = indexYear + ":" + indexMonth; 552 | if (!REGION_SELECTED.containsKey(key)) { 553 | REGION_SELECTED.put(key, new ArrayList()); 554 | } 555 | } 556 | 557 | private void arrayClear(DPInfo[][] info) { 558 | for (DPInfo[] anInfo : info) { 559 | Arrays.fill(anInfo, null); 560 | } 561 | } 562 | 563 | private DPInfo[][] arrayCopy(DPInfo[][] src, DPInfo[][] dst) { 564 | for (int i = 0; i < dst.length; i++) { 565 | System.arraycopy(src[i], 0, dst[i], 0, dst[i].length); 566 | } 567 | return dst; 568 | } 569 | 570 | private void defineRegion(int x, int y) { 571 | DPInfo[][] info = mCManager.obtainDPInfo(centerYear, centerMonth); 572 | Region[][] tmp; 573 | if (TextUtils.isEmpty(info[4][0].strG)) { 574 | tmp = MONTH_REGIONS_4; 575 | } else if (TextUtils.isEmpty(info[5][0].strG)) { 576 | tmp = MONTH_REGIONS_5; 577 | } else { 578 | tmp = MONTH_REGIONS_6; 579 | } 580 | for (int i = 0; i < tmp.length; i++) { 581 | for (int j = 0; j < tmp[i].length; j++) { 582 | Region region = tmp[i][j]; 583 | if (TextUtils.isEmpty(mCManager.obtainDPInfo(centerYear, centerMonth)[i][j].strG)) { 584 | continue; 585 | } 586 | if (region.contains(x, y)) { 587 | List regions = REGION_SELECTED.get(indexYear + ":" + indexMonth); 588 | if (mDPMode == DPMode.SINGLE) { 589 | cirApr.clear(); 590 | regions.add(region); 591 | final String date = centerYear + "-" + centerMonth + "-" + 592 | mCManager.obtainDPInfo(centerYear, centerMonth)[i][j].strG; 593 | BGCircle circle = createCircle( 594 | region.getBounds().centerX() + indexMonth * width, 595 | region.getBounds().centerY() + indexYear * height); 596 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 597 | ValueAnimator animScale1 = 598 | ObjectAnimator.ofInt(circle, "radius", 0, animZoomOut1); 599 | animScale1.setDuration(250); 600 | animScale1.setInterpolator(decelerateInterpolator); 601 | animScale1.addUpdateListener(scaleAnimationListener); 602 | 603 | ValueAnimator animScale2 = 604 | ObjectAnimator.ofInt(circle, "radius", animZoomOut1, animZoomIn1); 605 | animScale2.setDuration(100); 606 | animScale2.setInterpolator(accelerateInterpolator); 607 | animScale2.addUpdateListener(scaleAnimationListener); 608 | 609 | ValueAnimator animScale3 = 610 | ObjectAnimator.ofInt(circle, "radius", animZoomIn1, animZoomOut2); 611 | animScale3.setDuration(150); 612 | animScale3.setInterpolator(decelerateInterpolator); 613 | animScale3.addUpdateListener(scaleAnimationListener); 614 | 615 | ValueAnimator animScale4 = 616 | ObjectAnimator.ofInt(circle, "radius", animZoomOut2, circleRadius); 617 | animScale4.setDuration(50); 618 | animScale4.setInterpolator(accelerateInterpolator); 619 | animScale4.addUpdateListener(scaleAnimationListener); 620 | 621 | AnimatorSet animSet = new AnimatorSet(); 622 | animSet.playSequentially(animScale1, animScale2, animScale3, animScale4); 623 | animSet.addListener(new AnimatorListenerAdapter() { 624 | @Override 625 | public void onAnimationEnd(Animator animation) { 626 | if (null != onDatePickedListener) { 627 | onDatePickedListener.onDatePicked(date); 628 | } 629 | } 630 | }); 631 | animSet.start(); 632 | } 633 | cirApr.put(date, circle); 634 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { 635 | invalidate(); 636 | if (null != onDatePickedListener) { 637 | onDatePickedListener.onDatePicked(date); 638 | } 639 | } 640 | } else if (mDPMode == DPMode.MULTIPLE) { 641 | if (regions.contains(region)) { 642 | regions.remove(region); 643 | } else { 644 | regions.add(region); 645 | } 646 | final String date = centerYear + "-" + centerMonth + "-" + 647 | mCManager.obtainDPInfo(centerYear, centerMonth)[i][j].strG; 648 | if (dateSelected.contains(date)) { 649 | dateSelected.remove(date); 650 | BGCircle circle = cirApr.get(date); 651 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 652 | ValueAnimator animScale = ObjectAnimator.ofInt(circle, "radius", circleRadius, 0); 653 | animScale.setDuration(250); 654 | animScale.setInterpolator(accelerateInterpolator); 655 | animScale.addUpdateListener(scaleAnimationListener); 656 | animScale.addListener(new AnimatorListenerAdapter() { 657 | @Override 658 | public void onAnimationEnd(Animator animation) { 659 | cirDpr.remove(date); 660 | } 661 | }); 662 | animScale.start(); 663 | cirDpr.put(date, circle); 664 | } 665 | cirApr.remove(date); 666 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { 667 | invalidate(); 668 | } 669 | } else { 670 | dateSelected.add(date); 671 | BGCircle circle = createCircle( 672 | region.getBounds().centerX() + indexMonth * width, 673 | region.getBounds().centerY() + indexYear * height); 674 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 675 | ValueAnimator animScale1 = 676 | ObjectAnimator.ofInt(circle, "radius", 0, animZoomOut1); 677 | animScale1.setDuration(250); 678 | animScale1.setInterpolator(decelerateInterpolator); 679 | animScale1.addUpdateListener(scaleAnimationListener); 680 | 681 | ValueAnimator animScale2 = 682 | ObjectAnimator.ofInt(circle, "radius", animZoomOut1, animZoomIn1); 683 | animScale2.setDuration(100); 684 | animScale2.setInterpolator(accelerateInterpolator); 685 | animScale2.addUpdateListener(scaleAnimationListener); 686 | 687 | ValueAnimator animScale3 = 688 | ObjectAnimator.ofInt(circle, "radius", animZoomIn1, animZoomOut2); 689 | animScale3.setDuration(150); 690 | animScale3.setInterpolator(decelerateInterpolator); 691 | animScale3.addUpdateListener(scaleAnimationListener); 692 | 693 | ValueAnimator animScale4 = 694 | ObjectAnimator.ofInt(circle, "radius", animZoomOut2, circleRadius); 695 | animScale4.setDuration(50); 696 | animScale4.setInterpolator(accelerateInterpolator); 697 | animScale4.addUpdateListener(scaleAnimationListener); 698 | 699 | AnimatorSet animSet = new AnimatorSet(); 700 | animSet.playSequentially(animScale1, animScale2, animScale3, animScale4); 701 | animSet.start(); 702 | } 703 | cirApr.put(date, circle); 704 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { 705 | invalidate(); 706 | } 707 | } 708 | } else if (mDPMode == DPMode.NONE) { 709 | if (regions.contains(region)) { 710 | regions.remove(region); 711 | } else { 712 | regions.add(region); 713 | } 714 | final String date = centerYear + "-" + centerMonth + "-" + 715 | mCManager.obtainDPInfo(centerYear, centerMonth)[i][j].strG; 716 | if (dateSelected.contains(date)) { 717 | dateSelected.remove(date); 718 | } else { 719 | dateSelected.add(date); 720 | } 721 | } 722 | } 723 | } 724 | } 725 | } 726 | 727 | private void computeDate() { 728 | rightYear = leftYear = centerYear; 729 | topYear = centerYear - 1; 730 | bottomYear = centerYear + 1; 731 | 732 | topMonth = centerMonth; 733 | bottomMonth = centerMonth; 734 | 735 | rightMonth = centerMonth + 1; 736 | leftMonth = centerMonth - 1; 737 | 738 | if (centerMonth == 12) { 739 | rightYear++; 740 | rightMonth = 1; 741 | } 742 | if (centerMonth == 1) { 743 | leftYear--; 744 | leftMonth = 12; 745 | } 746 | if (null != onDateChangeListener) { 747 | onDateChangeListener.onYearChange(centerYear); 748 | onDateChangeListener.onMonthChange(centerMonth); 749 | } 750 | } 751 | 752 | interface OnDateChangeListener { 753 | void onMonthChange(int month); 754 | 755 | void onYearChange(int year); 756 | } 757 | 758 | private enum SlideMode { 759 | VER, 760 | HOR 761 | } 762 | 763 | private class BGCircle { 764 | private float x, y; 765 | private int radius; 766 | 767 | private ShapeDrawable shape; 768 | 769 | public BGCircle(ShapeDrawable shape) { 770 | this.shape = shape; 771 | } 772 | 773 | public float getX() { 774 | return x; 775 | } 776 | 777 | public void setX(float x) { 778 | this.x = x; 779 | } 780 | 781 | public float getY() { 782 | return y; 783 | } 784 | 785 | public void setY(float y) { 786 | this.y = y; 787 | } 788 | 789 | public int getRadius() { 790 | return radius; 791 | } 792 | 793 | public void setRadius(int radius) { 794 | this.radius = radius; 795 | } 796 | 797 | public ShapeDrawable getShape() { 798 | return shape; 799 | } 800 | 801 | public void setShape(ShapeDrawable shape) { 802 | this.shape = shape; 803 | } 804 | } 805 | 806 | @TargetApi(Build.VERSION_CODES.HONEYCOMB) 807 | private class ScaleAnimationListener implements ValueAnimator.AnimatorUpdateListener { 808 | @Override 809 | public void onAnimationUpdate(ValueAnimator animation) { 810 | MonthView.this.invalidate(); 811 | } 812 | } 813 | } 814 | -------------------------------------------------------------------------------- /Decor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devaige/DatePicker/7a4153d2cb17d20c31c6aa83b989f37d4c724bec/Decor.jpg -------------------------------------------------------------------------------- /DecorExample.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devaige/DatePicker/7a4153d2cb17d20c31c6aa83b989f37d4c724bec/DecorExample.jpg -------------------------------------------------------------------------------- /Demo/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /Demo/Demo.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /Demo/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 21 5 | buildToolsVersion "21.1.2" 6 | 7 | defaultConfig { 8 | applicationId "cn.aigestudio.datepicker.demo" 9 | minSdkVersion 11 10 | targetSdkVersion 21 11 | versionCode 4 12 | versionName "2.0.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | // compile 'cn.aigestudio.datepicker:DatePicker:2.0.1' 25 | compile project(':DatePicker') 26 | } 27 | -------------------------------------------------------------------------------- /Demo/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 e:\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 | -------------------------------------------------------------------------------- /Demo/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Demo/src/main/java/cn/aigestudio/datepicker/demo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package cn.aigestudio.datepicker.demo; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.Paint; 8 | import android.graphics.Rect; 9 | import android.os.Bundle; 10 | import android.view.Gravity; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.view.Window; 14 | import android.view.WindowManager; 15 | import android.widget.Button; 16 | import android.widget.Toast; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Iterator; 20 | import java.util.List; 21 | 22 | import cn.aigestudio.datepicker.bizs.calendars.DPCManager; 23 | import cn.aigestudio.datepicker.bizs.decors.DPDecor; 24 | import cn.aigestudio.datepicker.cons.DPMode; 25 | import cn.aigestudio.datepicker.views.DatePicker; 26 | 27 | /** 28 | * Demo应用的主Activity 29 | * The main activity of demo 30 | * 31 | * @author AigeStudio 2015-03-26 32 | */ 33 | public class MainActivity extends Activity { 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | requestWindowFeature(Window.FEATURE_NO_TITLE); 39 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 40 | setContentView(R.layout.activity_main); 41 | 42 | // // 默认多选模式 43 | // DatePicker picker = (DatePicker) findViewById(R.id.main_dp); 44 | // picker.setDate(2015, 7); 45 | // picker.setOnDateSelectedListener(new DatePicker.OnDateSelectedListener() { 46 | // @Override 47 | // public void onDateSelected(List date) { 48 | // String result = ""; 49 | // Iterator iterator = date.iterator(); 50 | // while (iterator.hasNext()) { 51 | // result += iterator.next(); 52 | // if (iterator.hasNext()) { 53 | // result += "\n"; 54 | // } 55 | // } 56 | // Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show(); 57 | // } 58 | // }); 59 | 60 | // 自定义背景绘制示例 Example of custom date's background 61 | // List tmp = new ArrayList<>(); 62 | // tmp.add("2015-7-1"); 63 | // tmp.add("2015-7-8"); 64 | // tmp.add("2015-7-16"); 65 | // DPCManager.getInstance().setDecorBG(tmp); 66 | // 67 | // DatePicker picker = (DatePicker) findViewById(R.id.main_dp); 68 | // picker.setDate(2015, 7); 69 | // picker.setDPDecor(new DPDecor() { 70 | // @Override 71 | // public void drawDecorBG(Canvas canvas, Rect rect, Paint paint) { 72 | // paint.setColor(Color.RED); 73 | // canvas.drawCircle(rect.centerX(), rect.centerY(), rect.width() / 2F, paint); 74 | // } 75 | // }); 76 | // picker.setOnDateSelectedListener(new DatePicker.OnDateSelectedListener() { 77 | // @Override 78 | // public void onDateSelected(List date) { 79 | // String result = ""; 80 | // Iterator iterator = date.iterator(); 81 | // while (iterator.hasNext()) { 82 | // result += iterator.next(); 83 | // if (iterator.hasNext()) { 84 | // result += "\n"; 85 | // } 86 | // } 87 | // Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show(); 88 | // } 89 | // }); 90 | 91 | // 自定义前景装饰物绘制示例 Example of custom date's foreground decor 92 | List tmpTL = new ArrayList<>(); 93 | tmpTL.add("2015-10-5"); 94 | tmpTL.add("2015-10-6"); 95 | tmpTL.add("2015-10-7"); 96 | tmpTL.add("2015-10-8"); 97 | tmpTL.add("2015-10-9"); 98 | tmpTL.add("2015-10-10"); 99 | tmpTL.add("2015-10-11"); 100 | DPCManager.getInstance().setDecorTL(tmpTL); 101 | 102 | List tmpTR = new ArrayList<>(); 103 | tmpTR.add("2015-10-10"); 104 | tmpTR.add("2015-10-11"); 105 | tmpTR.add("2015-10-12"); 106 | tmpTR.add("2015-10-13"); 107 | tmpTR.add("2015-10-14"); 108 | tmpTR.add("2015-10-15"); 109 | tmpTR.add("2015-10-16"); 110 | DPCManager.getInstance().setDecorTR(tmpTR); 111 | 112 | DatePicker picker = (DatePicker) findViewById(R.id.main_dp); 113 | picker.setDate(2015, 10); 114 | picker.setFestivalDisplay(false); 115 | picker.setTodayDisplay(false); 116 | picker.setHolidayDisplay(false); 117 | picker.setDeferredDisplay(false); 118 | picker.setMode(DPMode.NONE); 119 | picker.setDPDecor(new DPDecor() { 120 | @Override 121 | public void drawDecorTL(Canvas canvas, Rect rect, Paint paint, String data) { 122 | super.drawDecorTL(canvas, rect, paint, data); 123 | switch (data) { 124 | case "2015-10-5": 125 | case "2015-10-7": 126 | case "2015-10-9": 127 | case "2015-10-11": 128 | paint.setColor(Color.GREEN); 129 | canvas.drawRect(rect, paint); 130 | break; 131 | default: 132 | paint.setColor(Color.RED); 133 | canvas.drawCircle(rect.centerX(), rect.centerY(), rect.width() / 2, paint); 134 | break; 135 | } 136 | } 137 | 138 | @Override 139 | public void drawDecorTR(Canvas canvas, Rect rect, Paint paint, String data) { 140 | super.drawDecorTR(canvas, rect, paint, data); 141 | switch (data) { 142 | case "2015-10-10": 143 | case "2015-10-11": 144 | case "2015-10-12": 145 | paint.setColor(Color.BLUE); 146 | canvas.drawCircle(rect.centerX(), rect.centerY(), rect.width() / 2, paint); 147 | break; 148 | default: 149 | paint.setColor(Color.YELLOW); 150 | canvas.drawRect(rect, paint); 151 | break; 152 | } 153 | } 154 | }); 155 | // picker.setOnDateSelectedListener(new DatePicker.OnDateSelectedListener() { 156 | // @Override 157 | // public void onDateSelected(List date) { 158 | // String result = ""; 159 | // Iterator iterator = date.iterator(); 160 | // while (iterator.hasNext()) { 161 | // result += iterator.next(); 162 | // if (iterator.hasNext()) { 163 | // result += "\n"; 164 | // } 165 | // } 166 | // Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show(); 167 | // } 168 | // }); 169 | 170 | // 对话框下的DatePicker示例 Example in dialog 171 | Button btnPick = (Button) findViewById(R.id.main_btn); 172 | btnPick.setOnClickListener(new View.OnClickListener() { 173 | @Override 174 | public void onClick(View v) { 175 | final AlertDialog dialog = new AlertDialog.Builder(MainActivity.this).create(); 176 | dialog.show(); 177 | DatePicker picker = new DatePicker(MainActivity.this); 178 | picker.setDate(2015, 10); 179 | picker.setMode(DPMode.SINGLE); 180 | picker.setOnDatePickedListener(new DatePicker.OnDatePickedListener() { 181 | @Override 182 | public void onDatePicked(String date) { 183 | Toast.makeText(MainActivity.this, date, Toast.LENGTH_LONG).show(); 184 | dialog.dismiss(); 185 | } 186 | }); 187 | ViewGroup.LayoutParams params = new ViewGroup.LayoutParams( 188 | ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); 189 | dialog.getWindow().setContentView(picker, params); 190 | dialog.getWindow().setGravity(Gravity.CENTER); 191 | } 192 | }); 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /Demo/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devaige/DatePicker/7a4153d2cb17d20c31c6aa83b989f37d4c724bec/Demo/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /Demo/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devaige/DatePicker/7a4153d2cb17d20c31c6aa83b989f37d4c724bec/Demo/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /Demo/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devaige/DatePicker/7a4153d2cb17d20c31c6aa83b989f37d4c724bec/Demo/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Demo/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devaige/DatePicker/7a4153d2cb17d20c31c6aa83b989f37d4c724bec/Demo/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Demo/src/main/res/drawable-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devaige/DatePicker/7a4153d2cb17d20c31c6aa83b989f37d4c724bec/Demo/src/main/res/drawable-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /Demo/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 12 | 13 |