当你的才华还撑不起你的梦想时,你只能一直前进!

【无私分享】干货!!!一个炫酷的自定义日历控件,摆脱日历时间选择烦恼,纯福利~

最近公司项目中有一个按日期查看信息的功能,楼主本想用之前用的wheelView将就使用的,不过产品经理有个新要求,就是点击按钮弹出的日期选择对话框必须显示农历节假日,周几什么的。这可就难为人了,倘若使用之前的滚动时间选择器,无疑是难以实现的,楼主辗转反侧,冥思苦想,却不得正果。

对于楼主之前的wheelView写的滚动时间选择器,大家可以看看,分为了4种方式,还有仿QQ的发送消息哦:http://www.cnblogs.com/liushilin/p/5749481.html

 

好吧,去网上下了几个OA系统一用就有了idea,突然想到手机自带的日历~~,oh,year,日历就有这功能,瞧瞧,我靠,这个东西,咋做。

仔细一瞧,似乎用GridView可以实现,额,二话不说就开干。折腾了半天都没弄好,而且界面贼丑,并且特别是国历和公历上面如何一一对应呢?

遇上楼主上google科普了一番,发现网上自定义日历不少,可是没有楼主想要的,好不容易找到一个功能齐全,可惜代码调了半天也用不起,好吧,只能一步一个脚印慢慢做。

终于功夫不负有心人,最终楼主还是弄出来一个雏形。

额,对,基本实现了日历功能,并能自动定位当前日期以及本月和非本月日期显示的不同,而且支持左右滑动哦~~

额,有图有真相。

 

最后,楼主把Demo分离了出来,供大家分享参阅。

view包下几个东西。

1)CalendarGridView.java

 1 package com.example.nanchen.mydateviewdemo.view;
 2 
 3 import android.content.Context;
 4 import android.graphics.Color;
 5 import android.view.Gravity;
 6 import android.widget.GridView;
 7 import android.widget.LinearLayout;
 8 
 9 /**
10  *
11  * 用于生成日历展示的GridView布局
12  *
13  * @author nanchen
14  * @date 16-8-10 上午11:35
15  */
16 public class CalendarGridView extends GridView {
17     /**
18      * 当前操作的上下文对象
19      */
20     private Context mContext;
21 
22     /**
23      * CalendarGridView 构造器
24      *
25      * @param context
26      *            当前操作的上下文对象
27      */
28     public CalendarGridView(Context context) {
29         super(context);
30         mContext = context;
31         initGirdView();
32     }
33 
34     /**
35      * 初始化gridView 控件的布局
36      */
37     private void initGirdView() {
38         LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
39                 LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
40         setLayoutParams(params);
41         setNumColumns(7);// 设置每行列数
42         setGravity(Gravity.CENTER_VERTICAL);// 位置居中
43         setVerticalSpacing(1);// 垂直间隔
44         setHorizontalSpacing(1);// 水平间隔
45         setBackgroundColor(Color.argb(0xff, 0xe3, 0xee, 0xf4));
46 
47         int i = mContext.getResources().getDisplayMetrics().widthPixels / 7;
48         int j = mContext.getResources().getDisplayMetrics().widthPixels
49                 - (i * 7);
50         int x = j / 2;
51         setPadding(x, 0, 0, 0);// 居中
52     }
53 }

2)CalendarGridViewAdapter,java

  1 package com.example.nanchen.mydateviewdemo.view;
  2 
  3 import android.content.Context;
  4 import android.graphics.Color;
  5 import android.util.Log;
  6 import android.view.Gravity;
  7 import android.view.View;
  8 import android.view.ViewGroup;
  9 import android.view.ViewGroup.LayoutParams;
 10 import android.widget.BaseAdapter;
 11 import android.widget.LinearLayout;
 12 import android.widget.TextView;
 13 
 14 import com.example.nanchen.mydateviewdemo.R;
 15 
 16 import java.text.SimpleDateFormat;
 17 import java.util.ArrayList;
 18 import java.util.Calendar;
 19 import java.util.Date;
 20 import java.util.List;
 21 import java.util.Locale;
 22 
 23 /**
 24  * @author nanchen
 25  * @date 16-8-10 上午11:35
 26  */
 27 public class CalendarGridViewAdapter extends BaseAdapter {
 28     /** 日历item中默认id从0xff0000开始 */
 29     private final static int DEFAULT_ID = 0xff0000;
 30     private Calendar calStartDate = Calendar.getInstance();// 当前显示的日历
 31     private Calendar calSelected = Calendar.getInstance(); // 选择的日历
 32 
 33     /** 标注的日期 */
 34     private List<Date> markDates;
 35 
 36     private Context mContext;
 37 
 38     private Calendar calToday = Calendar.getInstance(); // 今日
 39     private ArrayList<Date> titles;
 40 
 41     private ArrayList<java.util.Date> getDates() {
 42 
 43         UpdateStartDateForMonth();
 44 
 45         ArrayList<java.util.Date> alArrayList = new ArrayList<java.util.Date>();
 46 
 47         for (int i = 1; i <= 42; i++) {
 48             alArrayList.add(calStartDate.getTime());
 49             calStartDate.add(Calendar.DAY_OF_MONTH, 1);
 50         }
 51 
 52         return alArrayList;
 53     }
 54 
 55     // construct
 56     public CalendarGridViewAdapter(Context context, Calendar cal, List<Date> dates) {
 57         calStartDate = cal;
 58         this.mContext = context;
 59         titles = getDates();
 60         this.markDates = dates;
 61     }
 62 
 63     public CalendarGridViewAdapter(Context context) {
 64         this.mContext = context;
 65     }
 66 
 67     @Override
 68     public int getCount() {
 69         return titles.size();
 70     }
 71 
 72     @Override
 73     public Object getItem(int position) {
 74         return titles.get(position);
 75     }
 76 
 77     @Override
 78     public long getItemId(int position) {
 79         return position;
 80     }
 81 
 82     @SuppressWarnings("deprecation")
 83     @Override
 84     public View getView(int position, View convertView, ViewGroup parent) {
 85         // 整个Item
 86         LinearLayout itemLayout = new LinearLayout(mContext);
 87         itemLayout.setId(position + DEFAULT_ID);
 88         itemLayout.setGravity(Gravity.CENTER);
 89         itemLayout.setOrientation(1);
 90         itemLayout.setBackgroundColor(Color.WHITE);
 91 
 92         Date myDate = (Date) getItem(position);
 93         itemLayout.setTag(myDate);
 94         Calendar calCalendar = Calendar.getInstance();
 95         calCalendar.setTime(myDate);
 96 
 97         // 显示日期day
 98         TextView textDay = new TextView(mContext);// 日期
 99         LinearLayout.LayoutParams text_params = new LinearLayout.LayoutParams(
100                 LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
101         textDay.setGravity(Gravity.CENTER_HORIZONTAL);
102         int day = myDate.getDate(); // 日期
103         textDay.setTextSize(15);
104         textDay.setText(String.valueOf(day));
105         textDay.setId(position + DEFAULT_ID);
106         itemLayout.addView(textDay, text_params);
107 
108         // 显示农历
109         TextView chineseDay = new TextView(mContext);
110         LinearLayout.LayoutParams chinese_params = new LinearLayout.LayoutParams(
111                 LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
112         chineseDay.setGravity(Gravity.CENTER_HORIZONTAL);
113         chineseDay.setTextSize(12);
114         CalendarUtil calendarUtil = new CalendarUtil(calCalendar);
115         chineseDay.setText(calendarUtil.toString());
116         itemLayout.addView(chineseDay, chinese_params);//把农历添加在公历下面
117 
118         SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
119         Log.e("flag",equalsDate(calToday.getTime(),myDate)+sdf.format(calToday.getTime()));
120         // 如果是当前日期则显示不同颜色
121         if (equalsDate(calToday.getTime(), myDate)) {//假定当前是8月10日
122             itemLayout.setBackgroundColor(mContext.getResources().getColor(R.color.date_today_text_color));
123         }
124 
125 //        Log.e("tag",equalsDate(myDate,calToday.getTime())+sdf.format(myDate));
126 
127         Log.e("tag",myDate.getMonth()+"---"+sdf.format(myDate));
128         Log.e("tag",calToday.getTime().getMonth()+"====="+sdf.format(calToday.getTime()));
129         if (equalsMonth(myDate,calStartDate.getTime())){
130             textDay.setTextColor(mContext.getResources().getColor(R.color.date_text_color));
131             chineseDay.setTextColor(mContext.getResources().getColor(R.color.date_text_color));
132         }else{
133             textDay.setTextColor(mContext.getResources().getColor(R.color.date_pre_color));
134             chineseDay.setTextColor(mContext.getResources().getColor(R.color.date_pre_color));
135         }
136 
137 
138 
139 
140 
141 
164         /** 设置标注日期颜色 */
165         if (markDates != null) {
166             final SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日", Locale.CHINA);
167             for (Date date : markDates) {
168                 if (format.format(myDate).equals(format.format(date))) {
169 //                    itemLayout.setBackgroundColor(mContext.getResources().getColor(R.color.date_select_color));
170                     break;
171                 }
172             }
173         }
174         return itemLayout;
175     }
176 
177     @Override
178     public void notifyDataSetChanged() {
179         super.notifyDataSetChanged();
180     }
181 
182     @SuppressWarnings("deprecation")
183     private Boolean equalsDate(Date date1, Date date2) {
184         if (date1.getYear() == date2.getYear()
185                 && date1.getMonth() == date2.getMonth()
186                 && date1.getDate() == date2.getDate()) {
187             return true;
188         } else {
189             return false;
190         }
191     }
192     @SuppressWarnings("deprecation")
193     private boolean equalsMonth(Date date1,Date date2){
194         if (date1.getMonth() == date2.getMonth()-1){
195             return true;
196         }
197         return false;
198     }
199 
200     // 根据改变的日期更新日历
201     // 填充日历控件用
202     private void UpdateStartDateForMonth() {
203         calStartDate.set(Calendar.DATE, 1); // 设置成当月第一天
204 
205         // 星期一是2 星期天是1 填充剩余天数
206         int iDay = 0;
207         int iFirstDayOfWeek = Calendar.MONDAY;
208         int iStartDay = iFirstDayOfWeek;
209         if (iStartDay == Calendar.MONDAY) {
210             iDay = calStartDate.get(Calendar.DAY_OF_WEEK) - Calendar.MONDAY;
211             if (iDay < 0)
212                 iDay = 6;
213         }
214         if (iStartDay == Calendar.SUNDAY) {
215             iDay = calStartDate.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY;
216             if (iDay < 0)
217                 iDay = 6;
218         }
219         calStartDate.add(Calendar.DAY_OF_WEEK, -iDay);
220         calStartDate.add(Calendar.DAY_OF_MONTH, -1);// 周日第一位
221     }
222 
223     public void setSelectedDate(Calendar cal) {
224         calSelected = cal;
225     }
226 
227 }

3)

CalendarUtil
  1 package com.example.nanchen.mydateviewdemo.view;
  2 
  3 import java.text.ParseException;
  4 import java.text.SimpleDateFormat;
  5 import java.util.Calendar;
  6 import java.util.Date;
  7 
  8 /**
  9  * @author nanchen
 10  * @date 16-8-10 上午11:36
 11  */
 12 public class CalendarUtil {
 13     /**
 14      * 用于保存中文的月份
 15      */
 16     private final static String CHINESE_NUMBER[] = { "一", "二", "三", "四", "五",
 17             "六", "七", "八", "九", "十", "十一", "腊" };
 18 
 19     /**
 20      * 用于保存展示周几使用
 21      */
 22     private final static String WEEK_NUMBER[] = { "日", "一", "二", "三", "四", "五",
 23             "六" };
 24 
 25     private final static long[] LUNAR_INFO = new long[] { 0x04bd8, 0x04ae0,
 26             0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0,
 27             0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540,
 28             0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5,
 29             0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970,
 30             0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3,
 31             0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0,
 32             0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0,
 33             0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8,
 34             0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570,
 35             0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5,
 36             0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0,
 37             0x195a6, 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50,
 38             0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0,
 39             0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0,
 40             0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7,
 41             0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50,
 42             0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954,
 43             0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260,
 44             0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0,
 45             0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0,
 46             0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20,
 47             0x0ada0 };
 48 
 49     /**
 50      * 转换为2012年11月22日格式
 51      */
 52     private static SimpleDateFormat chineseDateFormat = new SimpleDateFormat(
 53             "yyyy年MM月dd日");
 54     /**
 55      * 转换为2012-11-22格式
 56      */
 57     private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
 58             "yyyy-MM-dd");
 59 
 60     /**
 61      * 计算得到农历的年份
 62      */
 63     private int mLuchYear;
 64     /**
 65      * 计算得到农历的月份
 66      */
 67     private int mLuchMonth;
 68 
 69     /**
 70      * 计算得到农历的日期
 71      */
 72     private int mLuchDay;
 73 
 74     /**
 75      * 用于标识是事为闰年
 76      */
 77     private boolean isLoap;
 78 
 79     /**
 80      * 用于记录当前处理的时间
 81      */
 82     private Calendar mCurrenCalendar;
 83 
 84     /**
 85      * 传回农历 year年的总天数
 86      *
 87      * @param year
 88      *            将要计算的年份
 89      * @return 返回传入年份的总天数
 90      */
 91     private static int yearDays(int year) {
 92         int i, sum = 348;
 93         for (i = 0x8000; i > 0x8; i >>= 1) {
 94             if ((LUNAR_INFO[year - 1900] & i) != 0)
 95                 sum += 1;
 96         }
 97         return (sum + leapDays(year));
 98     }
 99 
100     /**
101      * 传回农历 year年闰月的天数
102      *
103      * @param year
104      *            将要计算的年份
105      * @return 返回 农历 year年闰月的天数
106      */
107     private static int leapDays(int year) {
108         if (leapMonth(year) != 0) {
109             if ((LUNAR_INFO[year - 1900] & 0x10000) != 0)
110                 return 30;
111             else
112                 return 29;
113         } else
114             return 0;
115     }
116 
117     /**
118      * 传回农历 year年闰哪个月 1-12 , 没闰传回 0
119      *
120      * @param year
121      *            将要计算的年份
122      * @return 传回农历 year年闰哪个月 1-12 , 没闰传回 0
123      */
124     private static int leapMonth(int year) {
125         return (int) (LUNAR_INFO[year - 1900] & 0xf);
126     }
127 
128     /**
129      * 传回农历 year年month月的总天数
130      *
131      * @param year
132      *            将要计算的年份
133      * @param month
134      *            将要计算的月份
135      * @return 传回农历 year年month月的总天数
136      */
137     private static int monthDays(int year, int month) {
138         if ((LUNAR_INFO[year - 1900] & (0x10000 >> month)) == 0)
139             return 29;
140         else
141             return 30;
142     }
143 
144     /**
145      * 传回农历 y年的生肖
146      *
147      * @return 传回农历 y年的生肖
148      */
149     public String animalsYear() {
150         final String[] Animals = new String[] { "鼠", "牛", "虎", "兔", "龙", "蛇",
151                 "马", "羊", "猴", "鸡", "狗", "猪" };
152         return Animals[(mLuchYear - 4) % 12];
153     }
154 
155     // ====== 传入 月日的offset 传回干支, 0=甲子
156     private static String cyclicalm(int num) {
157         final String[] Gan = new String[] { "甲", "乙", "丙", "丁", "戊", "己", "庚",
158                 "辛", "壬", "癸" };
159         final String[] Zhi = new String[] { "子", "丑", "寅", "卯", "辰", "巳", "午",
160                 "未", "申", "酉", "戌", "亥" };
161 
162         return (Gan[num % 10] + Zhi[num % 12]);
163     }
164 
165     // ====== 传入 offset 传回干支, 0=甲子
166     public String cyclical() {
167         int num = mLuchYear - 1900 + 36;
168         return (cyclicalm(num));
169     }
170 
171     /**
172      * 传出y年m月d日对应的农历. yearCyl3:农历年与1864的相差数 ? monCyl4:从1900年1月31日以来,闰月数
173      * dayCyl5:与1900年1月31日相差的天数,再加40 ?
174      *
175      * @param cal
176      * @return
177      */
178     public CalendarUtil(Calendar cal) {
179         mCurrenCalendar = cal;
180         int leapMonth = 0;
181         Date baseDate = null;
182         try {
183             baseDate = chineseDateFormat.parse("1900年1月31日");
184         } catch (ParseException e) {
185             e.printStackTrace(); // To change body of catch statement use
186             // Options | File Templates.
187         }
188 
189         // 求出和1900年1月31日相差的天数
190         int offset = (int) ((cal.getTime().getTime() - baseDate.getTime()) / 86400000L);
191         // 用offset减去每农历年的天数
192         // 计算当天是农历第几天
193         // i最终结果是农历的年份
194         // offset是当年的第几天
195         int iYear, daysOfYear = 0;
196         for (iYear = 1900; iYear < 2050 && offset > 0; iYear++) {
197             daysOfYear = yearDays(iYear);
198             offset -= daysOfYear;
199         }
200         if (offset < 0) {
201             offset += daysOfYear;
202             iYear--;
203         }
204         // 农历年份
205         mLuchYear = iYear;
206 
207         leapMonth = leapMonth(iYear); // 闰哪个月,1-12
208         isLoap = false;
209 
210         // 用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天
211         int iMonth, daysOfMonth = 0;
212         for (iMonth = 1; iMonth < 13 && offset > 0; iMonth++) {
213             // 闰月
214             if (leapMonth > 0 && iMonth == (leapMonth + 1) && !isLoap) {
215                 --iMonth;
216                 isLoap = true;
217                 daysOfMonth = leapDays(mLuchYear);
218             } else
219                 daysOfMonth = monthDays(mLuchYear, iMonth);
220 
221             offset -= daysOfMonth;
222             // 解除闰月
223             if (isLoap && iMonth == (leapMonth + 1))
224                 isLoap = false;
225             if (!isLoap) {
226             }
227         }
228         // offset为0时,并且刚才计算的月份是闰月,要校正
229         if (offset == 0 && leapMonth > 0 && iMonth == leapMonth + 1) {
230             if (isLoap) {
231                 isLoap = false;
232             } else {
233                 isLoap = true;
234                 --iMonth;
235             }
236         }
237         // offset小于0时,也要校正
238         if (offset < 0) {
239             offset += daysOfMonth;
240             --iMonth;
241 
242         }
243         mLuchMonth = iMonth;
244         mLuchDay = offset + 1;
245     }
246 
247     /**
248      * 返化成中文格式
249      *
250      * @param day
251      * @return
252      */
253     public static String getChinaDayString(int day) {
254         String chineseTen[] = { "初", "十", "廿", "卅" };
255         int n = day % 10 == 0 ? 9 : day % 10 - 1;
256         if (day > 30)
257             return "";
258         if (day == 10)
259             return "初十";
260         else
261             return chineseTen[day / 10] + CHINESE_NUMBER[n];
262     }
263 
264     /**
265      * 用于显示农历的初几这种格式
266      *
267      * @return 农历的日期
268      */
269     public String toString() {
270         String message = "";
271         // int n = mLuchDay % 10 == 0 ? 9 : mLuchDay % 10 - 1;
272         message = getChinaCalendarMsg(mLuchYear, mLuchMonth, mLuchDay);
273         if (StringUtil.isNullOrEmpty(message)) {
274             String solarMsg = new SolarTermsUtil(mCurrenCalendar)
275                     .getSolartermsMsg();
276             // 判断当前日期是否为节气
277             if (!StringUtil.isNullOrEmpty(solarMsg)) {
278                 message = solarMsg;
279             } else {
280                 /**
281                  * 判断当前日期是否为公历节日
282                  */
283                 String gremessage = new GregorianUtil(mCurrenCalendar)
284                         .getGremessage();
285                 if (!StringUtil.isNullOrEmpty(gremessage)) {
286                     message = gremessage;
287                 } else if (mLuchDay == 1) {
288                     message = CHINESE_NUMBER[mLuchMonth - 1] + "月";
289                 } else {
290                     message = getChinaDayString(mLuchDay);
291                 }
292 
293             }
294         }
295         return message;
296     }
297 
298     /**
299      * 返回农历的年月日
300      *
301      * @return 农历的年月日格式
302      */
303     public String getDay() {
304         return (isLoap ? "闰" : "") + CHINESE_NUMBER[mLuchMonth - 1] + "月"
305                 + getChinaDayString(mLuchDay);
306     }
307 
308     /**
309      * 把calendar转化为当前年月日
310      *
311      * @param calendar
312      *            Calendar
313      * @return 返回成转换好的 年月日格式
314      */
315     public static String getDay(Calendar calendar) {
316         return simpleDateFormat.format(calendar.getTime());
317     }
318 
319     /**
320      * 用于比对二个日期的大小
321      *
322      * @param compareDate
323      *            将要比对的时间
324      * @param currentDate
325      *            当前时间
326      * @return true 表示大于当前时间 false 表示小于当前时间
327      */
328     public static boolean compare(Date compareDate, Date currentDate) {
329         return chineseDateFormat.format(compareDate).compareTo(
330                 chineseDateFormat.format(currentDate)) >= 0;
331     }
332 
333     /**
334      * 获取当前周几
335      *
336      * @param calendar
337      * @return
338      */
339     public static String getWeek(Calendar calendar) {
340         return "周" + WEEK_NUMBER[calendar.get(Calendar.DAY_OF_WEEK) - 1] + "";
341     }
342 
343     /**
344      * 将当前时间转换成要展示的形式
345      *
346      * @param calendar
347      * @return
348      */
349     public static String getCurrentDay(Calendar calendar) {
350         return getDay(calendar) + " 农历" + new CalendarUtil(calendar).getDay()
351                 + " " + getWeek(calendar);
352     }
353 
354     /**
355      * 用于获取中国的传统节日
356      *
357      * @param month
358      *            农历的月
359      * @param day
360      *            农历日
361      * @return 中国传统节日
362      */
363     private String getChinaCalendarMsg(int year, int month, int day) {
364         String message = "";
365         if (((month) == 1) && day == 1) {
366             message = "春节";
367         } else if (((month) == 1) && day == 15) {
368             message = "元宵";
369         } else if (((month) == 5) && day == 5) {
370             message = "端午";
371         } else if ((month == 7) && day == 7) {
372             message = "七夕";
373         } else if (((month) == 8) && day == 15) {
374             message = "中秋";
375         } else if ((month == 9) && day == 9) {
376             message = "重阳";
377         } else if ((month == 12) && day == 8) {
378             message = "腊八";
379         } else {
380             if (month == 12) {
381                 if ((((monthDays(year, month) == 29) && day == 29))
382                         || ((((monthDays(year, month) == 30) && day == 30)))) {
383                     message = "除夕";
384                 }
385             }
386         }
387         return message;
388     }
389 }

 

4)

CalendarView
  1 package com.example.nanchen.mydateviewdemo.view;
  2 
  3 import android.annotation.SuppressLint;
  4 import android.content.Context;
  5 import android.graphics.Color;
  6 import android.text.TextUtils.TruncateAt;
  7 import android.util.AttributeSet;
  8 import android.view.GestureDetector;
  9 import android.view.GestureDetector.OnGestureListener;
 10 import android.view.Gravity;
 11 import android.view.MotionEvent;
 12 import android.view.View;
 13 import android.view.View.OnTouchListener;
 14 import android.view.animation.Animation;
 15 import android.view.animation.Animation.AnimationListener;
 16 import android.view.animation.TranslateAnimation;
 17 import android.widget.GridView;
 18 import android.widget.ImageButton;
 19 import android.widget.LinearLayout;
 20 import android.widget.RelativeLayout;
 21 import android.widget.TextView;
 22 import android.widget.ViewFlipper;
 23 
 24 import com.example.nanchen.mydateviewdemo.R;
 25 
 26 import java.util.ArrayList;
 27 import java.util.Calendar;
 28 import java.util.Date;
 29 import java.util.List;
 30 
 31 /**
 32  * @author nanchen
 33  * @date 16-8-10 上午11:40
 34  */
 35 public class CalendarView extends LinearLayout implements OnTouchListener, AnimationListener, OnGestureListener {
 36 
 37     /**
 38      * 点击日历
 39      */
 40     public interface OnCalendarViewListener {
 41         void onCalendarItemClick(CalendarView view, Date date);
 42     }
 43 
 44     /**
 45      * 顶部控件所占高度
 46      */
 47     private final static int TOP_HEIGHT = 40;
 48     /**
 49      * 日历item中默认id从0xff0000开始
 50      */
 51     private final static int DEFAULT_ID = 0xff0000;
 52 
 53     // 判断手势用
 54     private static final int SWIPE_MIN_DISTANCE = 120;
 55     private static final int SWIPE_MAX_OFF_PATH = 250;
 56     private static final int SWIPE_THRESHOLD_VELOCITY = 200;
 57 
 58     // 屏幕宽度和高度
 59     private int screenWidth;
 60 
 61     // 动画
 62     private Animation slideLeftIn;
 63     private Animation slideLeftOut;
 64     private Animation slideRightIn;
 65     private Animation slideRightOut;
 66     private ViewFlipper viewFlipper;
 67     private GestureDetector mGesture = null;
 68 
 69     /**
 70      * 上一月
 71      */
 72     private GridView gView1;
 73     /**
 74      * 当月
 75      */
 76     private GridView gView2;
 77     /**
 78      * 下一月
 79      */
 80     private GridView gView3;
 81 
 82     boolean bIsSelection = false;// 是否是选择事件发生
 83     private Calendar calStartDate = Calendar.getInstance();// 当前显示的日历
 84     private Calendar calSelected = Calendar.getInstance(); // 选择的日历
 85     private CalendarGridViewAdapter gAdapter;
 86     private CalendarGridViewAdapter gAdapter1;
 87     private CalendarGridViewAdapter gAdapter3;
 88 
 89     private LinearLayout mMainLayout;
 90     private TextView mTitle; // 显示年月
 91 
 92     private int iMonthViewCurrentMonth = 0; // 当前视图月
 93     private int iMonthViewCurrentYear = 0; // 当前视图年
 94 
 95     private static final int caltitleLayoutID = 66; // title布局ID
 96     private static final int calLayoutID = 55; // 日历布局ID
 97     private Context mContext;
 98 
 99     /**
100      * 标注日期
101      */
102     private final List<Date> markDates;
103 
104     private OnCalendarViewListener mListener;
105 
106     public CalendarView(Context context) {
107         this(context, null);
108     }
109 
110     public CalendarView(Context context, AttributeSet attrs) {
111         super(context, attrs);
112         // TODO Auto-generated constructor stub
113         mContext = context;
114         markDates = new ArrayList<>();
115         init();
116     }
117 
118     // 初始化相关工作
119     protected void init() {
120         // 得到屏幕的宽度
121         screenWidth = mContext.getResources().getDisplayMetrics().widthPixels;
122 
123         // 滑动的动画
124         slideLeftIn = new TranslateAnimation(screenWidth, 0, 0, 0);
125         slideLeftIn.setDuration(400);
126         slideLeftIn.setAnimationListener(this);
127         slideLeftOut = new TranslateAnimation(0, -screenWidth, 0, 0);
128         slideLeftOut.setDuration(400);
129         slideLeftOut.setAnimationListener(this);
130         slideRightIn = new TranslateAnimation(-screenWidth, 0, 0, 0);
131         slideRightIn.setDuration(400);
132         slideRightIn.setAnimationListener(this);
133         slideRightOut = new TranslateAnimation(0, screenWidth, 0, 0);
134         slideRightOut.setDuration(400);
135         slideRightOut.setAnimationListener(this);
136 
137         // 手势操作
138         mGesture = new GestureDetector(mContext, this);
139 
140         // 获取到当前日期
141         UpdateStartDateForMonth();
142         // 绘制界面
143         setOrientation(LinearLayout.HORIZONTAL);
144         mMainLayout = new LinearLayout(mContext);
145         LinearLayout.LayoutParams main_params = new LinearLayout.LayoutParams(
146                 LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
147         mMainLayout.setLayoutParams(main_params);
148         mMainLayout.setGravity(Gravity.CENTER_HORIZONTAL);
149         mMainLayout.setOrientation(LinearLayout.VERTICAL);
150         addView(mMainLayout);
151 
152         // 顶部控件
153         generateTopView();
154 
155         // 中间显示星期
156         generateWeekGirdView();
157 
158         // 底部显示日历
159         viewFlipper = new ViewFlipper(mContext);
160         RelativeLayout.LayoutParams fliper_params = new RelativeLayout.LayoutParams(
161                 LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
162         fliper_params.addRule(RelativeLayout.BELOW, caltitleLayoutID);
163         mMainLayout.addView(viewFlipper, fliper_params);
164         generateClaendarGirdView();
165 
166         // 最下方的一条线条
167         LinearLayout br = new LinearLayout(mContext);
168         br.setBackgroundColor(Color.argb(0xff, 0xe3, 0xee, 0xf4));
169         LinearLayout.LayoutParams params_br = new LinearLayout.LayoutParams(
170                 LayoutParams.MATCH_PARENT, 3);
171         mMainLayout.addView(br, params_br);
172     }
173 
174     /**
175      * 生成顶部控件
176      */
177     @SuppressWarnings("deprecation")
178     private void generateTopView() {
179         // 顶部显示上一个下一个,以及当前年月
180         RelativeLayout top = new RelativeLayout(mContext);
181         top.setBackgroundColor(Color.argb(0xff, 0x0e, 0x6b, 0xc2));
182         LinearLayout.LayoutParams top_params = new LinearLayout.LayoutParams(
183                 LayoutParams.MATCH_PARENT,
184                 ViewUtil.dip2px(mContext, TOP_HEIGHT));
185         top.setLayoutParams(top_params);
186         mMainLayout.addView(top);
187         // 左方按钮、中间日期显示、右方按钮
188         mTitle = new TextView(mContext);
189         android.widget.RelativeLayout.LayoutParams title_params = new android.widget.RelativeLayout.LayoutParams(
190                 android.widget.RelativeLayout.LayoutParams.MATCH_PARENT,
191                 android.widget.RelativeLayout.LayoutParams.MATCH_PARENT);
192         mTitle.setLayoutParams(title_params);
193         mTitle.setTextColor(Color.WHITE);
194         mTitle.setTextSize(18);
195         mTitle.setFocusableInTouchMode(true);
196         mTitle.setMarqueeRepeatLimit(-1);
197         mTitle.setEllipsize(TruncateAt.MARQUEE);
198         mTitle.setSingleLine(true);
199         mTitle.setGravity(Gravity.CENTER);
200         mTitle.setHorizontallyScrolling(true);
201         mTitle.setText("2014年9月");
202         top.addView(mTitle);
203 
204         // 左方按钮
205         ImageButton mLeftView = new ImageButton(mContext);
206 
218 
219         mLeftView.setBackgroundResource(R.drawable.month_pre_selector);
220         android.widget.RelativeLayout.LayoutParams leftPP = new android.widget.RelativeLayout.LayoutParams(
221                 ViewUtil.dip2px(mContext, 25), ViewUtil.dip2px(mContext, 22));
222         leftPP.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
223         leftPP.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
224         leftPP.setMargins(20, 0, 0, 0);
225         mLeftView.setLayoutParams(leftPP);
226         mLeftView.setOnClickListener(new OnClickListener() {
227 
228             @Override
229             public void onClick(View v) {
230                 // TODO Auto-generated method stub
231                 viewFlipper.setInAnimation(slideRightIn);
232                 viewFlipper.setOutAnimation(slideRightOut);
233                 viewFlipper.showPrevious();
234                 setPrevViewItem();
235             }
236         });
237         top.addView(mLeftView);
238 
239         // 右方按钮
240         ImageButton mRightView = new ImageButton(mContext);
241 
253 
254         mRightView.setBackgroundResource(R.drawable.month_next_selector);
255 
256         android.widget.RelativeLayout.LayoutParams rightPP = new android.widget.RelativeLayout.LayoutParams(
257                 ViewUtil.dip2px(mContext, 25), ViewUtil.dip2px(mContext, 22));
258         rightPP.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
259         rightPP.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
260         rightPP.setMargins(0, 0, 20, 0);
261         mRightView.setLayoutParams(rightPP);
262         mRightView.setOnClickListener(new OnClickListener() {
263 
264             @Override
265             public void onClick(View v) {
266                 // TODO Auto-generated method stub
267                 viewFlipper.setInAnimation(slideLeftIn);
268                 viewFlipper.setOutAnimation(slideLeftOut);
269                 viewFlipper.showNext();
270                 setNextViewItem();
271             }
272         });
273         top.addView(mRightView);
274     }
275 
276     /**
277      * 生成中间显示week
278      */
279     private void generateWeekGirdView() {
280         GridView gridView = new GridView(mContext);
281         LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
282                 LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
283         gridView.setLayoutParams(params);
284         gridView.setNumColumns(7);// 设置每行列数
285         gridView.setGravity(Gravity.CENTER_VERTICAL);// 位置居中
286         gridView.setVerticalSpacing(1);// 垂直间隔
287         gridView.setHorizontalSpacing(1);// 水平间隔
288         gridView.setBackgroundColor(Color.argb(0xff, 0xe3, 0xee, 0xf4));
289 
290         int i = screenWidth / 7;
291         int j = screenWidth - (i * 7);
292         int x = j / 2;
293         gridView.setPadding(x, 0, 0, 0);// 居中
294         WeekGridAdapter weekAdapter = new WeekGridAdapter(mContext);
295         gridView.setAdapter(weekAdapter);// 设置菜单Adapter
296         mMainLayout.addView(gridView);
297     }
298 
299     /**
300      * 生成底部日历
301      */
302     private void generateClaendarGirdView() {
303         Calendar tempSelected1 = Calendar.getInstance(); // 临时
304         Calendar tempSelected2 = Calendar.getInstance(); // 临时
305         Calendar tempSelected3 = Calendar.getInstance(); // 临时
306         tempSelected1.setTime(calStartDate.getTime());
307         tempSelected2.setTime(calStartDate.getTime());
308         tempSelected3.setTime(calStartDate.getTime());
309 
310         gView1 = new CalendarGridView(mContext);
311         tempSelected1.add(Calendar.MONTH, -1);
312         gAdapter1 = new CalendarGridViewAdapter(mContext, tempSelected1,
313                 markDates);
314         gView1.setAdapter(gAdapter1);// 设置菜单Adapter
315         gView1.setId(calLayoutID);
316 
317         gView2 = new CalendarGridView(mContext);
318         gAdapter = new CalendarGridViewAdapter(mContext, tempSelected2,
319                 markDates);
320         gView2.setAdapter(gAdapter);// 设置菜单Adapter
321         gView2.setId(calLayoutID);
322 
323         gView3 = new CalendarGridView(mContext);
324         tempSelected3.add(Calendar.MONTH, 1);
325         gAdapter3 = new CalendarGridViewAdapter(mContext, tempSelected3,
326                 markDates);
327         gView3.setAdapter(gAdapter3);// 设置菜单Adapter
328         gView3.setId(calLayoutID);
329 
330         gView2.setOnTouchListener(this);
331         gView1.setOnTouchListener(this);
332         gView3.setOnTouchListener(this);
333 
334         if (viewFlipper.getChildCount() != 0) {
335             viewFlipper.removeAllViews();
336         }
337 
338         viewFlipper.addView(gView2);
339         viewFlipper.addView(gView3);
340         viewFlipper.addView(gView1);
341 
342         String title = calStartDate.get(Calendar.YEAR)
343                 + "年"
344                 + NumberHelper.LeftPad_Tow_Zero(calStartDate
345                 .get(Calendar.MONTH) + 1) + "月";
346         mTitle.setText(title);
347     }
348 
349     // 上一个月
350     private void setPrevViewItem() {
351         iMonthViewCurrentMonth--;// 当前选择月--
352         // 如果当前月为负数的话显示上一年
353         if (iMonthViewCurrentMonth == -1) {
354             iMonthViewCurrentMonth = 11;
355             iMonthViewCurrentYear--;
356         }
357         calStartDate.set(Calendar.DAY_OF_MONTH, 1); // 设置日为当月1日
358         calStartDate.set(Calendar.MONTH, iMonthViewCurrentMonth); // 设置月
359         calStartDate.set(Calendar.YEAR, iMonthViewCurrentYear); // 设置年
360     }
361 
362     // 下一个月
363     private void setNextViewItem() {
364         iMonthViewCurrentMonth++;
365         if (iMonthViewCurrentMonth == 12) {
366             iMonthViewCurrentMonth = 0;
367             iMonthViewCurrentYear++;
368         }
369         calStartDate.set(Calendar.DAY_OF_MONTH, 1);
370         calStartDate.set(Calendar.MONTH, iMonthViewCurrentMonth);
371         calStartDate.set(Calendar.YEAR, iMonthViewCurrentYear);
372     }
373 
374     // 根据改变的日期更新日历
375     // 填充日历控件用
376     private void UpdateStartDateForMonth() {
377         calStartDate.set(Calendar.DATE, 1); // 设置成当月第一天
378         iMonthViewCurrentMonth = calStartDate.get(Calendar.MONTH);// 得到当前日历显示的月
379         iMonthViewCurrentYear = calStartDate.get(Calendar.YEAR);// 得到当前日历显示的年
380 
381         // 星期一是2 星期天是1 填充剩余天数
382         int iDay = 0;
383         int iFirstDayOfWeek = Calendar.MONDAY;
384         int iStartDay = iFirstDayOfWeek;
385         if (iStartDay == Calendar.MONDAY) {
386             iDay = calStartDate.get(Calendar.DAY_OF_WEEK) - Calendar.MONDAY;
387             if (iDay < 0)
388                 iDay = 6;
389         }
390         if (iStartDay == Calendar.SUNDAY) {
391             iDay = calStartDate.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY;
392             if (iDay < 0)
393                 iDay = 6;
394         }
395         calStartDate.add(Calendar.DAY_OF_WEEK, -iDay);
396     }
397 
398     /**
399      * 设置标注的日期
400      *
401      * @param markDates
402      */
403     public void setMarkDates(List<Date> markDates) {
404         this.markDates.clear();
405         this.markDates.addAll(markDates);
406         gAdapter.notifyDataSetChanged();
407         gAdapter1.notifyDataSetChanged();
408         gAdapter3.notifyDataSetChanged();
409     }
410 
411     /**
412      * 设置点击日历监听
413      *
414      * @param listener
415      */
416     public void setOnCalendarViewListener(OnCalendarViewListener listener) {
417         this.mListener = listener;
418     }
419 
420     @Override
421     public boolean onDown(MotionEvent e) {
422         // TODO Auto-generated method stub
423         return false;
424     }
425 
426     @SuppressLint("ClickableViewAccessibility")
427     @Override
428     public boolean onTouch(View v, MotionEvent event) {
429         return mGesture.onTouchEvent(event);
430     }
431 
432     @Override
433     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
434                            float velocityY) {
435         // TODO Auto-generated method stub
436         try {
437             if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
438                 return false;
439             // right to left swipe
440             if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
441                     && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
442                 viewFlipper.setInAnimation(slideLeftIn);
443                 viewFlipper.setOutAnimation(slideLeftOut);
444                 viewFlipper.showNext();
445                 setNextViewItem();
446                 return true;
447 
448             } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
449                     && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
450                 viewFlipper.setInAnimation(slideRightIn);
451                 viewFlipper.setOutAnimation(slideRightOut);
452                 viewFlipper.showPrevious();
453                 setPrevViewItem();
454                 return true;
455 
456             }
457         } catch (Exception e) {
458             // nothing
459         }
460         return false;
461     }
462 
463     @Override
464     public void onLongPress(MotionEvent e) {
465         // TODO Auto-generated method stub
466 
467     }
468 
469     @Override
470     public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
471                             float distanceY) {
472         // TODO Auto-generated method stub
473         return false;
474     }
475 
476     @Override
477     public void onShowPress(MotionEvent e) {
478         // TODO Auto-generated method stub
479 
480     }
481 
482     @Override
483     public boolean onSingleTapUp(MotionEvent e) {
484         // TODO Auto-generated method stub
485         // 得到当前选中的是第几个单元格
486         int pos = gView2.pointToPosition((int) e.getX(), (int) e.getY());
487         LinearLayout txtDay = (LinearLayout) gView2.findViewById(pos
488                 + DEFAULT_ID);
489         if (txtDay != null) {
490             if (txtDay.getTag() != null) {
491                 Date date = (Date) txtDay.getTag();
492                 calSelected.setTime(date);
493 
494                 gAdapter.setSelectedDate(calSelected);
495                 gAdapter.notifyDataSetChanged();
496 
497                 gAdapter1.setSelectedDate(calSelected);
498                 gAdapter1.notifyDataSetChanged();
499 
500                 gAdapter3.setSelectedDate(calSelected);
501                 gAdapter3.notifyDataSetChanged();
502                 if (mListener != null)
503                     mListener.onCalendarItemClick(this, date);
504             }
505         }
506         return false;
507     }
508 
509     @Override
510     public void onAnimationEnd(Animation animation) {
511         // TODO Auto-generated method stub
512         generateClaendarGirdView();
513     }
514 
515     @Override
516     public void onAnimationRepeat(Animation animation) {
517         // TODO Auto-generated method stub
518 
519     }
520 
521     @Override
522     public void onAnimationStart(Animation animation) {
523         // TODO Auto-generated method stub
524 
525     }
526 }

 

5)

GregorianUtil
 1 package com.example.nanchen.mydateviewdemo.view;
 2 
 3 import java.util.Calendar;
 4 
 5 /**
 6  * 对公历日期的处理类
 7  * @author nanchen
 8  * @date 16-8-10 上午11:37
 9  */
10 public class GregorianUtil {
11     private final static String[][] GRE_FESTVIAL = {
12             // 一月
13             { "元旦", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
14                     "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
15             // 二月
16             { "", "", "", "", "", "", "", "", "", "", "", "", "", "情人", "", "",
17                     "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
18             // 三月
19             { "", "", "", "", "", "", "", "妇女", "", "", "", "植树", "", "", "",
20                     "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
21                     "" },
22             // 四月
23             { "愚人", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
24                     "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
25             // 五月
26             { "劳动", "", "", "青年", "", "", "", "", "", "", "", "", "", "", "",
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     private int mMonth;
52     private int mDay;
53 
54     public GregorianUtil(Calendar calendar) {
55         mMonth = calendar.get(Calendar.MONTH);
56         mDay = calendar.get(Calendar.DATE);
57     }
58 
59     public String getGremessage() {
60         return GRE_FESTVIAL[mMonth][mDay - 1];
61     }
62 }

6)

 1 package com.example.nanchen.mydateviewdemo.view;
 2 
 3 /**
 4  * @author nanchen
 5  * @date 16-8-10 上午11:38
 6  */
 7 public class NumberHelper {
 8     public static String LeftPad_Tow_Zero(int str) {
 9         java.text.DecimalFormat format = new java.text.DecimalFormat("00");
10         return format.format(str);
11     }
12 }

7)

SolarTermsUtil
  1 package com.example.nanchen.mydateviewdemo.view;
  2 
  3 import java.util.Calendar;
  4 
  5 /**
  6  * 主要用于把公历日期处理成24节气
  7  * @author nanchen
  8  * @date 16-8-10 上午11:38
  9  */
 10 public class SolarTermsUtil {
 11     /**
 12      * 计算得到公历的年份
 13      */
 14     private int gregorianYear;
 15 
 16     /**
 17      * 计算得到公历的月份
 18      */
 19     private int gregorianMonth;
 20 
 21     /**
 22      * 用于计算得到公历的日期
 23      */
 24     private int gregorianDate;
 25 
 26     private int chineseYear;
 27     private int chineseMonth;
 28     private int chineseDate;
 29 
 30     // 初始日,公历农历对应日期:
 31     // 公历 1901 年 1 月 1 日,对应农历 4598 年 11 月 11 日
 32     private static int baseYear = 1901;
 33     private static int baseMonth = 1;
 34     private static int baseDate = 1;
 35     private static int baseIndex = 0;
 36     private static int baseChineseYear = 4598 - 1;
 37     private static int baseChineseMonth = 11;
 38     private static int baseChineseDate = 11;
 39     private static char[] daysInGregorianMonth = { 31, 28, 31, 30, 31, 30, 31,
 40             31, 30, 31, 30, 31 };
 41 
 42     private int sectionalTerm;
 43     private int principleTerm;
 44 
 45     private static char[][] sectionalTermMap = {
 46             { 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 5, 5, 5, 5, 5,
 47                     5, 5, 5, 4, 5, 5 },
 48             { 5, 4, 5, 5, 5, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 3,
 49                     3, 4, 4, 3, 3, 3 },
 50             { 6, 6, 6, 7, 6, 6, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 5, 5, 5, 6, 5, 5,
 51                     5, 5, 4, 5, 5, 5, 5 },
 52             { 5, 5, 6, 6, 5, 5, 5, 6, 5, 5, 5, 5, 4, 5, 5, 5, 4, 4, 5, 5, 4, 4,
 53                     4, 5, 4, 4, 4, 4, 5 },
 54             { 6, 6, 6, 7, 6, 6, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 5, 5, 5, 6, 5, 5,
 55                     5, 5, 4, 5, 5, 5, 5 },
 56             { 6, 6, 7, 7, 6, 6, 6, 7, 6, 6, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 5, 5,
 57                     5, 6, 5, 5, 5, 5, 4, 5, 5, 5, 5 },
 58             { 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7, 7, 7, 6, 7, 7, 7, 6, 6,
 59                     7, 7, 6, 6, 6, 7, 7 },
 60             { 8, 8, 8, 9, 8, 8, 8, 8, 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7,
 61                     7, 7, 6, 7, 7, 7, 6, 6, 7, 7, 7 },
 62             { 8, 8, 8, 9, 8, 8, 8, 8, 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7,
 63                     7, 7, 6, 7, 7, 7, 7 },
 64             { 9, 9, 9, 9, 8, 9, 9, 9, 8, 8, 9, 9, 8, 8, 8, 9, 8, 8, 8, 8, 7, 8,
 65                     8, 8, 7, 7, 8, 8, 8 },
 66             { 8, 8, 8, 8, 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7, 7, 7, 6, 7,
 67                     7, 7, 6, 6, 7, 7, 7 },
 68             { 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7, 7, 7, 6, 7, 7, 7, 6, 6,
 69                     7, 7, 6, 6, 6, 7, 7 } };
 70     private static char[][] sectionalTermYear = {
 71             { 13, 49, 85, 117, 149, 185, 201, 250, 250 },
 72             { 13, 45, 81, 117, 149, 185, 201, 250, 250 },
 73             { 13, 48, 84, 112, 148, 184, 200, 201, 250 },
 74             { 13, 45, 76, 108, 140, 172, 200, 201, 250 },
 75             { 13, 44, 72, 104, 132, 168, 200, 201, 250 },
 76             { 5, 33, 68, 96, 124, 152, 188, 200, 201 },
 77             { 29, 57, 85, 120, 148, 176, 200, 201, 250 },
 78             { 13, 48, 76, 104, 132, 168, 196, 200, 201 },
 79             { 25, 60, 88, 120, 148, 184, 200, 201, 250 },
 80             { 16, 44, 76, 108, 144, 172, 200, 201, 250 },
 81             { 28, 60, 92, 124, 160, 192, 200, 201, 250 },
 82             { 17, 53, 85, 124, 156, 188, 200, 201, 250 } };
 83     private static char[][] principleTermMap = {
 84             { 21, 21, 21, 21, 21, 20, 21, 21, 21, 20, 20, 21, 21, 20, 20, 20,
 85                     20, 20, 20, 20, 20, 19, 20, 20, 20, 19, 19, 20 },
 86             { 20, 19, 19, 20, 20, 19, 19, 19, 19, 19, 19, 19, 19, 18, 19, 19,
 87                     19, 18, 18, 19, 19, 18, 18, 18, 18, 18, 18, 18 },
 88             { 21, 21, 21, 22, 21, 21, 21, 21, 20, 21, 21, 21, 20, 20, 21, 21,
 89                     20, 20, 20, 21, 20, 20, 20, 20, 19, 20, 20, 20, 20 },
 90             { 20, 21, 21, 21, 20, 20, 21, 21, 20, 20, 20, 21, 20, 20, 20, 20,
 91                     19, 20, 20, 20, 19, 19, 20, 20, 19, 19, 19, 20, 20 },
 92             { 21, 22, 22, 22, 21, 21, 22, 22, 21, 21, 21, 22, 21, 21, 21, 21,
 93                     20, 21, 21, 21, 20, 20, 21, 21, 20, 20, 20, 21, 21 },
 94             { 22, 22, 22, 22, 21, 22, 22, 22, 21, 21, 22, 22, 21, 21, 21, 22,
 95                     21, 21, 21, 21, 20, 21, 21, 21, 20, 20, 21, 21, 21 },
 96             { 23, 23, 24, 24, 23, 23, 23, 24, 23, 23, 23, 23, 22, 23, 23, 23,
 97                     22, 22, 23, 23, 22, 22, 22, 23, 22, 22, 22, 22, 23 },
 98             { 23, 24, 24, 24, 23, 23, 24, 24, 23, 23, 23, 24, 23, 23, 23, 23,
 99                     22, 23, 23, 23, 22, 22, 23, 23, 22, 22, 22, 23, 23 },
100             { 23, 24, 24, 24, 23, 23, 24, 24, 23, 23, 23, 24, 23, 23, 23, 23,
101                     22, 23, 23, 23, 22, 22, 23, 23, 22, 22, 22, 23, 23 },
102             { 24, 24, 24, 24, 23, 24, 24, 24, 23, 23, 24, 24, 23, 23, 23, 24,
103                     23, 23, 23, 23, 22, 23, 23, 23, 22, 22, 23, 23, 23 },
104             { 23, 23, 23, 23, 22, 23, 23, 23, 22, 22, 23, 23, 22, 22, 22, 23,
105                     22, 22, 22, 22, 21, 22, 22, 22, 21, 21, 22, 22, 22 },
106             { 22, 22, 23, 23, 22, 22, 22, 23, 22, 22, 22, 22, 21, 22, 22, 22,
107                     21, 21, 22, 22, 21, 21, 21, 22, 21, 21, 21, 21, 22 } };
108     private static char[][] principleTermYear = {
109             { 13, 45, 81, 113, 149, 185, 201 },
110             { 21, 57, 93, 125, 161, 193, 201 },
111             { 21, 56, 88, 120, 152, 188, 200, 201 },
112             { 21, 49, 81, 116, 144, 176, 200, 201 },
113             { 17, 49, 77, 112, 140, 168, 200, 201 },
114             { 28, 60, 88, 116, 148, 180, 200, 201 },
115             { 25, 53, 84, 112, 144, 172, 200, 201 },
116             { 29, 57, 89, 120, 148, 180, 200, 201 },
117             { 17, 45, 73, 108, 140, 168, 200, 201 },
118             { 28, 60, 92, 124, 160, 192, 200, 201 },
119             { 16, 44, 80, 112, 148, 180, 200, 201 },
120             { 17, 53, 88, 120, 156, 188, 200, 201 } };
121 
122     private static char[] chineseMonths = {
123             // 农历月份大小压缩表,两个字节表示一年。两个字节共十六个二进制位数,
124             // 前四个位数表示闰月月份,后十二个位数表示十二个农历月份的大小。
125             0x00, 0x04, 0xad, 0x08, 0x5a, 0x01, 0xd5, 0x54, 0xb4, 0x09, 0x64,
126             0x05, 0x59, 0x45, 0x95, 0x0a, 0xa6, 0x04, 0x55, 0x24, 0xad, 0x08,
127             0x5a, 0x62, 0xda, 0x04, 0xb4, 0x05, 0xb4, 0x55, 0x52, 0x0d, 0x94,
128             0x0a, 0x4a, 0x2a, 0x56, 0x02, 0x6d, 0x71, 0x6d, 0x01, 0xda, 0x02,
129             0xd2, 0x52, 0xa9, 0x05, 0x49, 0x0d, 0x2a, 0x45, 0x2b, 0x09, 0x56,
130             0x01, 0xb5, 0x20, 0x6d, 0x01, 0x59, 0x69, 0xd4, 0x0a, 0xa8, 0x05,
131             0xa9, 0x56, 0xa5, 0x04, 0x2b, 0x09, 0x9e, 0x38, 0xb6, 0x08, 0xec,
132             0x74, 0x6c, 0x05, 0xd4, 0x0a, 0xe4, 0x6a, 0x52, 0x05, 0x95, 0x0a,
133             0x5a, 0x42, 0x5b, 0x04, 0xb6, 0x04, 0xb4, 0x22, 0x6a, 0x05, 0x52,
134             0x75, 0xc9, 0x0a, 0x52, 0x05, 0x35, 0x55, 0x4d, 0x0a, 0x5a, 0x02,
135             0x5d, 0x31, 0xb5, 0x02, 0x6a, 0x8a, 0x68, 0x05, 0xa9, 0x0a, 0x8a,
136             0x6a, 0x2a, 0x05, 0x2d, 0x09, 0xaa, 0x48, 0x5a, 0x01, 0xb5, 0x09,
137             0xb0, 0x39, 0x64, 0x05, 0x25, 0x75, 0x95, 0x0a, 0x96, 0x04, 0x4d,
138             0x54, 0xad, 0x04, 0xda, 0x04, 0xd4, 0x44, 0xb4, 0x05, 0x54, 0x85,
139             0x52, 0x0d, 0x92, 0x0a, 0x56, 0x6a, 0x56, 0x02, 0x6d, 0x02, 0x6a,
140             0x41, 0xda, 0x02, 0xb2, 0xa1, 0xa9, 0x05, 0x49, 0x0d, 0x0a, 0x6d,
141             0x2a, 0x09, 0x56, 0x01, 0xad, 0x50, 0x6d, 0x01, 0xd9, 0x02, 0xd1,
142             0x3a, 0xa8, 0x05, 0x29, 0x85, 0xa5, 0x0c, 0x2a, 0x09, 0x96, 0x54,
143             0xb6, 0x08, 0x6c, 0x09, 0x64, 0x45, 0xd4, 0x0a, 0xa4, 0x05, 0x51,
144             0x25, 0x95, 0x0a, 0x2a, 0x72, 0x5b, 0x04, 0xb6, 0x04, 0xac, 0x52,
145             0x6a, 0x05, 0xd2, 0x0a, 0xa2, 0x4a, 0x4a, 0x05, 0x55, 0x94, 0x2d,
146             0x0a, 0x5a, 0x02, 0x75, 0x61, 0xb5, 0x02, 0x6a, 0x03, 0x61, 0x45,
147             0xa9, 0x0a, 0x4a, 0x05, 0x25, 0x25, 0x2d, 0x09, 0x9a, 0x68, 0xda,
148             0x08, 0xb4, 0x09, 0xa8, 0x59, 0x54, 0x03, 0xa5, 0x0a, 0x91, 0x3a,
149             0x96, 0x04, 0xad, 0xb0, 0xad, 0x04, 0xda, 0x04, 0xf4, 0x62, 0xb4,
150             0x05, 0x54, 0x0b, 0x44, 0x5d, 0x52, 0x0a, 0x95, 0x04, 0x55, 0x22,
151             0x6d, 0x02, 0x5a, 0x71, 0xda, 0x02, 0xaa, 0x05, 0xb2, 0x55, 0x49,
152             0x0b, 0x4a, 0x0a, 0x2d, 0x39, 0x36, 0x01, 0x6d, 0x80, 0x6d, 0x01,
153             0xd9, 0x02, 0xe9, 0x6a, 0xa8, 0x05, 0x29, 0x0b, 0x9a, 0x4c, 0xaa,
154             0x08, 0xb6, 0x08, 0xb4, 0x38, 0x6c, 0x09, 0x54, 0x75, 0xd4, 0x0a,
155             0xa4, 0x05, 0x45, 0x55, 0x95, 0x0a, 0x9a, 0x04, 0x55, 0x44, 0xb5,
156             0x04, 0x6a, 0x82, 0x6a, 0x05, 0xd2, 0x0a, 0x92, 0x6a, 0x4a, 0x05,
157             0x55, 0x0a, 0x2a, 0x4a, 0x5a, 0x02, 0xb5, 0x02, 0xb2, 0x31, 0x69,
158             0x03, 0x31, 0x73, 0xa9, 0x0a, 0x4a, 0x05, 0x2d, 0x55, 0x2d, 0x09,
159             0x5a, 0x01, 0xd5, 0x48, 0xb4, 0x09, 0x68, 0x89, 0x54, 0x0b, 0xa4,
160             0x0a, 0xa5, 0x6a, 0x95, 0x04, 0xad, 0x08, 0x6a, 0x44, 0xda, 0x04,
161             0x74, 0x05, 0xb0, 0x25, 0x54, 0x03 };
162 
163     /**
164      * 用于保存24节气
165      */
166     private static String[] principleTermNames = { "大寒", "雨水", "春分", "谷雨",
167             "小满", "夏至", "大暑", "处暑", "秋分", "霜降", "小雪", "冬至" };
168     /**
169      * 用于保存24节气
170      */
171     private static String[] sectionalTermNames = { "小寒", "立春", "惊蛰", "清明",
172             "立夏", "芒种", "小暑", "立秋", "白露", "寒露", "立冬", "大雪" };
173 
174     public SolarTermsUtil(Calendar calendar) {
175         gregorianYear = calendar.get(Calendar.YEAR);
176         gregorianMonth = calendar.get(Calendar.MONTH) + 1;
177         gregorianDate = calendar.get(Calendar.DATE);
178         computeChineseFields();
179         computeSolarTerms();
180     }
181 
182     public int computeChineseFields() {
183         if (gregorianYear < 1901 || gregorianYear > 2100)
184             return 1;
185         int startYear = baseYear;
186         int startMonth = baseMonth;
187         int startDate = baseDate;
188         chineseYear = baseChineseYear;
189         chineseMonth = baseChineseMonth;
190         chineseDate = baseChineseDate;
191         // 第二个对应日,用以提高计算效率
192         // 公历 2000 年 1 月 1 日,对应农历 4697 年 11 月 25 日
193         if (gregorianYear >= 2000) {
194             startYear = baseYear + 99;
195             startMonth = 1;
196             startDate = 1;
197             chineseYear = baseChineseYear + 99;
198             chineseMonth = 11;
199             chineseDate = 25;
200         }
201         int daysDiff = 0;
202         for (int i = startYear; i < gregorianYear; i++) {
203             daysDiff += 365;
204             if (isGregorianLeapYear(i))
205                 daysDiff += 1; // leap year
206         }
207         for (int i = startMonth; i < gregorianMonth; i++) {
208             daysDiff += daysInGregorianMonth(gregorianYear, i);
209         }
210         daysDiff += gregorianDate - startDate;
211 
212         chineseDate += daysDiff;
213         int lastDate = daysInChineseMonth(chineseYear, chineseMonth);
214         int nextMonth = nextChineseMonth(chineseYear, chineseMonth);
215         while (chineseDate > lastDate) {
216             if (Math.abs(nextMonth) < Math.abs(chineseMonth))
217                 chineseYear++;
218             chineseMonth = nextMonth;
219             chineseDate -= lastDate;
220             lastDate = daysInChineseMonth(chineseYear, chineseMonth);
221             nextMonth = nextChineseMonth(chineseYear, chineseMonth);
222         }
223         return 0;
224     }
225 
226     public int computeSolarTerms() {
227         if (gregorianYear < 1901 || gregorianYear > 2100)
228             return 1;
229         sectionalTerm = sectionalTerm(gregorianYear, gregorianMonth);
230         principleTerm = principleTerm(gregorianYear, gregorianMonth);
231         return 0;
232     }
233 
234     public static int sectionalTerm(int y, int m) {
235         if (y < 1901 || y > 2100)
236             return 0;
237         int index = 0;
238         int ry = y - baseYear + 1;
239         while (ry >= sectionalTermYear[m - 1][index])
240             index++;
241         int term = sectionalTermMap[m - 1][4 * index + ry % 4];
242         if ((ry == 121) && (m == 4))
243             term = 5;
244         if ((ry == 132) && (m == 4))
245             term = 5;
246         if ((ry == 194) && (m == 6))
247             term = 6;
248         return term;
249     }
250 
251     public static int principleTerm(int y, int m) {
252         if (y < 1901 || y > 2100)
253             return 0;
254         int index = 0;
255         int ry = y - baseYear + 1;
256         while (ry >= principleTermYear[m - 1][index])
257             index++;
258         int term = principleTermMap[m - 1][4 * index + ry % 4];
259         if ((ry == 171) && (m == 3))
260             term = 21;
261         if ((ry == 181) && (m == 5))
262             term = 21;
263         return term;
264     }
265 
266     /**
267      * 用于判断输入的年份是否为闰年
268      *
269      * @param year
270      *            输入的年份
271      * @return true 表示闰年
272      */
273     public static boolean isGregorianLeapYear(int year) {
274         boolean isLeap = false;
275         if (year % 4 == 0)
276             isLeap = true;
277         if (year % 100 == 0)
278             isLeap = false;
279         if (year % 400 == 0)
280             isLeap = true;
281         return isLeap;
282     }
283 
284     public static int daysInGregorianMonth(int y, int m) {
285         int d = daysInGregorianMonth[m - 1];
286         if (m == 2 && isGregorianLeapYear(y))
287             d++; // 公历闰年二月多一天
288         return d;
289     }
290 
291     public static int daysInChineseMonth(int y, int m) {
292         // 注意:闰月 m < 0
293         int index = y - baseChineseYear + baseIndex;
294         int v = 0;
295         int l = 0;
296         int d = 30;
297         if (1 <= m && m <= 8) {
298             v = chineseMonths[2 * index];
299             l = m - 1;
300             if (((v >> l) & 0x01) == 1)
301                 d = 29;
302         } else if (9 <= m && m <= 12) {
303             v = chineseMonths[2 * index + 1];
304             l = m - 9;
305             if (((v >> l) & 0x01) == 1)
306                 d = 29;
307         } else {
308             v = chineseMonths[2 * index + 1];
309             v = (v >> 4) & 0x0F;
310             if (v != Math.abs(m)) {
311                 d = 0;
312             } else {
313                 d = 29;
314                 for (int i = 0; i < bigLeapMonthYears.length; i++) {
315                     if (bigLeapMonthYears[i] == index) {
316                         d = 30;
317                         break;
318                     }
319                 }
320             }
321         }
322         return d;
323     }
324 
325     public static int nextChineseMonth(int y, int m) {
326         int n = Math.abs(m) + 1;
327         if (m > 0) {
328             int index = y - baseChineseYear + baseIndex;
329             int v = chineseMonths[2 * index + 1];
330             v = (v >> 4) & 0x0F;
331             if (v == m)
332                 n = -m;
333         }
334         if (n == 13)
335             n = 1;
336         return n;
337     }
338 
339     // 大闰月的闰年年份
340     private static int[] bigLeapMonthYears = { 6, 14, 19, 25, 33, 36, 38, 41,
341             44, 52, 55, 79, 117, 136, 147, 150, 155, 158, 185, 193 };
342 
343     /**
344      * 用于获取24节气的值
345      *
346      * @return 24节气的值
347      */
348     public String getSolartermsMsg() {
349         String str = "";
350         String gm = String.valueOf(gregorianMonth);
351         if (gm.length() == 1)
352             gm = ' ' + gm;
353         String cm = String.valueOf(Math.abs(chineseMonth));
354         if (cm.length() == 1)
355             cm = ' ' + cm;
356         String gd = String.valueOf(gregorianDate);
357         if (gd.length() == 1)
358             gd = ' ' + gd;
359         String cd = String.valueOf(chineseDate);
360         if (cd.length() == 1)
361             cd = ' ' + cd;
362         if (gregorianDate == sectionalTerm) {
363             str = " " + sectionalTermNames[gregorianMonth - 1];
364         } else if (gregorianDate == principleTerm) {
365             str = " " + principleTermNames[gregorianMonth - 1];
366         }
367         return str;
368     }
369 }

8)

StringUtil
 1 package com.example.nanchen.mydateviewdemo.view;
 2 
 3 /**
 4  * @author nanchen
 5  * @date 16-8-10 上午11:39
 6  */
 7 public class StringUtil {
 8 
 9     /**
10      * 判断是否为null或空值
11      *
12      * @param str
13      *            String
14      * @return true or false
15      */
16     public static boolean isNullOrEmpty(String str) {
17         return str == null || str.trim().length() == 0;
18     }
19 
20     /**
21      * 判断str1和str2是否相同
22      *
23      * @param str1
24      *            str1
25      * @param str2
26      *            str2
27      * @return true or false
28      */
29     public static boolean equals(String str1, String str2) {
30         return str1 == str2 || str1 != null && str1.equals(str2);
31     }
32 
33     /**
34      * 判断str1和str2是否相同(不区分大小写)
35      *
36      * @param str1
37      *            str1
38      * @param str2
39      *            str2
40      * @return true or false
41      */
42     public static boolean equalsIgnoreCase(String str1, String str2) {
43         return str1 != null && str1.equalsIgnoreCase(str2);
44     }
45 
46     /**
47      * 判断字符串str1是否包含字符串str2
48      *
49      * @param str1
50      *            源字符串
51      * @param str2
52      *            指定字符串
53      * @return true源字符串包含指定字符串,false源字符串不包含指定字符串
54      */
55     public static boolean contains(String str1, String str2) {
56         return str1 != null && str1.contains(str2);
57     }
58 
59     /**
60      * 判断字符串是否为空,为空则返回一个空值,不为空则返回原字符串
61      *
62      * @param str
63      *            待判断字符串
64      * @return 判断后的字符串
65      */
66     public static String getString(String str) {
67         return str == null ? "" : str;
68     }
69 }

9)

ViewUtil
  1 package com.example.nanchen.mydateviewdemo.view;
  2 
  3 import android.content.Context;
  4 import android.content.res.Resources;
  5 
  6 /**
  7  * 辅助类
  8  *
  9  * @author nanchen
 10  * @date 16-8-10 上午11:39
 11  */
 12 public class ViewUtil {
 13     /**
 14      * 获取屏幕的宽度
 15      * @param context
 16      * @return
 17      */
 18     public int getScreenWidth(Context context) {
 19         Resources res = context.getResources();
 20         return res.getDisplayMetrics().widthPixels;
 21     }
 22 
 23     /**
 24      * 获取屏幕高度
 25      * @param context
 26      * @return
 27      */
 28     public int getScreenHeight(Context context) {
 29         Resources res = context.getResources();
 30         return res.getDisplayMetrics().heightPixels;
 31     }
 32 
 33     /**
 34      * 描述:根据分辨率获得字体大小.
 35      *
 36      * @param screenWidth the screen width
 37      * @param screenHeight the screen height
 38      * @param textSize the text size
 39      * @return the int
 40      */
 41     public static int resizeTextSize(int screenWidth,int screenHeight,int textSize){
 42         float ratio =  1;
 43         try {
 44             float ratioWidth = (float)screenWidth / 480;
 45             float ratioHeight = (float)screenHeight / 800;
 46             ratio = Math.min(ratioWidth, ratioHeight);
 47         } catch (Exception e) {
 48         }
 49         return Math.round(textSize * ratio);
 50     }
 51 
 52     /**
 53      *
 54      * 描述:dip转换为px
 55      * @param context
 56      * @param dipValue
 57      * @return
 58      * @throws
 59      */
 60     public static int dip2px(Context context, float dipValue) {
 61         final float scale = context.getResources().getDisplayMetrics().density;
 62         return Math.round(dipValue * scale);
 63     }
 64 
 65     /**
 66      *
 67      * 描述:px转换为dip
 68      * @param context
 69      * @param pxValue
 70      * @return
 71      * @throws
 72      */
 73     public static int px2dip(Context context, float pxValue) {
 74         final float scale = context.getResources().getDisplayMetrics().density;
 75         return Math.round(pxValue / scale);
 76     }
 77 
 78     /**
 79      *
 80      * 描述:px转换为sp
 81      * @param context
 82      * @param pxValue
 83      * @return
 84      * @throws
 85      */
 86     public static int px2sp(Context context, float pxValue) {
 87         final float scale = context.getResources().getDisplayMetrics().scaledDensity;
 88         return Math.round(pxValue / scale);
 89     }
 90 
 91     /**
 92      *
 93      * 描述:sp转换为px
 94      * @param context
 95      * @param spValue
 96      * @return
 97      * @throws
 98      */
 99     public static int sp2px(Context context, float spValue) {
100         final float scale = context.getResources().getDisplayMetrics().scaledDensity;
101         return Math.round(spValue * scale);
102     }
103 }

10)

WeekGridAdapter
 1 package com.example.nanchen.mydateviewdemo.view;
 2 
 3 import android.content.Context;
 4 import android.graphics.Color;
 5 import android.view.Gravity;
 6 import android.view.View;
 7 import android.view.ViewGroup;
 8 import android.view.ViewGroup.LayoutParams;
 9 import android.widget.BaseAdapter;
10 import android.widget.TextView;
11 
12 import com.example.nanchen.mydateviewdemo.R;
13 
14 /**
15  * 显示week的布局adapter
16  * @author nanchen
17  * @date 16-8-10 上午11:39
18  */
19 public class WeekGridAdapter extends BaseAdapter {
20     final String[] titles = new String[] { "日", "一", "二", "三", "四", "五", "六" };
21     private Context mContext;
22 
23     public WeekGridAdapter(Context context) {
24         this.mContext = context;
25     }
26 
27     @Override
28     public int getCount() {
29         return titles.length;
30     }
31 
32     @Override
33     public Object getItem(int position) {
34         return titles[position];
35     }
36 
37     @Override
38     public long getItemId(int position) {
39         return position;
40     }
41 
42     @Override
43     public View getView(int position, View convertView, ViewGroup parent) {
44         TextView week = new TextView(mContext);
45         android.view.ViewGroup.LayoutParams week_params = new LayoutParams(
46                 android.view.ViewGroup.LayoutParams.MATCH_PARENT,
47                 android.view.ViewGroup.LayoutParams.MATCH_PARENT);
48         week.setLayoutParams(week_params);
49         week.setPadding(0, 0, 0, 0);
50         week.setGravity(Gravity.CENTER);
51         week.setFocusable(false);
52         week.setBackgroundColor(Color.TRANSPARENT);
53 
54         if (position == 6) { // 周六
55             week.setBackgroundColor(R.color.date_weekend_text_color);
56             week.setTextColor(Color.WHITE);
57         } else if (position == 0) { // 周日
58             week.setBackgroundColor(R.color.date_weekend_text_color);
59             week.setTextColor(Color.WHITE);
60         } else {
61             week.setTextColor(Color.BLACK);
62         }
63         week.setText(getItem(position)+"");
64         return week;
65     }
66 }

11)

MainActivity
 1 package com.example.nanchen.mydateviewdemo;
 2 
 3 import android.os.Bundle;
 4 import android.support.v7.app.AppCompatActivity;
 5 import android.widget.Toast;
 6 
 7 import com.example.nanchen.mydateviewdemo.view.CalendarView;
 8 import com.example.nanchen.mydateviewdemo.view.CalendarView.OnCalendarViewListener;
 9 
10 import java.text.SimpleDateFormat;
11 import java.util.ArrayList;
12 import java.util.Date;
13 import java.util.List;
14 import java.util.Locale;
15 
16 public class MainActivity extends AppCompatActivity {
17 
18     @Override
19     protected void onCreate(Bundle savedInstanceState) {
20         super.onCreate(savedInstanceState);
21         setContentView(R.layout.activity_main);
22 
23         //在代码中
24         CalendarView calendarView = (CalendarView) findViewById(R.id.calender);
25         //设置标注日期
26         List<Date> markDates = new ArrayList<>();
27         markDates.add(new Date());
28         calendarView.setMarkDates(markDates);
29 
30         //设置点击操作
31         calendarView.setOnCalendarViewListener(new OnCalendarViewListener() {
32 
33             @Override
34             public void onCalendarItemClick(CalendarView view, Date date) {
35                 final SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日", Locale.CHINA);
36                 Toast.makeText(MainActivity.this, format.format(date), Toast.LENGTH_SHORT).show();
37             }
38         });
39     }
40 }

12)布局文件

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <RelativeLayout
 3     xmlns:android="http://schemas.android.com/apk/res/android"
 4     xmlns:tools="http://schemas.android.com/tools"
 5     android:layout_width="match_parent"
 6     android:layout_height="match_parent"
 7     tools:context="com.example.nanchen.mydateviewdemo.MainActivity">
 8 
 9     <com.example.nanchen.mydateviewdemo.view.CalendarView
10         android:id="@+id/calender"
11         android:background="#fff"
12         android:layout_width="match_parent"
13         android:layout_height="wrap_content">
14 
15     </com.example.nanchen.mydateviewdemo.view.CalendarView>
16 </RelativeLayout>

 

drawable包下的

month_next_selector.xml

1 <?xml version="1.0" encoding="utf-8"?>
2 <selector xmlns:android="http://schemas.android.com/apk/res/android">
3     <item android:state_pressed="false" android:drawable="@drawable/right_arrow_pre"/>
4     <item android:state_pressed="true" android:drawable="@drawable/right_arrow"/>
5 </selector>

month_pre_selector.xml

1 <?xml version="1.0" encoding="utf-8"?>
2 <selector xmlns:android="http://schemas.android.com/apk/res/android">
3     <item android:state_pressed="false" android:drawable="@drawable/left_arrow_pre"/>
4     <item android:state_pressed="true" android:drawable="@drawable/left_arrow"/>
5 </selector>

color.xml

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <resources>
 3     <color name="colorPrimary">#3F51B5</color>
 4     <color name="colorPrimaryDark">#303F9F</color>
 5     <color name="colorAccent">#FF4081</color>
 6     <color name="date_pre_color">#44010101</color>
 7     <color name="date_select_color">#66d8ec</color>
 8     <color name="date_text_color">#010101</color>
 9     <color name="date_other_text_color">#dd918d8d</color>
10     <color name="date_today_text_color">#aaf43ed8</color>
11 
12     <color name="date_weekend_text_color">#f27e9d</color>
13 
14 </resources>

 

 

项目已同步至github:https://github.com/nanchen2251/MyCalendarViewDemo

额,楼主很蠢,就这个花了好一阵功夫,但是无私分享给大家,希望大家越来越好,如果你觉得还算有帮助,别忘了右下角点赞~~分享给你我他~

转载别忘了在醒目位置附上楼主地址哦~谢谢:http://www.cnblogs.com/liushilin/p/5759750.html

 

 

针对小伙伴们说的UI不够美观和代码讲解不够,楼主已经有了修订版,自行食用,地址:http://www.cnblogs.com/liushilin/p/5763717.html

posted @ 2016-08-11 09:36  南尘  阅读(12178)  评论(27编辑  收藏  举报

写不完的矫情,做不完的开源

点击进入我的GitHub页
南 尘
主 页
优美钢琴曲合集-南尘.mp3                    感谢您阅读我的博客,如果您现在工作、学习累了或者疲惫了,不妨聆听一下音乐,它能够减轻你的疲劳,还能够带给您一种舒适愉悦的心情。(样式取自博客园-欲泪成雪)