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

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

可能不少的小伙伴都有看楼主昨天发的自定义日历控件,虽然实现功能不多,但也还算将就吧。

没有看的小伙伴如果有兴趣的话可以去看看:http://www.cnblogs.com/liushilin/p/5759750.html

但是看了的小伙伴就很心急了,说楼主上传到gitHub的东西有问题,楼主下载来看了看,基本都没问题吧,没弄好的小伙伴自己再去我的github首页提取哦~因为我还上传了一个新的。

有的小伙伴又不满意了,楼主,你发的东西代码量那么大也搞得很麻烦,小生纵有远大理想,可思前虑后,还是不得正果,倘若楼主能指点一二便好了。

有的小伙伴说,楼主,你的东西就不能封装一下吗?封装一下,方便你我他~

有的小伙伴说,楼主,你的东西是挺不错,但是界面也略丑了吧~这里gank到22楼住的小伙伴说,中间分隔太低,信息太密集,建议添加行间距和留白,希望能做的漂亮些~

......

小主已成功gank到各位的中肯建议,但是不要慌,大家一个一个来。

大家的建议小主都非常地认可,所以楼主觉得把整个东西该封装的算法封装起来,也UI也弄得漂亮一些。

照例先给个运行图吧~

下面给大家讲解一下我们这个自定义日历的简单思路,肯定还是使用GridView的。

由于昨天是纯定义画的UI,所以大家看起来可能有所困难,所以今天楼主简化了UI,把UI放在了xml文件中,供大家食用。

楼主不是废话多的人,具体看代码,代码中我也做了更多的注释。

1)先准备好我们的算法,我们现在把它完全分离。

闰年月的算法应该大家都懂吧。SpecialCalendar.java 

三个方法,判断闰年,这个可能只要学程序前面肯定就学了的。

对于判断月份,貌似也不用多说,就一个switch语句,闰年的时候2月是29天,平年是28天。

还有一个判断某一天是星期几的,这个在Calendar中已经很明显了,但是要注意的是Month在calendar中是0-11

 1 package com.example.nanchen.calendarviewdemo.view;
 2 
 3 import java.util.Calendar;
 4 
 5 /**
 6  * 闰年月算法
 7  *
 8  * @author nanchen
 9  * @date  2016-08-11 08:54:44
10  *
11  */
12 public class SpecialCalendar {
13 
14     private int daysOfMonth = 0; // 某月的天数
15     private int dayOfWeek = 0; // 具体某一天是星期几
16 
17     // 判断是否为闰年
18     public boolean isLeapYear(int year) {
19         if (year % 100 == 0 && year % 400 == 0) {
20             return true;
21         } else if (year % 100 != 0 && year % 4 == 0) {
22             return true;
23         }
24         return false;
25     }
26 
27     // 得到某月有多少天数
28     public int getDaysOfMonth(boolean isLeapYear, int month) {
29         switch (month) {
30         case 1:
31         case 3:
32         case 5:
33         case 7:
34         case 8:
35         case 10:
36         case 12:
37             daysOfMonth = 31;
38             break;
39         case 4:
40         case 6:
41         case 9:
42         case 11:
43             daysOfMonth = 30;
44             break;
45         case 2:
46             if (isLeapYear) {
47                 daysOfMonth = 29;
48             } else {
49                 daysOfMonth = 28;
50             }
51 
52         }
53         return daysOfMonth;
54     }
55 
56     /**
57      * 指定某年中的某月的第一天是星期几
58      */
59     public int getWeekdayOfMonth(int year, int month) {
60         Calendar cal = Calendar.getInstance();
61         cal.set(year, month - 1, 1);
62         dayOfWeek = cal.get(Calendar.DAY_OF_WEEK) - 1;
63         return dayOfWeek;
64     }
65 
66 }

 

2)然后带来的是算农历的算法。LunarCalendar.java

就算法本身而言,楼主参考了网上留下的算法。基本就是定义好这些要用的数组,然后考虑完所有的情况。

这里需要心细严谨一些,毕竟你或许错一个参数,一个值就会让你一直搞不出原因,所以写出算法不妨先在Eclipse中看看控制台运行的结果是否正确吧。

高配置随便带Android studio的童鞋当我没说。

这里需要注意的是,我们要做农历,肯定必须想到年份,闰月,闰月是哪个月,这个月有多少天,这些都是需要考虑的。

楼主这简单添加几个节日,节日大家可以随便添加哦。只是一个显示问题。

  1 package com.example.nanchen.calendarviewdemo.view;
  2 
  3 import java.text.ParseException;
  4 import java.text.SimpleDateFormat;
  5 import java.util.Date;
  6 import java.util.Locale;
  7 
  8 /**
  9  * 农历算法
 10  *
 11  * @author nanchen
 12  * @date 2016-08-11  08-57:24
 13  */
 14 public class LunarCalendar {
 15     private int year; // 农历的年份
 16     private int month;
 17     private int day;
 18     private String lunarMonth; // 农历的月份
 19     public int leapMonth = 0; // 闰的是哪个月
 20 
 21     final static String chineseNumber[] = {"一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"};
 22     static SimpleDateFormat chineseDateFormat = new SimpleDateFormat("yyyy年MM月dd日", Locale.CHINA);
 23     final static long[] lunarInfo = new long[]{ //
 24             0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, //
 25             0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, //
 26             0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, //
 27             0x09570, 0x052f2, 0x04970, 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, //
 28             0x186e3, 0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, //
 29             0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550, 0x15355, 0x04da0, //
 30             0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, //
 31             0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, //
 32             0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6, 0x095b0, //
 33             0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, //
 34             0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, //
 35             0x092e0, 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, //
 36             0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, //
 37             0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, //
 38             0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, //
 39             0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, //
 40             0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0};
 41 
 42     // 农历部分假日
 43     final static String[] lunarHoliday = new String[]{"0101 春节", "0115 元宵", "0505 端午", "0707 情人", "0715 中元", "0815 中秋", "0909 重阳", "1208 腊八", "1224 小年", "0100 除夕"};
 44 
 45     // 公历部分节假日
 46     final static String[] solarHoliday = new String[]{ //
 47             "0101 元旦", "0214 情人", "0308 妇女", "0312 植树", "0315 消费者权益日", "0401 愚人", "0501 劳动", "0504 青年", //
 48             "0512 护士", "0601 儿童", "0701 建党", "0801 建军", "0808 父亲", "0910 教师", "0928 孔子诞辰",//
 49             "1001 国庆", "1006 老人", "1024 联合国日", "1112 孙中山诞辰纪念", "1220 澳门回归纪念", "1225 圣诞"};
 50 
 51     /**
 52      * 传回农历 y年的总天数
 53      *
 54      * @param y 年份
 55      * @return 该年的总天数
 56      */
 57     private static int yearDays(int y) {
 58         int i, sum = 348;
 59         for (i = 0x8000; i > 0x8; i >>= 1) {
 60             if ((lunarInfo[y - 1900] & i) != 0)
 61                 sum += 1;
 62         }
 63         return (sum + leapDays(y));
 64     }
 65 
 66     /**
 67      * 传回农历 y年闰月的天数
 68      *
 69      * @param y 年份
 70      * @return 改年闰月天数
 71      */
 72     private static int leapDays(int y) {
 73         if (leapMonth(y) != 0) {
 74             if ((lunarInfo[y - 1900] & 0x10000) != 0)
 75                 return 30;
 76             else
 77                 return 29;
 78         } else
 79             return 0;
 80     }
 81 
 82     /**
 83      * 传回农历 y年闰哪个月 1-12 , 没闰传回 0
 84      *
 85      * @param y 年份
 86      * @return 改年闰月的月数
 87      */
 88     private static int leapMonth(int y) {
 89         return (int) (lunarInfo[y - 1900] & 0b1111);
 90     }
 91 
 92     /**
 93      * 传回农历 y年m月的总天数
 94      *
 95      * @param y 年份
 96      * @param m 月份
 97      * @return 该月份的总天数
 98      */
 99     private static int monthDays(int y, int m) {
100         if ((lunarInfo[y - 1900] & (0x10000 >> m)) == 0)
101             return 29;
102         else
103             return 30;
104     }
105 
106     /**
107      * 传回农历 y年的生肖
108      *
109      * @param year 年份
110      * @return 生肖
111      */
112     public String animalsYear(int year) {
113         final String[] Animals = new String[]{"鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪"};
114         return Animals[(year - 4) % 12];
115     }
116 
117     /**
118      * 传入 月日的offset 传回干支, 0=甲子
119      */
120     private static String cyclicalm(int num) {
121         final String[] Gan = new String[]{"甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"};
122         final String[] Zhi = new String[]{"子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"};
123         return (Gan[num % 10] + Zhi[num % 12]);
124     }
125 
126     /**
127      * 传入 offset 传回干支, 0=甲子
128      */
129     public String cyclical(int year) {
130         int num = year - 1900 + 36;
131         return (cyclicalm(num));
132     }
133 
134     public static String getChinaDayString(int day) {
135         String chineseTen[] = {"初", "十", "廿", "卅"};
136         int n = day % 10 == 0 ? 9 : day % 10 - 1;
137         if (day > 30)
138             return "";
139         if (day == 10)
140             return "初十";
141         else
142             return chineseTen[day / 10] + chineseNumber[n];
143     }
144 
145     /**
146      * 传出y年m月d日对应的农历. yearCyl3:农历年与1864的相差数 ? monCyl4:从1900年1月31日以来,闰月数
147      * dayCyl5:与1900年1月31日相差的天数,再加40 ?
148      * <p/>
149      * isday: 这个参数为false---日期为节假日时,阴历日期就返回节假日 ,true---不管日期是否为节假日依然返回这天对应的阴历日期
150      *
151      * @return
152      */
153     public String getLunarDate(int year_log, int month_log, int day_log,
154                                boolean isday) {
155         // @SuppressWarnings("unused")
156         int yearCyl, monCyl, dayCyl;
157         // int leapMonth = 0;
158         String nowadays;
159         Date baseDate = null;
160         Date nowaday = null;
161         try {
162             baseDate = chineseDateFormat.parse("1900年1月31日");
163         } catch (ParseException e) {
164             e.printStackTrace(); // To change body of catch statement use
165             // Options | File Templates.
166         }
167 
168         nowadays = year_log + "年" + month_log + "月" + day_log + "日";
169         try {
170             nowaday = chineseDateFormat.parse(nowadays);
171         } catch (ParseException e) {
172             e.printStackTrace(); // To change body of catch statement use
173             // Options | File Templates.
174         }
175 
176         // 求出和1900年1月31日相差的天数
177         int offset = (int) ((nowaday.getTime() - baseDate.getTime()) / 86400000L);
178         dayCyl = offset + 40;
179         monCyl = 14;
180 
181         // 用offset减去每农历年的天数
182         // 计算当天是农历第几天
183         // i最终结果是农历的年份
184         // offset是当年的第几天
185         int iYear, daysOfYear = 0;
186         for (iYear = 1900; iYear < 10000 && offset > 0; iYear++) {
187             daysOfYear = yearDays(iYear);
188             offset -= daysOfYear;
189             monCyl += 12;
190         }
191         if (offset < 0) {
192             offset += daysOfYear;
193             iYear--;
194             monCyl -= 12;
195         }
196         // 农历年份
197         year = iYear;
198         setYear(year); // 设置公历对应的农历年份
199 
200         yearCyl = iYear - 1864;
201         leapMonth = leapMonth(iYear); // 闰哪个月,1-12
202         boolean leap = false;
203 
204         // 用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天
205         int iMonth, daysOfMonth = 0;
206         for (iMonth = 1; iMonth < 13 && offset > 0; iMonth++) {
207             // 闰月
208             if (leapMonth > 0 && iMonth == (leapMonth + 1) && !leap) {
209                 --iMonth;
210                 leap = true;
211                 daysOfMonth = leapDays(year);
212             } else
213                 daysOfMonth = monthDays(year, iMonth);
214 
215             offset -= daysOfMonth;
216             // 解除闰月
217             if (leap && iMonth == (leapMonth + 1))
218                 leap = false;
219             if (!leap)
220                 monCyl++;
221         }
222         // offset为0时,并且刚才计算的月份是闰月,要校正
223         if (offset == 0 && leapMonth > 0 && iMonth == leapMonth + 1) {
224             if (leap) {
225                 leap = false;
226             } else {
227                 leap = true;
228                 --iMonth;
229                 --monCyl;
230             }
231         }
232         // offset小于0时,也要校正
233         if (offset < 0) {
234             offset += daysOfMonth;
235             --iMonth;
236             --monCyl;
237         }
238         month = iMonth;
239         setLunarMonth(chineseNumber[month - 1] + "月"); // 设置对应的阴历月份
240         day = offset + 1;
241 
242         if (!isday) {
243             // 如果日期为节假日则阴历日期则返回节假日
244             // setLeapMonth(leapMonth);
245             for (int i = 0; i < solarHoliday.length; i++) {
246                 // 返回公历节假日名称
247                 String sd = solarHoliday[i].split(" ")[0]; // 节假日的日期
248                 String sdv = solarHoliday[i].split(" ")[1]; // 节假日的名称
249                 String smonth_v = month_log + "";
250                 String sday_v = day_log + "";
251                 String smd = "";
252                 if (month_log < 10) {
253                     smonth_v = "0" + month_log;
254                 }
255                 if (day_log < 10) {
256                     sday_v = "0" + day_log;
257                 }
258                 smd = smonth_v + sday_v;
259                 if (sd.trim().equals(smd.trim())) {
260                     return sdv;
261                 }
262             }
263 
264             for (int i = 0; i < lunarHoliday.length; i++) {
265                 // 返回农历节假日名称
266                 String ld = lunarHoliday[i].split(" ")[0]; // 节假日的日期
267                 String ldv = lunarHoliday[i].split(" ")[1]; // 节假日的名称
268                 String lmonth_v = month + "";
269                 String lday_v = day + "";
270                 String lmd = "";
271                 if (month < 10) {
272                     lmonth_v = "0" + month;
273                 }
274                 if (day < 10) {
275                     lday_v = "0" + day;
276                 }
277                 lmd = lmonth_v + lday_v;
278                 if (ld.trim().equals(lmd.trim())) {
279                     return ldv;
280                 }
281             }
282         }
283         if (day == 1)
284             return chineseNumber[month - 1] + "月";
285         else
286             return getChinaDayString(day);
287 
288     }
289 
290     public String toString() {
291         if (chineseNumber[month - 1] == "一" && getChinaDayString(day) == "初一")
292             return "农历" + year + "年";
293         else if (getChinaDayString(day) == "初一")
294             return chineseNumber[month - 1] + "月";
295         else
296             return getChinaDayString(day);
297         // return year + "年" + (leap ? "闰" : "") + chineseNumber[month - 1] +
298         // "月" + getChinaDayString(day);
299     }
300 
301 //
302 //    public static void main(String[] args) {
303 //        System.out.println(new
304 //                LunarCalendar().getLunarDate(2012, 1, 23));
305 //    }
306 
307 
308     public int getLeapMonth() {
309         return leapMonth;
310     }
311 
312     public void setLeapMonth(int leapMonth) {
313         this.leapMonth = leapMonth;
314     }
315 
316     /**
317      * 得到当前日期对应的阴历月份
318      *
319      * @return
320      */
321     public String getLunarMonth() {
322         return lunarMonth;
323     }
324 
325     public void setLunarMonth(String lunarMonth) {
326         this.lunarMonth = lunarMonth;
327     }
328 
329     /**
330      * 得到当前年对应的农历年份
331      *
332      * @return
333      */
334     public int getYear() {
335         return year;
336     }
337 
338     public void setYear(int year) {
339         this.year = year;
340     }
341 }

3)为了设置点击事件,这里就分离一个接口出来吧。

ClickDataListener.java
 1 package com.example.nanchen.calendarviewdemo.view;
 2 
 3 /**
 4  * 选中日期的监听事件
 5  *
 6  * @author nanchen
 7  * @date   2016-08-11 09:14:21
 8  */
 9 public interface ClickDataListener {
10     /**
11      * 点击日期day的点击事件监听
12      * @param year    年
13      * @param month   月
14      * @param day     日
15      */
16     void onClickData(int year, int month, int day);
17 }

这里暂且只有一个点击事件,这个东西大家可以自行创新。

4)这里定义一个格式,可能大家格式都不一样,自己弄呗。

FormatDate.java
1 package com.example.nanchen.calendarviewdemo.view;
2 
3 /**
4  * @author nanchen
5  * @date 16-8-12 上午8:15
6  */
7 public class FormatDate {
8     public static String DATE_FORMAT = "yyyy-MM-dd";
9 }

5)先来看看Adapter的代码,毕竟只有Adapter做好了,才能好好显示。

这里大家需要注意的是设置点击左右和滑动的时候都要显示上月或者下月,这个其实之前楼主写了一个TimeUtils的工具类。

这个可以通过Calendar里面的set方法来解决的,里面有两个参数。

这里先给大家看看我写的两个方法,与本例无关哦。

/**
     * 获得指定日期的前一月
     * @param specifiedDay 指定的字符串日期  格式:yyyy-MM
     * @return   指定的前一月
     */
    public static String getSpecifiedMonthBefore(String specifiedDay){
        Calendar c = Calendar.getInstance();
        Date date = null;
        try {
            date = new SimpleDateFormat("yyyy-MM").parse(specifiedDay);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        c.setTime(date);
        int month = c.get(Calendar.MONTH);
        c.set(Calendar.MONTH,month-1);
        return new SimpleDateFormat("yyyy-MM").format(c.getTime());
    }
    /**
     * 获得指定日期的后一月
     * @param specifiedDay 指定的字符串日期  格式:yyyy-MM
     * @return   指定的后一月
     */
    public static String getSpecifiedMonthAfter(String specifiedDay){
        Calendar c = Calendar.getInstance();
        Date date=null;
        try {
            date = new SimpleDateFormat("yyyy-MM").parse(specifiedDay);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        c.setTime(date);
        int month = c.get(Calendar.MONTH);
        c.set(Calendar.MONTH,month+1);
        return new SimpleDateFormat("yyyy-MM").format(c.getTime());
    }

 

上面只是教大家如何达到上月下月的效果,其实同样你可以通过Calendar和format方式对day和year等其他做同样的功能实现,大家可能以后还是有用的。

下面是Adapter,我想大家应该都很明白吧?就用new Date获取当前日期,然后字符串split分离成小数组,然后获取年月日,获取年月日方式不限,很多的。

要说到显示还是得看我们的getView,毕竟Adapter的精髓就在这个方法里,它可以觉得你到底是用怎么显示,这里楼主抛弃了以前画的方法,直接搞一个xml,把大小限制了,这样就不会像昨天那样布局密集,而丑了。

布局很简单啦。

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:background="#FFFFFF" >
 6 
 7     <TextView
 8         android:id="@+id/tvtext"
 9         android:layout_width="45dp"
10         android:layout_height="55dp"
11         android:gravity="center" />
12 
13 </LinearLayout>

我们在getView中设置了颜色等属性。并把非当前月设置为暗色,不可点击。

然后对于week做一些处理,好的,Adapter就OK了。

  1 package com.example.nanchen.calendarviewdemo.view;
  2 
  3 import android.content.Context;
  4 import android.content.res.Resources;
  5 import android.graphics.Color;
  6 import android.text.SpannableString;
  7 import android.text.Spanned;
  8 import android.text.TextUtils;
  9 import android.text.style.RelativeSizeSpan;
 10 import android.text.style.StyleSpan;
 11 import android.util.Log;
 12 import android.view.LayoutInflater;
 13 import android.view.View;
 14 import android.view.ViewGroup;
 15 import android.widget.BaseAdapter;
 16 import android.widget.TextView;
 17 
 18 import com.example.nanchen.calendarviewdemo.R;
 19 
 20 import java.text.SimpleDateFormat;
 21 import java.util.Date;
 22 import java.util.Locale;
 23 
 24 /**
 25  * 日历GridView中的每一个item显示的文本
 26  *
 27  * @author nanchen
 28  * @date  2016-08-11 10:14:52
 29  */
 30 public class CalendarAdapter extends BaseAdapter {
 31     private boolean isLeapYear = false; // 是否为闰年
 32     private int daysOfMonth = 0; // 某月的天数
 33     private int dayOfWeek = 0; // 具体某一天是星期几
 34     private int lastDaysOfMonth = 0; // 上一个月的总天数
 35     private Context context;
 36     private String[] dayNumber = new String[42]; // 一个GridView中的日期存入此数组中,因为一般日历都是6行7列
 37     private SpecialCalendar sc = null;
 38     private LunarCalendar lc = null;
 39     private Resources res = null;
 40     private int currentYear = 0;
 41     private int currentMonth = 0;
 42     private int currentDay = 0;
 43 
 44     private SimpleDateFormat sdf = new SimpleDateFormat(FormatDate.DATE_FORMAT, Locale.CHINA);//格式化日期格式
 45     private String showYear = ""; // 用于在头部显示的年份
 46     private String showMonth = ""; // 用于在头部显示的月份
 47     private String animalsYear = "";
 48     private String leapMonth = ""; // 闰哪一个月
 49     private String cyclical = ""; // 天干地支
 50     // 系统当前时间
 51     private String sysDate = "";
 52     private String sys_year = "";
 53     private String sys_month = "";
 54     private String sys_day = "";
 55     private int colorDataPosition = -1;
 56     private boolean isClickData = false;
 57 
 58     public CalendarAdapter() {
 59         Date date = new Date();
 60         sysDate = sdf.format(date); // 当期日期
 61         sys_year = sysDate.split("-")[0];
 62         sys_month = sysDate.split("-")[1];
 63         sys_day = sysDate.split("-")[2];
 64 
 65     }
 66 
 67     public CalendarAdapter(Context context, Resources rs, int jumpMonth,
 68             int jumpYear, int year_c, int month_c, int day_c) {
 69         this();
 70         this.context = context;
 71         sc = new SpecialCalendar();
 72         lc = new LunarCalendar();
 73         this.res = rs;
 74 
 75         int stepYear = year_c + jumpYear;
 76         int stepMonth = month_c + jumpMonth;
 77         if (stepMonth > 0) {
 78             // 往下一个月滑动
 79             if (stepMonth % 12 == 0) {
 80                 stepYear = year_c + stepMonth / 12 - 1;
 81                 stepMonth = 12;
 82             } else {
 83                 stepYear = year_c + stepMonth / 12;
 84                 stepMonth = stepMonth % 12;
 85             }
 86         } else {
 87             // 往上一个月滑动
 88             stepYear = year_c - 1 + stepMonth / 12;
 89             stepMonth = stepMonth % 12 + 12;
 90             if (stepMonth % 12 == 0) {
 91 
 92             }
 93         }
 94 
 95         currentYear = stepYear; // 得到当前的年份
 96         currentMonth = stepMonth; // 得到本月
 97                                                     // (jumpMonth为滑动的次数,每滑动一次就增加一月或减一月)
 98         currentDay = day_c; // 得到当前日期是哪天
 99 
100         getCalendar(currentYear, currentMonth);
101 
102     }
103 
104     public CalendarAdapter(Context context, Resources rs, int year, int month,
105             int day) {
106         this();
107         this.context = context;
108         sc = new SpecialCalendar();
109         lc = new LunarCalendar();
110         this.res = rs;
111         currentYear = year;// 得到跳转到的年份
112         currentMonth = month; // 得到跳转到的月份
113         currentDay = day; // 得到跳转到的天
114         getCalendar(currentYear, currentMonth);
115     }
116 
117     @Override
118     public int getCount() {
119         return dayNumber.length;
120     }
121 
122     @Override
123     public Object getItem(int position) {
124         return dayNumber[position];
125     }
126 
127     @Override
128     public long getItemId(int position) {
129         return position;
130     }
131 
132     @Override
133     public View getView(int position, View convertView, ViewGroup parent) {
134 
135         if (convertView == null) {
136             convertView = LayoutInflater.from(context).inflate(R.layout.calen_calendar_item, parent,false);
137         }
138         TextView textView = (TextView) convertView.findViewById(R.id.tvtext);
139         String d = dayNumber[position].split("\\.")[0];
140         String dv = dayNumber[position].split("\\.")[1];
141 
142         SpannableString sp = new SpannableString(d + "\n" + dv);
143         sp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0,
144                 d.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
145         sp.setSpan(new RelativeSizeSpan(1.2f), 0, d.length(),
146                 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
147         if (dv != null || !TextUtils.isEmpty(dv)) {
148             sp.setSpan(new RelativeSizeSpan(0.75f), d.length() + 1,
149                     dayNumber[position].length(),
150                     Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
151         }
152         textView.setText(sp);
153         textView.setTextColor(Color.GRAY);
154 
155         if (position < daysOfMonth + dayOfWeek && position >= dayOfWeek) {
156             // 当前月信息显示
157             textView.setTextColor(Color.BLACK);// 当月字体设黑
158             // drawable = new ColorDrawable(Color.rgb(23, 126, 214));
159             if (position % 7 == 0 || position % 7 == 6) {
160                 // 当前月信息显示
161                 textView.setTextColor(Color.rgb(23, 126, 214));// 当月字体设黑
162             }
163         }
164 
165         if (colorDataPosition == position) {
166             // 设置当天的背景
167             textView.setTextColor(Color.WHITE);
168 
169             textView.setBackgroundResource(R.drawable.bg_circle);
170         } else {
171             textView.setBackgroundColor(res.getColor(android.R.color.transparent));
172         }
173         return convertView;
174     }
175 
176     // 得到某年的某月的天数且这月的第一天是星期几
177     private void getCalendar(int year, int month) {
178         isLeapYear = sc.isLeapYear(year); // 是否为闰年
179         daysOfMonth = sc.getDaysOfMonth(isLeapYear, month); // 某月的总天数
180         dayOfWeek = sc.getWeekdayOfMonth(year, month); // 某月第一天为星期几
181         lastDaysOfMonth = sc.getDaysOfMonth(isLeapYear, month - 1); // 上一个月的总天数
182         getweek(year, month);
183     }
184 
185     // 将一个月中的每一天的值添加入数组dayNuber中
186     private void getweek(int year, int month) {
187         int j = 1;
188         String lunarDay = "";
189         // 得到当前月的所有日程日期(这些日期需要标记)
190         for (int i = 0; i < dayNumber.length; i++) {
191             if (i < dayOfWeek) { // 前一个月
192                 int temp = lastDaysOfMonth - dayOfWeek + 1;
193                 lunarDay = lc.getLunarDate(year, month - 1, temp + i, false);
194                 dayNumber[i] = (temp + i) + "." + lunarDay;
195 
196             } else if (i < daysOfMonth + dayOfWeek) { // 本月
197                 String day = String.valueOf(i - dayOfWeek + 1); // 得到的日期
198                 lunarDay = lc.getLunarDate(year, month, i - dayOfWeek + 1,
199                         false);
200                 dayNumber[i] = i - dayOfWeek + 1 + "." + lunarDay;
201                 // 对于当前月才去标记当前日期
202                 if (sys_year.equals(String.valueOf(year))
203                         && sys_month.equals(String.valueOf(month))
204                         && sys_day.equals(day)) {
205                     // 标记当前日期
206                     colorDataPosition = i;
207                 }
208                 setShowYear(String.valueOf(year));
209                 setShowMonth(String.valueOf(month));
210                 setAnimalsYear(lc.animalsYear(year));
211                 setLeapMonth(lc.leapMonth == 0 ? "" : String
212                         .valueOf(lc.leapMonth));
213                 setCyclical(lc.cyclical(year));
214             } else { // 下一个月
215                 lunarDay = lc.getLunarDate(year, month + 1, j, false);
216                 dayNumber[i] = j + "." + lunarDay;
217                 j++;
218             }
219         }
220 
221         String abc = "";
222         for (int i = 0; i < dayNumber.length; i++) {
223             abc = abc + dayNumber[i] + ":";
224         }
225         Log.d("DAYNUMBER", abc);
226 
227     }
228 
229     /**
230      * 点击每一个item时返回item中的日期
231      * 
232      * @param position
233      * @return
234      */
235     public String getDateByClickItem(int position) {
236         return dayNumber[position];
237     }
238 
239     /**
240      * 在点击gridView时,得到这个月中第一天的位置
241      * 
242      * @return
243      */
244     public int getStartPositon() {
245         return dayOfWeek + 7;
246     }
247 
248     /**
249      * 在点击gridView时,得到这个月中最后一天的位置
250      * 
251      * @return
252      */
253     public int getEndPosition() {
254         return (dayOfWeek + daysOfMonth + 7) - 1;
255     }
256 
257     public String getShowYear() {
258         return showYear;
259     }
260 
261     public void setShowYear(String showYear) {
262         this.showYear = showYear;
263     }
264 
265     public String getShowMonth() {
266         return showMonth;
267     }
268 
269     public void setShowMonth(String showMonth) {
270         this.showMonth = showMonth;
271     }
272 
273     public String getAnimalsYear() {
274         return animalsYear;
275     }
276 
277     public void setAnimalsYear(String animalsYear) {
278         this.animalsYear = animalsYear;
279     }
280 
281     public String getLeapMonth() {
282         return leapMonth;
283     }
284 
285     public void setLeapMonth(String leapMonth) {
286         this.leapMonth = leapMonth;
287     }
288 
289     public String getCyclical() {
290         return cyclical;
291     }
292 
293     public void setCyclical(String cyclical) {
294         this.cyclical = cyclical;
295     }
296 
297     /**
298      * @param position
299      * 设置点击的日期的颜色位置
300      */
301     public void setColorDataPosition(int position) {
302         if (position >= dayOfWeek && position < daysOfMonth + dayOfWeek) {
303             colorDataPosition = position;
304             notifyDataSetChanged();
305         }
306     }
307 }

6)重头戏还是这个MyCalendarView.java,毕竟,你其他的东西都是打辅助的,到后面,大家要用的还不是这个类。

MyCalendarView.java

  1 package com.example.nanchen.calendarviewdemo.view;
  2 
  3 import android.app.Activity;
  4 import android.content.Context;
  5 import android.graphics.Color;
  6 import android.graphics.drawable.ColorDrawable;
  7 import android.util.AttributeSet;
  8 import android.util.Log;
  9 import android.view.Display;
 10 import android.view.GestureDetector;
 11 import android.view.GestureDetector.SimpleOnGestureListener;
 12 import android.view.Gravity;
 13 import android.view.MotionEvent;
 14 import android.view.View;
 15 import android.view.View.OnClickListener;
 16 import android.view.WindowManager;
 17 import android.view.animation.AnimationUtils;
 18 import android.widget.AdapterView;
 19 import android.widget.AdapterView.OnItemClickListener;
 20 import android.widget.GridView;
 21 import android.widget.ImageView;
 22 import android.widget.LinearLayout;
 23 import android.widget.TextView;
 24 import android.widget.ViewFlipper;
 25 
 26 import com.example.nanchen.calendarviewdemo.R;
 27 
 28 import java.text.SimpleDateFormat;
 29 import java.util.Date;
 30 import java.util.Locale;
 31 
 32 
 33 /**
 34  * 自定义的日历控件
 35  *
 36  * @author nanchen
 37  * @date   2016-08-11 09:44:27
 38  */
 39 public class MyCalendarView extends LinearLayout implements OnClickListener {
 40 
 41     private final String TAG = MyCalendarView.class.getSimpleName();
 42     private int year_c = 0;// 今天的年份
 43     private int month_c = 0;// 今天的月份
 44     private int day_c = 0;// 今天的日期
 45     private String currentDate = "";//当前日期
 46     private Context mContext;
 47     private TextView currentMonth;// 显示日期
 48     private ImageView prevMonth;// 去上一个月
 49     private ImageView nextMonth;// 去下一个月
 50     private int gvFlag = 0;
 51     private GestureDetector gestureDetector = null;//用户手势检测
 52     private CalendarAdapter adapter = null;//适配器
 53     private ViewFlipper flipper = null;
 54     private GridView gridView = null;
 55     private static int jumpMonth = 0; // 每次滑动,增加或减去一个月,默认为0(即显示当前月)
 56     private static int jumpYear = 0; // 滑动跨越一年,则增加或者减去一年,默认为0(即当前年)
 57     private ClickDataListener clickDataListener;
 58 
 59     public MyCalendarView(Context context) {
 60         this(context, null);
 61     }
 62 
 63     public MyCalendarView(Context context, AttributeSet attrs) {
 64         super(context, attrs);
 65         mContext = context;
 66         initView();
 67     }
 68 
 69     /**
 70      * 初始化布局
 71      */
 72     private void initView() {
 73         //加载布局,一个头布局,一个横向的星期布局,下面一个ViewFlipper用于滑动
 74         View view = View.inflate(mContext, R.layout.calen_calendar, this);
 75         currentMonth = (TextView) view.findViewById(R.id.currentMonth);
 76         prevMonth = (ImageView) view.findViewById(R.id.prevMonth);
 77         nextMonth = (ImageView) view.findViewById(R.id.nextMonth);
 78         setListener();
 79         setCurrentDay();
 80         gestureDetector = new GestureDetector(mContext, new MyGestureListener());
 81         flipper = (ViewFlipper) findViewById(R.id.flipper);
 82         flipper.removeAllViews();
 83         adapter = new CalendarAdapter(mContext, getResources(), jumpMonth,
 84                 jumpYear, year_c, month_c, day_c);
 85         addGridView();
 86         gridView.setAdapter(adapter);
 87         flipper.addView(gridView, 0);
 88         addTextToTopTextView(currentMonth);
 89     }
 90 
 91     private void setListener() {
 92         prevMonth.setOnClickListener(this);
 93         nextMonth.setOnClickListener(this);
 94 
 95     }
 96 
 97     public void setClickDataListener(ClickDataListener clickDataListener) {
 98         this.clickDataListener = clickDataListener;
 99     }
100 
101     private void setCurrentDay() {
102         Date date = new Date();
103         SimpleDateFormat sdf = new SimpleDateFormat(FormatDate.DATE_FORMAT, Locale.CHINA);
104         currentDate = sdf.format(date); // 当期日期
105         year_c = Integer.parseInt(currentDate.split("-")[0]);
106         month_c = Integer.parseInt(currentDate.split("-")[1]);
107         day_c = Integer.parseInt(currentDate.split("-")[2]);
108     }
109 
110     /**
111      * 移动到下一个月
112      * 
113      * @param gvFlag
114      */
115     private void enterNextMonth(int gvFlag) {
116         addGridView(); // 添加一个gridView
117         jumpMonth++; // 下一个月
118         adapter = new CalendarAdapter(mContext, this.getResources(), jumpMonth,
119                 jumpYear, year_c, month_c, day_c);
120         gridView.setAdapter(adapter);
121         addTextToTopTextView(currentMonth); // 移动到下一月后,将当月显示在头标题中
122         gvFlag++;
123         flipper.addView(gridView, gvFlag);
124         flipper.setInAnimation(AnimationUtils.loadAnimation(mContext,
125                 R.anim.push_left_in));
126         flipper.setOutAnimation(AnimationUtils.loadAnimation(mContext,
127                 R.anim.push_left_out));
128         flipper.showNext();
129         flipper.removeViewAt(0);
130     }
131 
132     /**
133      * 移动到上一个月
134      * 
135      * @param gvFlag
136      */
137     private void enterPrevMonth(int gvFlag) {
138         addGridView(); // 添加一个gridView
139         jumpMonth--; // 上一个月
140 
141         adapter = new CalendarAdapter(mContext, this.getResources(), jumpMonth,
142                 jumpYear, year_c, month_c, day_c);
143         gridView.setAdapter(adapter);
144         gvFlag++;
145         addTextToTopTextView(currentMonth); // 移动到上一月后,将当月显示在头标题中
146         flipper.addView(gridView, gvFlag);
147 
148         flipper.setInAnimation(AnimationUtils.loadAnimation(mContext,
149                 R.anim.push_right_in));
150         flipper.setOutAnimation(AnimationUtils.loadAnimation(mContext,
151                 R.anim.push_right_out));
152         flipper.showPrevious();
153         flipper.removeViewAt(0);
154     }
155 
156     /**
157      * 添加头部的年份 闰哪月等信息
158      * 
159      * @param view
160      */
161     private void addTextToTopTextView(TextView view) {
162         StringBuffer textDate = new StringBuffer();
163         // draw = getResources().getDrawable(R.drawable.top_day);
164         // view.setBackgroundDrawable(draw);
165         textDate.append(adapter.getShowYear()).append("年")
166                 .append(adapter.getShowMonth()).append("月").append("\t");
167         view.setText(textDate);
168     }
169 
170     private void addGridView() {
171         LayoutParams params = new LayoutParams(
172                 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
173         // 取得屏幕的宽度和高度
174         WindowManager windowManager = ((Activity) mContext).getWindowManager();
175         Display display = windowManager.getDefaultDisplay();
176         int Width = display.getWidth();
177         int Height = display.getHeight();
178 
179         gridView = new GridView(mContext);
180         gridView.setNumColumns(7);
181         gridView.setColumnWidth(40);
182         // gridView.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
183         if (Width == 720 && Height == 1280) {
184             gridView.setColumnWidth(40);
185         }
186         gridView.setGravity(Gravity.CENTER_VERTICAL);
187         gridView.setSelector(new ColorDrawable(Color.TRANSPARENT));
188         // 去除gridView边框
189         gridView.setVerticalSpacing(0);
190         gridView.setHorizontalSpacing(0);
191         gridView.setOnTouchListener(new OnTouchListener() {
192             // 将gridview中的触摸事件回传给gestureDetector
193 
194             public boolean onTouch(View v, MotionEvent event) {
195                 // TODO Auto-generated method stub
196                 return gestureDetector.onTouchEvent(event);
197             }
198         });
199 
200         gridView.setOnItemClickListener(new OnItemClickListener() {
201 
202             @Override
203             public void onItemClick(AdapterView<?> arg0, View arg1,
204                     int position, long arg3) {
205                 // TODO Auto-generated method stub
206                 // 点击任何一个item,得到这个item的日期(排除点击的是周日到周六(点击不响应))
207                 int startPosition = adapter.getStartPositon();
208                 int endPosition = adapter.getEndPosition();
209                 if (startPosition <= position + 7
210                         && position <= endPosition - 7) {
211                     int scheduleDay = Integer.parseInt(adapter.getDateByClickItem(position)
212                             .split("\\.")[0]); // 这一天的阳历
213                     int scheduleYear = Integer.parseInt(adapter.getShowYear());
214                     int scheduleMonth = Integer.parseInt(adapter.getShowMonth());
215                     ((CalendarAdapter) arg0.getAdapter())
216                             .setColorDataPosition(position);
217                     if (clickDataListener != null) {
218                         clickDataListener.onClickData(scheduleYear,
219                                 scheduleMonth, scheduleDay);
220                     }
221                 }
222             }
223         });
224         gridView.setLayoutParams(params);
225     }
226 
227     @Override
228     public void onClick(View v) {
229         switch (v.getId()) {
230         case R.id.nextMonth: // 下一个月
231             enterNextMonth(gvFlag);
232             Log.d(TAG, "gvFlag=" + gvFlag);
233             break;
234         case R.id.prevMonth: // 上一个月
235             enterPrevMonth(gvFlag);
236             break;
237 
238         }
239 
240     }
241 
242     private static class MyGestureListener extends SimpleOnGestureListener {
243         private MyCalendarView calendarView;
244 
245         @Override
246         public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
247                 float velocityY) {
248             int gvFlag = 0; // 每次添加gridview到viewflipper中时给的标记
249             if (e1.getX() - e2.getX() > 120) {
250                 // 像左滑动
251                 calendarView.enterNextMonth(gvFlag);
252                 return true;
253             } else if (e1.getX() - e2.getX() < -120) {
254                 // 向右滑动
255                 calendarView.enterPrevMonth(gvFlag);
256                 return true;
257             }
258             return false;
259         }
260     }
261 }

这个,这个类没啥难的吧?看不懂?就跟一般的Activity处理一样,绑定布局,设置监听,做一些交互。

额,对,昨天写这个的时候搞得太复杂太复杂了。今天楼主全部放到xml文件中去了啦啦啦。

而且上面的布局和周几都不用刷新的,这不,直接放在Xml中定死就可以了嘛。

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical" >
 6 
 7     <LinearLayout
 8         android:layout_width="match_parent"
 9         android:layout_height="wrap_content"
10         android:orientation="horizontal" >
11 
12         <ImageView
13             android:id="@+id/prevMonth"
14             android:layout_width="0dp"
15             android:layout_height="wrap_content"
16             android:layout_gravity="center"
17             android:layout_weight="1"
18             android:src="@drawable/pre_month_selector" />
19 
20         <TextView
21             android:id="@+id/currentMonth"
22             android:layout_width="0dp"
23             android:layout_height="35dp"
24             android:layout_weight="3"
25             android:gravity="center"
26             android:text="2016年8月"
27             android:textColor="#177ed6"
28             android:textSize="18dp" />
29 
30         <ImageView
31             android:id="@+id/nextMonth"
32             android:layout_width="0dp"
33             android:layout_height="wrap_content"
34             android:layout_gravity="center"
35             android:layout_weight="1"
36             android:src="@drawable/next_month_selector" />
37     </LinearLayout>
38 
39 
40     <!--周几的布局-->
41     <LinearLayout
42         android:layout_width="match_parent"
43         android:layout_height="20dp"
44         android:background="#ffffffff" >
45 
46         <TextView
47             style="@style/weekName"
48             android:text="日"
49             android:textColor="#177ed6" />
50 
51         <TextView
52             style="@style/weekName"
53             android:text="一" />
54 
55         <TextView
56             style="@style/weekName"
57             android:text="二" />
58 
59         <TextView
60             style="@style/weekName"
61             android:text="三" />
62 
63         <TextView
64             style="@style/weekName"
65             android:text="四" />
66 
67         <TextView
68             style="@style/weekName"
69             android:text="五" />
70 
71         <TextView
72             style="@style/weekName"
73             android:text="六"
74             android:textColor="#177ed6" />
75     </LinearLayout>
76 
77     <View
78         android:layout_width="match_parent"
79         android:layout_height="1dp"
80         android:background="#ff8091a8" />
81 
82     <ViewFlipper
83         android:id="@+id/flipper"
84         android:layout_width="match_parent"
85         android:layout_height="wrap_content" />
86 </LinearLayout>

XML文件够简单吧~上部一个简单的title布局,中间一个水平的线性布局用于显示周几,下面一个ViewFlipper用于左右滑动。

额,两个Selector

pre_month_selector.xml

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

next_month_selector.xml

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

7)使用,MainActivity.java

 1 package com.example.nanchen.calendarviewdemo;
 2 
 3 import android.os.Bundle;
 4 import android.support.v7.app.AppCompatActivity;
 5 import android.widget.Toast;
 6 
 7 import com.example.nanchen.calendarviewdemo.view.MyCalendarView;
 8 import com.example.nanchen.calendarviewdemo.view.ClickDataListener;
 9 
10 import java.util.Locale;
11 
12 /**
13  * @author nanchen
14  * @date   2016-08-11 10:48:21
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         MyCalendarView myCalendarView = (MyCalendarView) findViewById(R.id.main_calendar);
24         myCalendarView.setClickDataListener(new ClickDataListener() {
25             @Override
26             public void onClickData(int year, int month, int day) {
27                 String date = String.format(Locale.CHINA,"%04d年%02d月%02d日",year,month,day);
28                 Toast.makeText(MainActivity.this,date,Toast.LENGTH_SHORT).show();
29             }
30         });
31     }
32 }

布局文件

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout
 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     android:orientation="vertical"
 8     tools:context="com.example.nanchen.calendarviewdemo.MainActivity">
 9 
10     <com.example.nanchen.calendarviewdemo.view.MyCalendarView
11         android:layout_width="match_parent"
12         android:layout_height="wrap_content"
13         android:id="@+id/main_calendar"/>
14 </LinearLayout>

 

更多详情源码请上github:https://github.com/nanchen2251/MyCalendarViewNewDemo

 

额,差不多啦,转载的小伙伴别忘了附上本文地址:http://www.cnblogs.com/liushilin/p/5763717.html

还是欢迎大家抨击,点赞,分享~你们的支持和打击是小主进步的源泉~

posted @ 2016-08-12 09:37  南尘  阅读(4112)  评论(16编辑  收藏  举报

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

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