Android实现自定义日历

时间:2021-09-05 07:28:07

自定义日历控件,支持旧历、节气、日期标注、点击操作 (参考网络上的日历控件改写)
注:将下面的四张资源图片拷贝到所建包的下一个image目录中,如calendar.java 所在包为
cc.util.android.view,则需要再创建一个包cc.util.android.view.image 然后将图片拷贝进去

  1. /****************从此出开始将代码拷贝到一个文件中*******************/ 
  2. package cc.util.android.view; 
  3.   
  4. import java.text.parseexception; 
  5. import java.text.simpledateformat; 
  6. import java.util.arraylist; 
  7. import java.util.calendar; 
  8. import java.util.date; 
  9. import java.util.list; 
  10. import java.util.locale; 
  11. import android.annotation.suppresslint; 
  12. import android.content.context; 
  13. import android.graphics.bitmapfactory; 
  14. import android.graphics.color; 
  15. import android.graphics.drawable.bitmapdrawable; 
  16. import android.graphics.drawable.drawable; 
  17. import android.graphics.drawable.statelistdrawable; 
  18. import android.text.textutils.truncateat; 
  19. import android.util.attributeset; 
  20. import android.view.gesturedetector; 
  21. import android.view.gesturedetector.ongesturelistener; 
  22. import android.view.gravity; 
  23. import android.view.motionevent; 
  24. import android.view.view; 
  25. import android.view.viewgroup; 
  26. import android.view.view.ontouchlistener; 
  27. import android.view.animation.animation; 
  28. import android.view.animation.animation.animationlistener; 
  29. import android.view.animation.translateanimation; 
  30. import android.widget.baseadapter; 
  31. import android.widget.gridview; 
  32. import android.widget.imagebutton; 
  33. import android.widget.linearlayout; 
  34. import android.widget.relativelayout; 
  35. import android.widget.textview; 
  36. import android.widget.viewflipper; 
  37. import android.widget.abslistview.layoutparams; 
  38.   
  39. /** 
  40.  * 日历控件,支持旧历、节气、日期标注、点击操作 (参考网络上的日历控件改写) 
  41.  * 
  42.  * @author wangcccong 
  43.  * @version 1.406 create at: mon, 03 sep. 2014 
  44.  * <br>update at: mon, 23 sep. 2014 
  45.  *   新增日期标注和点击操作 
  46.  */ 
  47. public class calendarview extends linearlayout implements ontouchlistener, 
  48.     animationlistener, ongesturelistener { 
  49.   
  50.   /** 
  51.    * 点击日历 
  52.    */ 
  53.   public interface oncalendarviewlistener { 
  54.     void oncalendaritemclick(calendarview view, date date); 
  55.   } 
  56.   
  57.   /** 顶部控件所占高度 */ 
  58.   private final static int top_height = 40; 
  59.   /** 日历item中默认id从0xff0000开始 */ 
  60.   private final static int default_id = 0xff0000; 
  61.   
  62.   // 判断手势用 
  63.   private static final int swipe_min_distance = 120; 
  64.   private static final int swipe_max_off_path = 250; 
  65.   private static final int swipe_threshold_velocity = 200; 
  66.   
  67.   // 屏幕宽度和高度 
  68.   private int screenwidth; 
  69.   
  70.   // 动画 
  71.   private animation slideleftin; 
  72.   private animation slideleftout; 
  73.   private animation sliderightin; 
  74.   private animation sliderightout; 
  75.   private viewflipper viewflipper; 
  76.   private gesturedetector mgesture = null
  77.   
  78.   /** 上一月 */ 
  79.   private gridview gview1; 
  80.   /** 当月 */ 
  81.   private gridview gview2; 
  82.   /** 下一月 */ 
  83.   private gridview gview3; 
  84.   
  85.   boolean bisselection = false;// 是否是选择事件发生 
  86.   private calendar calstartdate = calendar.getinstance();// 当前显示的日历 
  87.   private calendar calselected = calendar.getinstance(); // 选择的日历 
  88.   private calendargridviewadapter gadapter; 
  89.   private calendargridviewadapter gadapter1; 
  90.   private calendargridviewadapter gadapter3; 
  91.   
  92.   private linearlayout mmainlayout; 
  93.   private textview mtitle; // 显示年月 
  94.   
  95.   private int imonthviewcurrentmonth = 0; // 当前视图月 
  96.   private int imonthviewcurrentyear = 0; // 当前视图年 
  97.   
  98.   private static final int caltitlelayoutid = 66; // title布局id 
  99.   private static final int callayoutid = 55; // 日历布局id 
  100.   private context mcontext; 
  101.   
  102.   /** 标注日期 */ 
  103.   private final list<date> markdates; 
  104.   
  105.   private oncalendarviewlistener mlistener; 
  106.   
  107.   public calendarview(context context) { 
  108.     this(context, null); 
  109.   } 
  110.   
  111.   public calendarview(context context, attributeset attrs) { 
  112.     super(context, attrs); 
  113.     // todo auto-generated constructor stub 
  114.     mcontext = context; 
  115.     markdates = new arraylist<date>(); 
  116.     init(); 
  117.   } 
  118.   
  119.   // 初始化相关工作 
  120.   protected void init() { 
  121.     // 得到屏幕的宽度 
  122.     screenwidth = mcontext.getresources().getdisplaymetrics().widthpixels; 
  123.   
  124.     // 滑动的动画 
  125.     slideleftin = new translateanimation(screenwidth, 0, 0, 0); 
  126.     slideleftin.setduration(400); 
  127.     slideleftin.setanimationlistener(this); 
  128.     slideleftout = new translateanimation(0, -screenwidth, 0, 0); 
  129.     slideleftout.setduration(400); 
  130.     slideleftout.setanimationlistener(this); 
  131.     sliderightin = new translateanimation(-screenwidth, 0, 0, 0); 
  132.     sliderightin.setduration(400); 
  133.     sliderightin.setanimationlistener(this); 
  134.     sliderightout = new translateanimation(0, screenwidth, 0, 0); 
  135.     sliderightout.setduration(400); 
  136.     sliderightout.setanimationlistener(this); 
  137.   
  138.     // 手势操作 
  139.     mgesture = new gesturedetector(mcontext, this); 
  140.   
  141.     // 获取到当前日期 
  142.     updatestartdateformonth(); 
  143.     // 绘制界面 
  144.     setorientation(linearlayout.horizontal); 
  145.     mmainlayout = new linearlayout(mcontext); 
  146.     linearlayout.layoutparams main_params = new linearlayout.layoutparams( 
  147.         layoutparams.match_parent, layoutparams.wrap_content); 
  148.     mmainlayout.setlayoutparams(main_params); 
  149.     mmainlayout.setgravity(gravity.center_horizontal); 
  150.     mmainlayout.setorientation(linearlayout.vertical); 
  151.     addview(mmainlayout); 
  152.   
  153.     // 顶部控件 
  154.     generatetopview(); 
  155.   
  156.     // 中间显示星期 
  157.     generateweekgirdview(); 
  158.   
  159.     // 底部显示日历 
  160.     viewflipper = new viewflipper(mcontext); 
  161.     relativelayout.layoutparams fliper_params = new relativelayout.layoutparams( 
  162.         layoutparams.match_parent, layoutparams.wrap_content); 
  163.     fliper_params.addrule(relativelayout.below, caltitlelayoutid); 
  164.     mmainlayout.addview(viewflipper, fliper_params); 
  165.     generateclaendargirdview(); 
  166.   
  167.     // 最下方的一条线条 
  168.     linearlayout br = new linearlayout(mcontext); 
  169.     br.setbackgroundcolor(color.argb(0xff, 0xe3, 0xee, 0xf4)); 
  170.     linearlayout.layoutparams params_br = new linearlayout.layoutparams( 
  171.         layoutparams.match_parent, 3); 
  172.     mmainlayout.addview(br, params_br); 
  173.   } 
  174.   
  175.   /** 生成顶部控件 */ 
  176.   @suppresswarnings("deprecation"
  177.   private void generatetopview() { 
  178.     // 顶部显示上一个下一个,以及当前年月 
  179.     relativelayout top = new relativelayout(mcontext); 
  180.     top.setbackgroundcolor(color.argb(0xff, 0x0e, 0x6b, 0xc2)); 
  181.     linearlayout.layoutparams top_params = new linearlayout.layoutparams( 
  182.         layoutparams.match_parent, 
  183.         viewutil.dip2px(mcontext, top_height)); 
  184.     top.setlayoutparams(top_params); 
  185.     mmainlayout.addview(top); 
  186.     // 左方按钮、中间日期显示、右方按钮 
  187.     mtitle = new textview(mcontext); 
  188.     android.widget.relativelayout.layoutparams title_params = new android.widget.relativelayout.layoutparams( 
  189.         android.widget.relativelayout.layoutparams.match_parent, 
  190.         android.widget.relativelayout.layoutparams.match_parent); 
  191.     mtitle.setlayoutparams(title_params); 
  192.     mtitle.settextcolor(color.white); 
  193.     mtitle.settextsize(18); 
  194.     mtitle.setfocusableintouchmode(true); 
  195.     mtitle.setmarqueerepeatlimit(-1); 
  196.     mtitle.setellipsize(truncateat.marquee); 
  197.     mtitle.setsingleline(true); 
  198.     mtitle.setgravity(gravity.center); 
  199.     mtitle.sethorizontallyscrolling(true); 
  200.     mtitle.settext("2014年9月"); 
  201.     top.addview(mtitle); 
  202.   
  203.     // 左方按钮 
  204.     imagebutton mleftview = new imagebutton(mcontext); 
  205.     statelistdrawable statelistdrawablel = new statelistdrawable(); 
  206.     drawable ldrawablenor = new bitmapdrawable(mcontext.getresources(), 
  207.         bitmapfactory.decodestream(calendarview.class 
  208.             .getresourceasstream("image/left_arrow.png"))); 
  209.     drawable ldrawablepre = new bitmapdrawable(mcontext.getresources(), 
  210.         bitmapfactory.decodestream(calendarview.class 
  211.             .getresourceasstream("image/left_arrow_pre.png"))); 
  212.     statelistdrawablel.addstate( 
  213.         new int[] { -android.r.attr.state_pressed }, ldrawablenor); 
  214.     statelistdrawablel.addstate(new int[] { android.r.attr.state_pressed }, 
  215.         ldrawablepre); 
  216.     mleftview.setbackgrounddrawable(statelistdrawablel); 
  217.   
  218.     android.widget.relativelayout.layoutparams leftpp = new android.widget.relativelayout.layoutparams( 
  219.         viewutil.dip2px(mcontext, 25), viewutil.dip2px(mcontext, 22)); 
  220.     leftpp.addrule(relativelayout.align_parent_left); 
  221.     leftpp.addrule(relativelayout.center_vertical, relativelayout.true); 
  222.     leftpp.setmargins(20, 0, 0, 0); 
  223.     mleftview.setlayoutparams(leftpp); 
  224.     mleftview.setonclicklistener(new onclicklistener() { 
  225.   
  226.       @override 
  227.       public void onclick(view v) { 
  228.         // todo auto-generated method stub 
  229.         viewflipper.setinanimation(sliderightin); 
  230.         viewflipper.setoutanimation(sliderightout); 
  231.         viewflipper.showprevious(); 
  232.         setprevviewitem(); 
  233.       } 
  234.     }); 
  235.     top.addview(mleftview); 
  236.   
  237.     // 右方按钮 
  238.     imagebutton mrightview = new imagebutton(mcontext); 
  239.     statelistdrawable statelistdrawable = new statelistdrawable(); 
  240.     drawable rdrawablenor = new bitmapdrawable(mcontext.getresources(), 
  241.         bitmapfactory.decodestream(calendarview.class 
  242.             .getresourceasstream("image/right_arrow.png"))); 
  243.     drawable rdrawablepre = new bitmapdrawable(mcontext.getresources(), 
  244.         bitmapfactory.decodestream(calendarview.class 
  245.             .getresourceasstream("image/right_arrow_pre.png"))); 
  246.     statelistdrawable.addstate(new int[] { -android.r.attr.state_pressed }, 
  247.         rdrawablenor); 
  248.     statelistdrawable.addstate(new int[] { android.r.attr.state_pressed }, 
  249.         rdrawablepre); 
  250.     mrightview.setbackgrounddrawable(statelistdrawable); 
  251.   
  252.     android.widget.relativelayout.layoutparams rightpp = new android.widget.relativelayout.layoutparams( 
  253.         viewutil.dip2px(mcontext, 25), viewutil.dip2px(mcontext, 22)); 
  254.     rightpp.addrule(relativelayout.align_parent_right); 
  255.     rightpp.addrule(relativelayout.center_vertical, relativelayout.true); 
  256.     rightpp.setmargins(0, 0, 20, 0); 
  257.     mrightview.setlayoutparams(rightpp); 
  258.     mrightview.setonclicklistener(new onclicklistener() { 
  259.   
  260.       @override 
  261.       public void onclick(view v) { 
  262.         // todo auto-generated method stub 
  263.         viewflipper.setinanimation(slideleftin); 
  264.         viewflipper.setoutanimation(slideleftout); 
  265.         viewflipper.shownext(); 
  266.         setnextviewitem(); 
  267.       } 
  268.     }); 
  269.     top.addview(mrightview); 
  270.   } 
  271.   
  272.   /** 生成中间显示week */ 
  273.   private void generateweekgirdview() { 
  274.     gridview gridview = new gridview(mcontext); 
  275.     linearlayout.layoutparams params = new linearlayout.layoutparams( 
  276.         layoutparams.match_parent, layoutparams.wrap_content); 
  277.     gridview.setlayoutparams(params); 
  278.     gridview.setnumcolumns(7);// 设置每行列数 
  279.     gridview.setgravity(gravity.center_vertical);// 位置居中 
  280.     gridview.setverticalspacing(1);// 垂直间隔 
  281.     gridview.sethorizontalspacing(1);// 水平间隔 
  282.     gridview.setbackgroundcolor(color.argb(0xff, 0xe3, 0xee, 0xf4)); 
  283.   
  284.     int i = screenwidth / 7; 
  285.     int j = screenwidth - (i * 7); 
  286.     int x = j / 2; 
  287.     gridview.setpadding(x, 0, 0, 0);// 居中 
  288.     weekgridadapter weekadapter = new weekgridadapter(mcontext); 
  289.     gridview.setadapter(weekadapter);// 设置菜单adapter 
  290.     mmainlayout.addview(gridview); 
  291.   } 
  292.   
  293.   /** 生成底部日历 */ 
  294.   private void generateclaendargirdview() { 
  295.     calendar tempselected1 = calendar.getinstance(); // 临时 
  296.     calendar tempselected2 = calendar.getinstance(); // 临时 
  297.     calendar tempselected3 = calendar.getinstance(); // 临时 
  298.     tempselected1.settime(calstartdate.gettime()); 
  299.     tempselected2.settime(calstartdate.gettime()); 
  300.     tempselected3.settime(calstartdate.gettime()); 
  301.   
  302.     gview1 = new calendargridview(mcontext); 
  303.     tempselected1.add(calendar.month, -1); 
  304.     gadapter1 = new calendargridviewadapter(mcontext, tempselected1, 
  305.         markdates); 
  306.     gview1.setadapter(gadapter1);// 设置菜单adapter 
  307.     gview1.setid(callayoutid); 
  308.   
  309.     gview2 = new calendargridview(mcontext); 
  310.     gadapter = new calendargridviewadapter(mcontext, tempselected2, 
  311.         markdates); 
  312.     gview2.setadapter(gadapter);// 设置菜单adapter 
  313.     gview2.setid(callayoutid); 
  314.   
  315.     gview3 = new calendargridview(mcontext); 
  316.     tempselected3.add(calendar.month, 1); 
  317.     gadapter3 = new calendargridviewadapter(mcontext, tempselected3, 
  318.         markdates); 
  319.     gview3.setadapter(gadapter3);// 设置菜单adapter 
  320.     gview3.setid(callayoutid); 
  321.   
  322.     gview2.setontouchlistener(this); 
  323.     gview1.setontouchlistener(this); 
  324.     gview3.setontouchlistener(this); 
  325.   
  326.     if (viewflipper.getchildcount() != 0) { 
  327.       viewflipper.removeallviews(); 
  328.     } 
  329.   
  330.     viewflipper.addview(gview2); 
  331.     viewflipper.addview(gview3); 
  332.     viewflipper.addview(gview1); 
  333.   
  334.     string title = calstartdate.get(calendar.year) 
  335.         + "年" 
  336.         + numberhelper.leftpad_tow_zero(calstartdate 
  337.             .get(calendar.month) + 1) + "月"
  338.     mtitle.settext(title); 
  339.   } 
  340.   
  341.   // 上一个月 
  342.   private void setprevviewitem() { 
  343.     imonthviewcurrentmonth--;// 当前选择月-- 
  344.     // 如果当前月为负数的话显示上一年 
  345.     if (imonthviewcurrentmonth == -1) { 
  346.       imonthviewcurrentmonth = 11; 
  347.       imonthviewcurrentyear--; 
  348.     } 
  349.     calstartdate.set(calendar.day_of_month, 1); // 设置日为当月1日 
  350.     calstartdate.set(calendar.month, imonthviewcurrentmonth); // 设置月 
  351.     calstartdate.set(calendar.year, imonthviewcurrentyear); // 设置年 
  352.   } 
  353.   
  354.   // 下一个月 
  355.   private void setnextviewitem() { 
  356.     imonthviewcurrentmonth++; 
  357.     if (imonthviewcurrentmonth == 12) { 
  358.       imonthviewcurrentmonth = 0; 
  359.       imonthviewcurrentyear++; 
  360.     } 
  361.     calstartdate.set(calendar.day_of_month, 1); 
  362.     calstartdate.set(calendar.month, imonthviewcurrentmonth); 
  363.     calstartdate.set(calendar.year, imonthviewcurrentyear); 
  364.   } 
  365.   
  366.   // 根据改变的日期更新日历 
  367.   // 填充日历控件用 
  368.   private void updatestartdateformonth() { 
  369.     calstartdate.set(calendar.date, 1); // 设置成当月第一天 
  370.     imonthviewcurrentmonth = calstartdate.get(calendar.month);// 得到当前日历显示的月 
  371.     imonthviewcurrentyear = calstartdate.get(calendar.year);// 得到当前日历显示的年 
  372.   
  373.     // 星期一是2 星期天是1 填充剩余天数 
  374.     int iday = 0; 
  375.     int ifirstdayofweek = calendar.monday; 
  376.     int istartday = ifirstdayofweek; 
  377.     if (istartday == calendar.monday) { 
  378.       iday = calstartdate.get(calendar.day_of_week) - calendar.monday; 
  379.       if (iday < 0) 
  380.         iday = 6; 
  381.     } 
  382.     if (istartday == calendar.sunday) { 
  383.       iday = calstartdate.get(calendar.day_of_week) - calendar.sunday; 
  384.       if (iday < 0) 
  385.         iday = 6; 
  386.     } 
  387.     calstartdate.add(calendar.day_of_week, -iday); 
  388.   } 
  389.   
  390.   /** 
  391.    * 设置标注的日期 
  392.    * 
  393.    * @param markdates 
  394.    */ 
  395.   public void setmarkdates(list<date> markdates) { 
  396.     this.markdates.clear(); 
  397.     this.markdates.addall(markdates); 
  398.     gadapter.notifydatasetchanged(); 
  399.     gadapter1.notifydatasetchanged(); 
  400.     gadapter3.notifydatasetchanged(); 
  401.   } 
  402.   
  403.   /** 
  404.    * 设置点击日历监听 
  405.    * 
  406.    * @param listener 
  407.    */ 
  408.   public void setoncalendarviewlistener(oncalendarviewlistener listener) { 
  409.     this.mlistener = listener; 
  410.   } 
  411.   
  412.   @override 
  413.   public boolean ondown(motionevent e) { 
  414.     // todo auto-generated method stub 
  415.     return false
  416.   } 
  417.   
  418.   @suppresslint("clickableviewaccessibility"
  419.   @override 
  420.   public boolean ontouch(view v, motionevent event) { 
  421.     return mgesture.ontouchevent(event); 
  422.   } 
  423.   
  424.   @override 
  425.   public boolean onfling(motionevent e1, motionevent e2, float velocityx, 
  426.       float velocityy) { 
  427.     // todo auto-generated method stub 
  428.     try { 
  429.       if (math.abs(e1.gety() - e2.gety()) > swipe_max_off_path) 
  430.         return false
  431.       // right to left swipe 
  432.       if (e1.getx() - e2.getx() > swipe_min_distance 
  433.           && math.abs(velocityx) > swipe_threshold_velocity) { 
  434.         viewflipper.setinanimation(slideleftin); 
  435.         viewflipper.setoutanimation(slideleftout); 
  436.         viewflipper.shownext(); 
  437.         setnextviewitem(); 
  438.         return true
  439.   
  440.       } else if (e2.getx() - e1.getx() > swipe_min_distance 
  441.           && math.abs(velocityx) > swipe_threshold_velocity) { 
  442.         viewflipper.setinanimation(sliderightin); 
  443.         viewflipper.setoutanimation(sliderightout); 
  444.         viewflipper.showprevious(); 
  445.         setprevviewitem(); 
  446.         return true
  447.   
  448.       } 
  449.     } catch (exception e) { 
  450.       // nothing 
  451.     } 
  452.     return false
  453.   } 
  454.   
  455.   @override 
  456.   public void onlongpress(motionevent e) { 
  457.     // todo auto-generated method stub 
  458.   
  459.   } 
  460.   
  461.   @override 
  462.   public boolean onscroll(motionevent e1, motionevent e2, float distancex, 
  463.       float distancey) { 
  464.     // todo auto-generated method stub 
  465.     return false
  466.   } 
  467.   
  468.   @override 
  469.   public void onshowpress(motionevent e) { 
  470.     // todo auto-generated method stub 
  471.   
  472.   } 
  473.   
  474.   @override 
  475.   public boolean onsingletapup(motionevent e) { 
  476.     // todo auto-generated method stub 
  477.     // 得到当前选中的是第几个单元格 
  478.     int pos = gview2.pointtoposition((int) e.getx(), (int) e.gety()); 
  479.     linearlayout txtday = (linearlayout) gview2.findviewbyid(pos 
  480.         + default_id); 
  481.     if (txtday != null) { 
  482.       if (txtday.gettag() != null) { 
  483.         date date = (date) txtday.gettag(); 
  484.         calselected.settime(date); 
  485.   
  486.         gadapter.setselecteddate(calselected); 
  487.         gadapter.notifydatasetchanged(); 
  488.   
  489.         gadapter1.setselecteddate(calselected); 
  490.         gadapter1.notifydatasetchanged(); 
  491.   
  492.         gadapter3.setselecteddate(calselected); 
  493.         gadapter3.notifydatasetchanged(); 
  494.         if (mlistener != null
  495.           mlistener.oncalendaritemclick(this, date); 
  496.       } 
  497.     } 
  498.     return false
  499.   } 
  500.   
  501.   @override 
  502.   public void onanimationend(animation animation) { 
  503.     // todo auto-generated method stub 
  504.     generateclaendargirdview(); 
  505.   } 
  506.   
  507.   @override 
  508.   public void onanimationrepeat(animation animation) { 
  509.     // todo auto-generated method stub 
  510.   
  511.   } 
  512.   
  513.   @override 
  514.   public void onanimationstart(animation animation) { 
  515.     // todo auto-generated method stub 
  516.   
  517.   } 
  518.   
  519.   
  520. /** 
  521.  * 显示week的布局adapter 
  522.  * 
  523.  */ 
  524. class weekgridadapter extends baseadapter { 
  525.   
  526.   final string[] titles = new string[] { "日""一""二""三""四""五""六" }; 
  527.   private context mcontext; 
  528.   
  529.   public weekgridadapter(context context) { 
  530.     this.mcontext = context; 
  531.   } 
  532.   
  533.   @override 
  534.   public int getcount() { 
  535.     return titles.length; 
  536.   } 
  537.   
  538.   @override 
  539.   public object getitem(int position) { 
  540.     return titles[position]; 
  541.   } 
  542.   
  543.   @override 
  544.   public long getitemid(int position) { 
  545.     return position; 
  546.   } 
  547.   
  548.   @override 
  549.   public view getview(int position, view convertview, viewgroup parent) { 
  550.     textview week = new textview(mcontext); 
  551.     android.view.viewgroup.layoutparams week_params = new layoutparams( 
  552.         android.view.viewgroup.layoutparams.match_parent, 
  553.         android.view.viewgroup.layoutparams.match_parent); 
  554.     week.setlayoutparams(week_params); 
  555.     week.setpadding(0, 0, 0, 0); 
  556.     week.setgravity(gravity.center); 
  557.     week.setfocusable(false); 
  558.     week.setbackgroundcolor(color.transparent); 
  559.   
  560.     if (position == 6) { // 周六 
  561.       week.setbackgroundcolor(color.argb(0xff, 0x52, 0x9b, 0xd0)); 
  562.       week.settextcolor(color.white); 
  563.     } else if (position == 0) { // 周日 
  564.       week.setbackgroundcolor(color.argb(0xff, 0xbc, 0x44, 0x45)); 
  565.       week.settextcolor(color.white); 
  566.     } else { 
  567.       week.settextcolor(color.black); 
  568.     } 
  569.     week.settext(getitem(position) + ""); 
  570.     return week; 
  571.   } 
  572.   
  573. /** 
  574.  * 显示日期的adapter 
  575.  */ 
  576. class calendargridviewadapter extends baseadapter { 
  577.   
  578.   /** 日历item中默认id从0xff0000开始 */ 
  579.   private final static int default_id = 0xff0000; 
  580.   private calendar calstartdate = calendar.getinstance();// 当前显示的日历 
  581.   private calendar calselected = calendar.getinstance(); // 选择的日历 
  582.   
  583.   /** 标注的日期 */ 
  584.   private list<date> markdates; 
  585.   
  586.   private context mcontext; 
  587.   
  588.   private calendar caltoday = calendar.getinstance(); // 今日 
  589.   private arraylist<java.util.date> titles; 
  590.   
  591.   private arraylist<java.util.date> getdates() { 
  592.   
  593.     updatestartdateformonth(); 
  594.   
  595.     arraylist<java.util.date> alarraylist = new arraylist<java.util.date>(); 
  596.   
  597.     for (int i = 1; i <= 42; i++) { 
  598.       alarraylist.add(calstartdate.gettime()); 
  599.       calstartdate.add(calendar.day_of_month, 1); 
  600.     } 
  601.   
  602.     return alarraylist; 
  603.   } 
  604.   
  605.   // construct 
  606.   public calendargridviewadapter(context context, calendar cal, list<date> dates) { 
  607.     calstartdate = cal; 
  608.     this.mcontext = context; 
  609.     titles = getdates(); 
  610.     this.markdates = dates; 
  611.   } 
  612.   
  613.   public calendargridviewadapter(context context) { 
  614.     this.mcontext = context; 
  615.   } 
  616.   
  617.   @override 
  618.   public int getcount() { 
  619.     return titles.size(); 
  620.   } 
  621.   
  622.   @override 
  623.   public object getitem(int position) { 
  624.     return titles.get(position); 
  625.   } 
  626.   
  627.   @override 
  628.   public long getitemid(int position) { 
  629.     return position; 
  630.   } 
  631.   
  632.   @suppresswarnings("deprecation"
  633.   @override 
  634.   public view getview(int position, view convertview, viewgroup parent) { 
  635.     // 整个item 
  636.     linearlayout itemlayout = new linearlayout(mcontext); 
  637.     itemlayout.setid(position + default_id); 
  638.     itemlayout.setgravity(gravity.center); 
  639.     itemlayout.setorientation(1); 
  640.     itemlayout.setbackgroundcolor(color.white); 
  641.   
  642.     date mydate = (date) getitem(position); 
  643.     itemlayout.settag(mydate); 
  644.     calendar calcalendar = calendar.getinstance(); 
  645.     calcalendar.settime(mydate); 
  646.   
  647.     // 显示日期day 
  648.     textview textday = new textview(mcontext);// 日期 
  649.     linearlayout.layoutparams text_params = new linearlayout.layoutparams( 
  650.         layoutparams.match_parent, layoutparams.wrap_content); 
  651.     textday.setgravity(gravity.center_horizontal); 
  652.     int day = mydate.getdate(); // 日期 
  653.     textday.settext(string.valueof(day)); 
  654.     textday.setid(position + default_id); 
  655.     itemlayout.addview(textday, text_params); 
  656.   
  657.     // 显示公历 
  658.     textview chineseday = new textview(mcontext); 
  659.     linearlayout.layoutparams chinese_params = new linearlayout.layoutparams( 
  660.         layoutparams.match_parent, layoutparams.wrap_content); 
  661.     chineseday.setgravity(gravity.center_horizontal); 
  662.     chineseday.settextsize(9); 
  663.     calendarutil calendarutil = new calendarutil(calcalendar); 
  664.     chineseday.settext(calendarutil.tostring()); 
  665.     itemlayout.addview(chineseday, chinese_params); 
  666.   
  667.     // 如果是当前日期则显示不同颜色 
  668.     if (equalsdate(caltoday.gettime(), mydate)) { 
  669.       itemlayout.setbackgroundcolor(color.argb(0xff, 0x6d, 0xd6, 0x97)); 
  670.     } 
  671.   
  672.     // 这里用于比对是不是比当前日期小,如果比当前日期小则显示浅灰色 
  673.     if (!calendarutil.compare(mydate, caltoday.gettime())) { 
  674.       itemlayout.setbackgroundcolor(color.argb(0xff, 0xee, 0xee, 0xee)); 
  675.       textday.settextcolor(color.argb(0xff, 0xc0, 0xc0, 0xc0)); 
  676.       chineseday.settextcolor(color.argb(0xff, 0xc0, 0xc0, 0xc0)); 
  677.     } else { 
  678.       chineseday.settextcolor(color.argb(0xff, 0xc2, 0xa5, 0x3d)); 
  679.       chineseday.settextcolor(color.argb(0xff, 0x60, 0x3b, 0x07)); 
  680.       // 设置背景颜色 
  681.       if (equalsdate(calselected.gettime(), mydate)) { 
  682.         // 选择的 
  683.         itemlayout.setbackgroundcolor(color.argb(0xff, 0xdc, 0xe2, 0xff)); 
  684.       } else { 
  685.         if (equalsdate(caltoday.gettime(), mydate)) { 
  686.           // 当前日期faedda 
  687.           itemlayout.setbackgroundcolor(color.argb(0xff, 0xfa, 0xed, 0xda)); 
  688.         } 
  689.       } 
  690.     } 
  691.     /** 设置标注日期颜色 */ 
  692.     if (markdates != null) { 
  693.       final simpledateformat format = new simpledateformat("yyyy-mm-dd", locale.china); 
  694.       for (date date : markdates) { 
  695.         if (format.format(mydate).equals(format.format(date))) { 
  696.           itemlayout.setbackgroundcolor(color.argb(0xff, 0xd3, 0x3a, 0x3a)); 
  697.           break
  698.         } 
  699.       } 
  700.     } 
  701.     return itemlayout; 
  702.   } 
  703.   
  704.   @override 
  705.   public void notifydatasetchanged() { 
  706.     super.notifydatasetchanged(); 
  707.   } 
  708.   
  709.   @suppresswarnings("deprecation"
  710.   private boolean equalsdate(date date1, date date2) { 
  711.     if (date1.getyear() == date2.getyear() 
  712.         && date1.getmonth() == date2.getmonth() 
  713.         && date1.getdate() == date2.getdate()) { 
  714.       return true
  715.     } else { 
  716.       return false
  717.     } 
  718.   
  719.   } 
  720.   
  721.   // 根据改变的日期更新日历 
  722.   // 填充日历控件用 
  723.   private void updatestartdateformonth() { 
  724.     calstartdate.set(calendar.date, 1); // 设置成当月第一天 
  725.   
  726.     // 星期一是2 星期天是1 填充剩余天数 
  727.     int iday = 0; 
  728.     int ifirstdayofweek = calendar.monday; 
  729.     int istartday = ifirstdayofweek; 
  730.     if (istartday == calendar.monday) { 
  731.       iday = calstartdate.get(calendar.day_of_week) - calendar.monday; 
  732.       if (iday < 0) 
  733.         iday = 6; 
  734.     } 
  735.     if (istartday == calendar.sunday) { 
  736.       iday = calstartdate.get(calendar.day_of_week) - calendar.sunday; 
  737.       if (iday < 0) 
  738.         iday = 6; 
  739.     } 
  740.     calstartdate.add(calendar.day_of_week, -iday); 
  741.     calstartdate.add(calendar.day_of_month, -1);// 周日第一位 
  742.   } 
  743.   
  744.   public void setselecteddate(calendar cal) { 
  745.     calselected = cal; 
  746.   } 
  747.   
  748.   
  749. /** 
  750.  * 用于生成日历展示的gridview布局 
  751.  */ 
  752. class calendargridview extends gridview { 
  753.   
  754.   /** 
  755.    * 当前操作的上下文对象 
  756.    */ 
  757.   private context mcontext; 
  758.   
  759.   /** 
  760.    * calendargridview 构造器 
  761.    * 
  762.    * @param context 
  763.    *      当前操作的上下文对象 
  764.    */ 
  765.   public calendargridview(context context) { 
  766.     super(context); 
  767.     mcontext = context; 
  768.     initgirdview(); 
  769.   } 
  770.   
  771.   /** 
  772.    * 初始化gridview 控件的布局 
  773.    */ 
  774.   private void initgirdview() { 
  775.     linearlayout.layoutparams params = new linearlayout.layoutparams( 
  776.         layoutparams.match_parent, layoutparams.wrap_content); 
  777.     setlayoutparams(params); 
  778.     setnumcolumns(7);// 设置每行列数 
  779.     setgravity(gravity.center_vertical);// 位置居中 
  780.     setverticalspacing(1);// 垂直间隔 
  781.     sethorizontalspacing(1);// 水平间隔 
  782.     setbackgroundcolor(color.argb(0xff, 0xe3, 0xee, 0xf4)); 
  783.   
  784.     int i = mcontext.getresources().getdisplaymetrics().widthpixels / 7; 
  785.     int j = mcontext.getresources().getdisplaymetrics().widthpixels 
  786.         - (i * 7); 
  787.     int x = j / 2; 
  788.     setpadding(x, 0, 0, 0);// 居中 
  789.   } 
  790.   
  791. /** 
  792.  * 把公历时间处理成农历时间 
  793.  * 
  794.  */ 
  795. class calendarutil { 
  796.   /** 
  797.    * 用于保存中文的月份 
  798.    */ 
  799.   private final static string chinese_number[] = { "一""二""三""四""五"
  800.       "六""七""八""九""十""十一""腊" }; 
  801.   
  802.   /** 
  803.    * 用于保存展示周几使用 
  804.    */ 
  805.   private final static string week_number[] = { "日""一""二""三""四""五"
  806.       "六" }; 
  807.   
  808.   private final static long[] lunar_info = new long[] { 0x04bd8, 0x04ae0, 
  809.       0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 
  810.       0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 
  811.       0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 
  812.       0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 
  813.       0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 
  814.       0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 
  815.       0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 
  816.       0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 
  817.       0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 
  818.       0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 
  819.       0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 
  820.       0x195a6, 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 
  821.       0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 
  822.       0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0, 
  823.       0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 
  824.       0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 
  825.       0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 
  826.       0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 
  827.       0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 
  828.       0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 
  829.       0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 
  830.       0x0ada0 }; 
  831.   
  832.   /** 
  833.    * 转换为2012年11月22日格式 
  834.    */ 
  835.   private static simpledateformat chinesedateformat = new simpledateformat( 
  836.       "yyyy年mm月dd日"); 
  837.   /** 
  838.    * 转换为2012-11-22格式 
  839.    */ 
  840.   private static simpledateformat simpledateformat = new simpledateformat( 
  841.       "yyyy-mm-dd"); 
  842.   
  843.   /** 
  844.    * 计算得到农历的年份 
  845.    */ 
  846.   private int mluchyear; 
  847.   /** 
  848.    * 计算得到农历的月份 
  849.    */ 
  850.   private int mluchmonth; 
  851.   
  852.   /** 
  853.    * 计算得到农历的日期 
  854.    */ 
  855.   private int mluchday; 
  856.   
  857.   /** 
  858.    * 用于标识是事为闰年 
  859.    */ 
  860.   private boolean isloap; 
  861.   
  862.   /** 
  863.    * 用于记录当前处理的时间 
  864.    */ 
  865.   private calendar mcurrencalendar; 
  866.   
  867.   /** 
  868.    * 传回农历 year年的总天数 
  869.    * 
  870.    * @param year 
  871.    *      将要计算的年份 
  872.    * @return 返回传入年份的总天数 
  873.    */ 
  874.   private static int yeardays(int year) { 
  875.     int i, sum = 348; 
  876.     for (i = 0x8000; i > 0x8; i >>= 1) { 
  877.       if ((lunar_info[year - 1900] & i) != 0) 
  878.         sum += 1; 
  879.     } 
  880.     return (sum + leapdays(year)); 
  881.   } 
  882.   
  883.   /** 
  884.    * 传回农历 year年闰月的天数 
  885.    * 
  886.    * @param year 
  887.    *      将要计算的年份 
  888.    * @return 返回 农历 year年闰月的天数 
  889.    */ 
  890.   private static int leapdays(int year) { 
  891.     if (leapmonth(year) != 0) { 
  892.       if ((lunar_info[year - 1900] & 0x10000) != 0) 
  893.         return 30; 
  894.       else 
  895.         return 29; 
  896.     } else 
  897.       return 0; 
  898.   } 
  899.   
  900.   /** 
  901.    * 传回农历 year年闰哪个月 1-12 , 没闰传回 0 
  902.    * 
  903.    * @param year 
  904.    *      将要计算的年份 
  905.    * @return 传回农历 year年闰哪个月 1-12 , 没闰传回 0 
  906.    */ 
  907.   private static int leapmonth(int year) { 
  908.     return (int) (lunar_info[year - 1900] & 0xf); 
  909.   } 
  910.   
  911.   /** 
  912.    * 传回农历 year年month月的总天数 
  913.    * 
  914.    * @param year 
  915.    *      将要计算的年份 
  916.    * @param month 
  917.    *      将要计算的月份 
  918.    * @return 传回农历 year年month月的总天数 
  919.    */ 
  920.   private static int monthdays(int year, int month) { 
  921.     if ((lunar_info[year - 1900] & (0x10000 >> month)) == 0) 
  922.       return 29; 
  923.     else 
  924.       return 30; 
  925.   } 
  926.   
  927.   /** 
  928.    * 传回农历 y年的生肖 
  929.    * 
  930.    * @return 传回农历 y年的生肖 
  931.    */ 
  932.   public string animalsyear() { 
  933.     final string[] animals = new string[] { "鼠""牛""虎""兔""龙""蛇"
  934.         "马""羊""猴""鸡""狗""猪" }; 
  935.     return animals[(mluchyear - 4) % 12]; 
  936.   } 
  937.   
  938.   // ====== 传入 月日的offset 传回干支, 0=甲子 
  939.   private static string cyclicalm(int num) { 
  940.     final string[] gan = new string[] { "甲""乙""丙""丁""戊""己""庚"
  941.         "辛""壬""癸" }; 
  942.     final string[] zhi = new string[] { "子""丑""寅""卯""辰""巳""午"
  943.         "未""申""酉""戌""亥" }; 
  944.   
  945.     return (gan[num % 10] + zhi[num % 12]); 
  946.   } 
  947.   
  948.   // ====== 传入 offset 传回干支, 0=甲子 
  949.   public string cyclical() { 
  950.     int num = mluchyear - 1900 + 36; 
  951.     return (cyclicalm(num)); 
  952.   } 
  953.   
  954.   /** 
  955.    * 传出y年m月d日对应的农历. yearcyl3:农历年与1864的相差数 ? moncyl4:从1900年1月31日以来,闰月数 
  956.    * daycyl5:与1900年1月31日相差的天数,再加40 ? 
  957.    * 
  958.    * @param cal 
  959.    * @return 
  960.    */ 
  961.   public calendarutil(calendar cal) { 
  962.     mcurrencalendar = cal; 
  963.     int leapmonth = 0; 
  964.     date basedate = null
  965.     try { 
  966.       basedate = chinesedateformat.parse("1900年1月31日"); 
  967.     } catch (parseexception e) { 
  968.       e.printstacktrace(); // to change body of catch statement use 
  969.       // options | file templates. 
  970.     } 
  971.   
  972.     // 求出和1900年1月31日相差的天数 
  973.     int offset = (int) ((cal.gettime().gettime() - basedate.gettime()) / 86400000l); 
  974.     // 用offset减去每农历年的天数 
  975.     // 计算当天是农历第几天 
  976.     // i最终结果是农历的年份 
  977.     // offset是当年的第几天 
  978.     int iyear, daysofyear = 0; 
  979.     for (iyear = 1900; iyear < 2050 && offset > 0; iyear++) { 
  980.       daysofyear = yeardays(iyear); 
  981.       offset -= daysofyear; 
  982.     } 
  983.     if (offset < 0) { 
  984.       offset += daysofyear; 
  985.       iyear--; 
  986.     } 
  987.     // 农历年份 
  988.     mluchyear = iyear; 
  989.   
  990.     leapmonth = leapmonth(iyear); // 闰哪个月,1-12 
  991.     isloap = false
  992.   
  993.     // 用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天 
  994.     int imonth, daysofmonth = 0; 
  995.     for (imonth = 1; imonth < 13 && offset > 0; imonth++) { 
  996.       // 闰月 
  997.       if (leapmonth > 0 && imonth == (leapmonth + 1) && !isloap) { 
  998.         --imonth; 
  999.         isloap = true
  1000.         daysofmonth = leapdays(mluchyear); 
  1001.       } else 
  1002.         daysofmonth = monthdays(mluchyear, imonth); 
  1003.   
  1004.       offset -= daysofmonth; 
  1005.       // 解除闰月 
  1006.       if (isloap && imonth == (leapmonth + 1)) 
  1007.         isloap = false
  1008.       if (!isloap) { 
  1009.       } 
  1010.     } 
  1011.     // offset为0时,并且刚才计算的月份是闰月,要校正 
  1012.     if (offset == 0 && leapmonth > 0 && imonth == leapmonth + 1) { 
  1013.       if (isloap) { 
  1014.         isloap = false
  1015.       } else { 
  1016.         isloap = true
  1017.         --imonth; 
  1018.       } 
  1019.     } 
  1020.     // offset小于0时,也要校正 
  1021.     if (offset < 0) { 
  1022.       offset += daysofmonth; 
  1023.       --imonth; 
  1024.   
  1025.     } 
  1026.     mluchmonth = imonth; 
  1027.     mluchday = offset + 1; 
  1028.   } 
  1029.   
  1030.   /** 
  1031.    * 返化成中文格式 
  1032.    * 
  1033.    * @param day 
  1034.    * @return 
  1035.    */ 
  1036.   public static string getchinadaystring(int day) { 
  1037.     string chineseten[] = { "初""十""廿""卅" }; 
  1038.     int n = day % 10 == 0 ? 9 : day % 10 - 1; 
  1039.     if (day > 30) 
  1040.       return ""
  1041.     if (day == 10) 
  1042.       return "初十"
  1043.     else 
  1044.       return chineseten[day / 10] + chinese_number[n]; 
  1045.   } 
  1046.   
  1047.   /** 
  1048.    * 用于显示农历的初几这种格式 
  1049.    * 
  1050.    * @return 农历的日期 
  1051.    */ 
  1052.   public string tostring() { 
  1053.     string message = ""
  1054.     // int n = mluchday % 10 == 0 ? 9 : mluchday % 10 - 1; 
  1055.     message = getchinacalendarmsg(mluchyear, mluchmonth, mluchday); 
  1056.     if (stringutil.isnullorempty(message)) { 
  1057.       string solarmsg = new solartermsutil(mcurrencalendar) 
  1058.           .getsolartermsmsg(); 
  1059.       // 判断当前日期是否为节气 
  1060.       if (!stringutil.isnullorempty(solarmsg)) { 
  1061.         message = solarmsg; 
  1062.       } else { 
  1063.         /** 
  1064.          * 判断当前日期是否为公历节日 
  1065.          */ 
  1066.         string gremessage = new gregorianutil(mcurrencalendar) 
  1067.             .getgremessage(); 
  1068.         if (!stringutil.isnullorempty(gremessage)) { 
  1069.           message = gremessage; 
  1070.         } else if (mluchday == 1) { 
  1071.           message = chinese_number[mluchmonth - 1] + "月"
  1072.         } else { 
  1073.           message = getchinadaystring(mluchday); 
  1074.         } 
  1075.   
  1076.       } 
  1077.     } 
  1078.     return message; 
  1079.   } 
  1080.   
  1081.   /** 
  1082.    * 返回农历的年月日 
  1083.    * 
  1084.    * @return 农历的年月日格式 
  1085.    */ 
  1086.   public string getday() { 
  1087.     return (isloap ? "闰" : "") + chinese_number[mluchmonth - 1] + "月" 
  1088.         + getchinadaystring(mluchday); 
  1089.   } 
  1090.   
  1091.   /** 
  1092.    * 把calendar转化为当前年月日 
  1093.    * 
  1094.    * @param calendar 
  1095.    *      calendar 
  1096.    * @return 返回成转换好的 年月日格式 
  1097.    */ 
  1098.   public static string getday(calendar calendar) { 
  1099.     return simpledateformat.format(calendar.gettime()); 
  1100.   } 
  1101.   
  1102.   /** 
  1103.    * 用于比对二个日期的大小 
  1104.    * 
  1105.    * @param comparedate 
  1106.    *      将要比对的时间 
  1107.    * @param currentdate 
  1108.    *      当前时间 
  1109.    * @return true 表示大于当前时间 false 表示小于当前时间 
  1110.    */ 
  1111.   public static boolean compare(date comparedate, date currentdate) { 
  1112.     return chinesedateformat.format(comparedate).compareto( 
  1113.         chinesedateformat.format(currentdate)) >= 0; 
  1114.   } 
  1115.   
  1116.   /** 
  1117.    * 获取当前周几 
  1118.    * 
  1119.    * @param calendar 
  1120.    * @return 
  1121.    */ 
  1122.   public static string getweek(calendar calendar) { 
  1123.     return "周" + week_number[calendar.get(calendar.day_of_week) - 1] + ""
  1124.   } 
  1125.   
  1126.   /** 
  1127.    * 将当前时间转换成要展示的形式 
  1128.    * 
  1129.    * @param calendar 
  1130.    * @return 
  1131.    */ 
  1132.   public static string getcurrentday(calendar calendar) { 
  1133.     return getday(calendar) + " 农历" + new calendarutil(calendar).getday() 
  1134.         + " " + getweek(calendar); 
  1135.   } 
  1136.   
  1137.   /** 
  1138.    * 用于获取中国的传统节日 
  1139.    * 
  1140.    * @param month 
  1141.    *      农历的月 
  1142.    * @param day 
  1143.    *      农历日 
  1144.    * @return 中国传统节日 
  1145.    */ 
  1146.   private string getchinacalendarmsg(int year, int month, int day) { 
  1147.     string message = ""
  1148.     if (((month) == 1) && day == 1) { 
  1149.       message = "春节"
  1150.     } else if (((month) == 1) && day == 15) { 
  1151.       message = "元宵"
  1152.     } else if (((month) == 5) && day == 5) { 
  1153.       message = "端午"
  1154.     } else if ((month == 7) && day == 7) { 
  1155.       message = "七夕"
  1156.     } else if (((month) == 8) && day == 15) { 
  1157.       message = "中秋"
  1158.     } else if ((month == 9) && day == 9) { 
  1159.       message = "重阳"
  1160.     } else if ((month == 12) && day == 8) { 
  1161.       message = "腊八"
  1162.     } else { 
  1163.       if (month == 12) { 
  1164.         if ((((monthdays(year, month) == 29) && day == 29)) 
  1165.             || ((((monthdays(year, month) == 30) && day == 30)))) { 
  1166.           message = "除夕"
  1167.         } 
  1168.       } 
  1169.     } 
  1170.     return message; 
  1171.   } 
  1172.   
  1173. /** 
  1174.  * 字符串的处理类 
  1175.  */ 
  1176. class stringutil { 
  1177.   /** 
  1178.    * 判断是否为null或空值 
  1179.    * 
  1180.    * @param str 
  1181.    *      string 
  1182.    * @return true or false 
  1183.    */ 
  1184.   public static boolean isnullorempty(string str) { 
  1185.     return str == null || str.trim().length() == 0; 
  1186.   } 
  1187.   
  1188.   /** 
  1189.    * 判断str1和str2是否相同 
  1190.    * 
  1191.    * @param str1 
  1192.    *      str1 
  1193.    * @param str2 
  1194.    *      str2 
  1195.    * @return true or false 
  1196.    */ 
  1197.   public static boolean equals(string str1, string str2) { 
  1198.     return str1 == str2 || str1 != null && str1.equals(str2); 
  1199.   } 
  1200.   
  1201.   /** 
  1202.    * 判断str1和str2是否相同(不区分大小写) 
  1203.    * 
  1204.    * @param str1 
  1205.    *      str1 
  1206.    * @param str2 
  1207.    *      str2 
  1208.    * @return true or false 
  1209.    */ 
  1210.   public static boolean equalsignorecase(string str1, string str2) { 
  1211.     return str1 != null && str1.equalsignorecase(str2); 
  1212.   } 
  1213.   
  1214.   /** 
  1215.    * 判断字符串str1是否包含字符串str2 
  1216.    * 
  1217.    * @param str1 
  1218.    *      源字符串 
  1219.    * @param str2 
  1220.    *      指定字符串 
  1221.    * @return true源字符串包含指定字符串,false源字符串不包含指定字符串 
  1222.    */ 
  1223.   public static boolean contains(string str1, string str2) { 
  1224.     return str1 != null && str1.contains(str2); 
  1225.   } 
  1226.   
  1227.   /** 
  1228.    * 判断字符串是否为空,为空则返回一个空值,不为空则返回原字符串 
  1229.    * 
  1230.    * @param str 
  1231.    *      待判断字符串 
  1232.    * @return 判断后的字符串 
  1233.    */ 
  1234.   public static string getstring(string str) { 
  1235.     return str == null ? "" : str; 
  1236.   } 
  1237.   
  1238. /** 
  1239.  * 主要用于把公历日期处理成24节气 
  1240.  */ 
  1241. class solartermsutil { 
  1242.   
  1243.   /** 
  1244.    * 计算得到公历的年份 
  1245.    */ 
  1246.   private int gregorianyear; 
  1247.   
  1248.   /** 
  1249.    * 计算得到公历的月份 
  1250.    */ 
  1251.   private int gregorianmonth; 
  1252.   
  1253.   /** 
  1254.    * 用于计算得到公历的日期 
  1255.    */ 
  1256.   private int gregoriandate; 
  1257.   
  1258.   private int chineseyear; 
  1259.   private int chinesemonth; 
  1260.   private int chinesedate; 
  1261.   
  1262.   // 初始日,公历农历对应日期: 
  1263.   // 公历 1901 年 1 月 1 日,对应农历 4598 年 11 月 11 日 
  1264.   private static int baseyear = 1901; 
  1265.   private static int basemonth = 1; 
  1266.   private static int basedate = 1; 
  1267.   private static int baseindex = 0; 
  1268.   private static int basechineseyear = 4598 - 1; 
  1269.   private static int basechinesemonth = 11; 
  1270.   private static int basechinesedate = 11; 
  1271.   private static char[] daysingregorianmonth = { 31, 28, 31, 30, 31, 30, 31, 
  1272.       31, 30, 31, 30, 31 }; 
  1273.   
  1274.   private int sectionalterm; 
  1275.   private int principleterm; 
  1276.   
  1277.   private static char[][] sectionaltermmap = { 
  1278.       { 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 5, 5, 5, 5, 5, 
  1279.           5, 5, 5, 4, 5, 5 }, 
  1280.       { 5, 4, 5, 5, 5, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 3, 
  1281.           3, 4, 4, 3, 3, 3 }, 
  1282.       { 6, 6, 6, 7, 6, 6, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 5, 5, 5, 6, 5, 5, 
  1283.           5, 5, 4, 5, 5, 5, 5 }, 
  1284.       { 5, 5, 6, 6, 5, 5, 5, 6, 5, 5, 5, 5, 4, 5, 5, 5, 4, 4, 5, 5, 4, 4, 
  1285.           4, 5, 4, 4, 4, 4, 5 }, 
  1286.       { 6, 6, 6, 7, 6, 6, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 5, 5, 5, 6, 5, 5, 
  1287.           5, 5, 4, 5, 5, 5, 5 }, 
  1288.       { 6, 6, 7, 7, 6, 6, 6, 7, 6, 6, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 5, 5, 
  1289.           5, 6, 5, 5, 5, 5, 4, 5, 5, 5, 5 }, 
  1290.       { 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7, 7, 7, 6, 7, 7, 7, 6, 6, 
  1291.           7, 7, 6, 6, 6, 7, 7 }, 
  1292.       { 8, 8, 8, 9, 8, 8, 8, 8, 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7, 
  1293.           7, 7, 6, 7, 7, 7, 6, 6, 7, 7, 7 }, 
  1294.       { 8, 8, 8, 9, 8, 8, 8, 8, 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7, 
  1295.           7, 7, 6, 7, 7, 7, 7 }, 
  1296.       { 9, 9, 9, 9, 8, 9, 9, 9, 8, 8, 9, 9, 8, 8, 8, 9, 8, 8, 8, 8, 7, 8, 
  1297.           8, 8, 7, 7, 8, 8, 8 }, 
  1298.       { 8, 8, 8, 8, 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7, 7, 7, 6, 7, 
  1299.           7, 7, 6, 6, 7, 7, 7 }, 
  1300.       { 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7, 7, 7, 6, 7, 7, 7, 6, 6, 
  1301.           7, 7, 6, 6, 6, 7, 7 } }; 
  1302.   private static char[][] sectionaltermyear = { 
  1303.       { 13, 49, 85, 117, 149, 185, 201, 250, 250 }, 
  1304.       { 13, 45, 81, 117, 149, 185, 201, 250, 250 }, 
  1305.       { 13, 48, 84, 112, 148, 184, 200, 201, 250 }, 
  1306.       { 13, 45, 76, 108, 140, 172, 200, 201, 250 }, 
  1307.       { 13, 44, 72, 104, 132, 168, 200, 201, 250 }, 
  1308.       { 5, 33, 68, 96, 124, 152, 188, 200, 201 }, 
  1309.       { 29, 57, 85, 120, 148, 176, 200, 201, 250 }, 
  1310.       { 13, 48, 76, 104, 132, 168, 196, 200, 201 }, 
  1311.       { 25, 60, 88, 120, 148, 184, 200, 201, 250 }, 
  1312.       { 16, 44, 76, 108, 144, 172, 200, 201, 250 }, 
  1313.       { 28, 60, 92, 124, 160, 192, 200, 201, 250 }, 
  1314.       { 17, 53, 85, 124, 156, 188, 200, 201, 250 } }; 
  1315.   private static char[][] principletermmap = { 
  1316.       { 21, 21, 21, 21, 21, 20, 21, 21, 21, 20, 20, 21, 21, 20, 20, 20, 
  1317.           20, 20, 20, 20, 20, 19, 20, 20, 20, 19, 19, 20 }, 
  1318.       { 20, 19, 19, 20, 20, 19, 19, 19, 19, 19, 19, 19, 19, 18, 19, 19, 
  1319.           19, 18, 18, 19, 19, 18, 18, 18, 18, 18, 18, 18 }, 
  1320.       { 21, 21, 21, 22, 21, 21, 21, 21, 20, 21, 21, 21, 20, 20, 21, 21, 
  1321.           20, 20, 20, 21, 20, 20, 20, 20, 19, 20, 20, 20, 20 }, 
  1322.       { 20, 21, 21, 21, 20, 20, 21, 21, 20, 20, 20, 21, 20, 20, 20, 20, 
  1323.           19, 20, 20, 20, 19, 19, 20, 20, 19, 19, 19, 20, 20 }, 
  1324.       { 21, 22, 22, 22, 21, 21, 22, 22, 21, 21, 21, 22, 21, 21, 21, 21, 
  1325.           20, 21, 21, 21, 20, 20, 21, 21, 20, 20, 20, 21, 21 }, 
  1326.       { 22, 22, 22, 22, 21, 22, 22, 22, 21, 21, 22, 22, 21, 21, 21, 22, 
  1327.           21, 21, 21, 21, 20, 21, 21, 21, 20, 20, 21, 21, 21 }, 
  1328.       { 23, 23, 24, 24, 23, 23, 23, 24, 23, 23, 23, 23, 22, 23, 23, 23, 
  1329.           22, 22, 23, 23, 22, 22, 22, 23, 22, 22, 22, 22, 23 }, 
  1330.       { 23, 24, 24, 24, 23, 23, 24, 24, 23, 23, 23, 24, 23, 23, 23, 23, 
  1331.           22, 23, 23, 23, 22, 22, 23, 23, 22, 22, 22, 23, 23 }, 
  1332.       { 23, 24, 24, 24, 23, 23, 24, 24, 23, 23, 23, 24, 23, 23, 23, 23, 
  1333.           22, 23, 23, 23, 22, 22, 23, 23, 22, 22, 22, 23, 23 }, 
  1334.       { 24, 24, 24, 24, 23, 24, 24, 24, 23, 23, 24, 24, 23, 23, 23, 24, 
  1335.           23, 23, 23, 23, 22, 23, 23, 23, 22, 22, 23, 23, 23 }, 
  1336.       { 23, 23, 23, 23, 22, 23, 23, 23, 22, 22, 23, 23, 22, 22, 22, 23, 
  1337.           22, 22, 22, 22, 21, 22, 22, 22, 21, 21, 22, 22, 22 }, 
  1338.       { 22, 22, 23, 23, 22, 22, 22, 23, 22, 22, 22, 22, 21, 22, 22, 22, 
  1339.           21, 21, 22, 22, 21, 21, 21, 22, 21, 21, 21, 21, 22 } }; 
  1340.   private static char[][] principletermyear = { 
  1341.       { 13, 45, 81, 113, 149, 185, 201 }, 
  1342.       { 21, 57, 93, 125, 161, 193, 201 }, 
  1343.       { 21, 56, 88, 120, 152, 188, 200, 201 }, 
  1344.       { 21, 49, 81, 116, 144, 176, 200, 201 }, 
  1345.       { 17, 49, 77, 112, 140, 168, 200, 201 }, 
  1346.       { 28, 60, 88, 116, 148, 180, 200, 201 }, 
  1347.       { 25, 53, 84, 112, 144, 172, 200, 201 }, 
  1348.       { 29, 57, 89, 120, 148, 180, 200, 201 }, 
  1349.       { 17, 45, 73, 108, 140, 168, 200, 201 }, 
  1350.       { 28, 60, 92, 124, 160, 192, 200, 201 }, 
  1351.       { 16, 44, 80, 112, 148, 180, 200, 201 }, 
  1352.       { 17, 53, 88, 120, 156, 188, 200, 201 } }; 
  1353.   
  1354.   private static char[] chinesemonths = { 
  1355.       // 农历月份大小压缩表,两个字节表示一年。两个字节共十六个二进制位数, 
  1356.       // 前四个位数表示闰月月份,后十二个位数表示十二个农历月份的大小。 
  1357.       0x00, 0x04, 0xad, 0x08, 0x5a, 0x01, 0xd5, 0x54, 0xb4, 0x09, 0x64, 
  1358.       0x05, 0x59, 0x45, 0x95, 0x0a, 0xa6, 0x04, 0x55, 0x24, 0xad, 0x08, 
  1359.       0x5a, 0x62, 0xda, 0x04, 0xb4, 0x05, 0xb4, 0x55, 0x52, 0x0d, 0x94, 
  1360.       0x0a, 0x4a, 0x2a, 0x56, 0x02, 0x6d, 0x71, 0x6d, 0x01, 0xda, 0x02, 
  1361.       0xd2, 0x52, 0xa9, 0x05, 0x49, 0x0d, 0x2a, 0x45, 0x2b, 0x09, 0x56, 
  1362.       0x01, 0xb5, 0x20, 0x6d, 0x01, 0x59, 0x69, 0xd4, 0x0a, 0xa8, 0x05, 
  1363.       0xa9, 0x56, 0xa5, 0x04, 0x2b, 0x09, 0x9e, 0x38, 0xb6, 0x08, 0xec, 
  1364.       0x74, 0x6c, 0x05, 0xd4, 0x0a, 0xe4, 0x6a, 0x52, 0x05, 0x95, 0x0a, 
  1365.       0x5a, 0x42, 0x5b, 0x04, 0xb6, 0x04, 0xb4, 0x22, 0x6a, 0x05, 0x52, 
  1366.       0x75, 0xc9, 0x0a, 0x52, 0x05, 0x35, 0x55, 0x4d, 0x0a, 0x5a, 0x02, 
  1367.       0x5d, 0x31, 0xb5, 0x02, 0x6a, 0x8a, 0x68, 0x05, 0xa9, 0x0a, 0x8a, 
  1368.       0x6a, 0x2a, 0x05, 0x2d, 0x09, 0xaa, 0x48, 0x5a, 0x01, 0xb5, 0x09, 
  1369.       0xb0, 0x39, 0x64, 0x05, 0x25, 0x75, 0x95, 0x0a, 0x96, 0x04, 0x4d, 
  1370.       0x54, 0xad, 0x04, 0xda, 0x04, 0xd4, 0x44, 0xb4, 0x05, 0x54, 0x85, 
  1371.       0x52, 0x0d, 0x92, 0x0a, 0x56, 0x6a, 0x56, 0x02, 0x6d, 0x02, 0x6a, 
  1372.       0x41, 0xda, 0x02, 0xb2, 0xa1, 0xa9, 0x05, 0x49, 0x0d, 0x0a, 0x6d, 
  1373.       0x2a, 0x09, 0x56, 0x01, 0xad, 0x50, 0x6d, 0x01, 0xd9, 0x02, 0xd1, 
  1374.       0x3a, 0xa8, 0x05, 0x29, 0x85, 0xa5, 0x0c, 0x2a, 0x09, 0x96, 0x54, 
  1375.       0xb6, 0x08, 0x6c, 0x09, 0x64, 0x45, 0xd4, 0x0a, 0xa4, 0x05, 0x51, 
  1376.       0x25, 0x95, 0x0a, 0x2a, 0x72, 0x5b, 0x04, 0xb6, 0x04, 0xac, 0x52, 
  1377.       0x6a, 0x05, 0xd2, 0x0a, 0xa2, 0x4a, 0x4a, 0x05, 0x55, 0x94, 0x2d, 
  1378.       0x0a, 0x5a, 0x02, 0x75, 0x61, 0xb5, 0x02, 0x6a, 0x03, 0x61, 0x45, 
  1379.       0xa9, 0x0a, 0x4a, 0x05, 0x25, 0x25, 0x2d, 0x09, 0x9a, 0x68, 0xda, 
  1380.       0x08, 0xb4, 0x09, 0xa8, 0x59, 0x54, 0x03, 0xa5, 0x0a, 0x91, 0x3a, 
  1381.       0x96, 0x04, 0xad, 0xb0, 0xad, 0x04, 0xda, 0x04, 0xf4, 0x62, 0xb4, 
  1382.       0x05, 0x54, 0x0b, 0x44, 0x5d, 0x52, 0x0a, 0x95, 0x04, 0x55, 0x22, 
  1383.       0x6d, 0x02, 0x5a, 0x71, 0xda, 0x02, 0xaa, 0x05, 0xb2, 0x55, 0x49, 
  1384.       0x0b, 0x4a, 0x0a, 0x2d, 0x39, 0x36, 0x01, 0x6d, 0x80, 0x6d, 0x01, 
  1385.       0xd9, 0x02, 0xe9, 0x6a, 0xa8, 0x05, 0x29, 0x0b, 0x9a, 0x4c, 0xaa, 
  1386.       0x08, 0xb6, 0x08, 0xb4, 0x38, 0x6c, 0x09, 0x54, 0x75, 0xd4, 0x0a, 
  1387.       0xa4, 0x05, 0x45, 0x55, 0x95, 0x0a, 0x9a, 0x04, 0x55, 0x44, 0xb5, 
  1388.       0x04, 0x6a, 0x82, 0x6a, 0x05, 0xd2, 0x0a, 0x92, 0x6a, 0x4a, 0x05, 
  1389.       0x55, 0x0a, 0x2a, 0x4a, 0x5a, 0x02, 0xb5, 0x02, 0xb2, 0x31, 0x69, 
  1390.       0x03, 0x31, 0x73, 0xa9, 0x0a, 0x4a, 0x05, 0x2d, 0x55, 0x2d, 0x09, 
  1391.       0x5a, 0x01, 0xd5, 0x48, 0xb4, 0x09, 0x68, 0x89, 0x54, 0x0b, 0xa4, 
  1392.       0x0a, 0xa5, 0x6a, 0x95, 0x04, 0xad, 0x08, 0x6a, 0x44, 0xda, 0x04, 
  1393.       0x74, 0x05, 0xb0, 0x25, 0x54, 0x03 }; 
  1394.   
  1395.   /** 
  1396.    * 用于保存24节气 
  1397.    */ 
  1398.   private static string[] principletermnames = { "大寒""雨水""春分""谷雨"
  1399.       "小满""夏至""大暑""处暑""秋分""霜降""小雪""冬至" }; 
  1400.   /** 
  1401.    * 用于保存24节气 
  1402.    */ 
  1403.   private static string[] sectionaltermnames = { "小寒""立春""惊蛰""清明"
  1404.       "立夏""芒种""小暑""立秋""白露""寒露""立冬""大雪" }; 
  1405.   
  1406.   public solartermsutil(calendar calendar) { 
  1407.     gregorianyear = calendar.get(calendar.year); 
  1408.     gregorianmonth = calendar.get(calendar.month) + 1; 
  1409.     gregoriandate = calendar.get(calendar.date); 
  1410.     computechinesefields(); 
  1411.     computesolarterms(); 
  1412.   } 
  1413.   
  1414.   public int computechinesefields() { 
  1415.     if (gregorianyear < 1901 || gregorianyear > 2100) 
  1416.       return 1; 
  1417.     int startyear = baseyear; 
  1418.     int startmonth = basemonth; 
  1419.     int startdate = basedate; 
  1420.     chineseyear = basechineseyear; 
  1421.     chinesemonth = basechinesemonth; 
  1422.     chinesedate = basechinesedate; 
  1423.     // 第二个对应日,用以提高计算效率 
  1424.     // 公历 2000 年 1 月 1 日,对应农历 4697 年 11 月 25 日 
  1425.     if (gregorianyear >= 2000) { 
  1426.       startyear = baseyear + 99; 
  1427.       startmonth = 1; 
  1428.       startdate = 1; 
  1429.       chineseyear = basechineseyear + 99; 
  1430.       chinesemonth = 11; 
  1431.       chinesedate = 25; 
  1432.     } 
  1433.     int daysdiff = 0; 
  1434.     for (int i = startyear; i < gregorianyear; i++) { 
  1435.       daysdiff += 365; 
  1436.       if (isgregorianleapyear(i)) 
  1437.         daysdiff += 1; // leap year 
  1438.     } 
  1439.     for (int i = startmonth; i < gregorianmonth; i++) { 
  1440.       daysdiff += daysingregorianmonth(gregorianyear, i); 
  1441.     } 
  1442.     daysdiff += gregoriandate - startdate; 
  1443.   
  1444.     chinesedate += daysdiff; 
  1445.     int lastdate = daysinchinesemonth(chineseyear, chinesemonth); 
  1446.     int nextmonth = nextchinesemonth(chineseyear, chinesemonth); 
  1447.     while (chinesedate > lastdate) { 
  1448.       if (math.abs(nextmonth) < math.abs(chinesemonth)) 
  1449.         chineseyear++; 
  1450.       chinesemonth = nextmonth; 
  1451.       chinesedate -= lastdate; 
  1452.       lastdate = daysinchinesemonth(chineseyear, chinesemonth); 
  1453.       nextmonth = nextchinesemonth(chineseyear, chinesemonth); 
  1454.     } 
  1455.     return 0; 
  1456.   } 
  1457.   
  1458.   public int computesolarterms() { 
  1459.     if (gregorianyear < 1901 || gregorianyear > 2100) 
  1460.       return 1; 
  1461.     sectionalterm = sectionalterm(gregorianyear, gregorianmonth); 
  1462.     principleterm = principleterm(gregorianyear, gregorianmonth); 
  1463.     return 0; 
  1464.   } 
  1465.   
  1466.   public static int sectionalterm(int y, int m) { 
  1467.     if (y < 1901 || y > 2100) 
  1468.       return 0; 
  1469.     int index = 0; 
  1470.     int ry = y - baseyear + 1; 
  1471.     while (ry >= sectionaltermyear[m - 1][index]) 
  1472.       index++; 
  1473.     int term = sectionaltermmap[m - 1][4 * index + ry % 4]; 
  1474.     if ((ry == 121) && (m == 4)) 
  1475.       term = 5; 
  1476.     if ((ry == 132) && (m == 4)) 
  1477.       term = 5; 
  1478.     if ((ry == 194) && (m == 6)) 
  1479.       term = 6; 
  1480.     return term; 
  1481.   } 
  1482.   
  1483.   public static int principleterm(int y, int m) { 
  1484.     if (y < 1901 || y > 2100) 
  1485.       return 0; 
  1486.     int index = 0; 
  1487.     int ry = y - baseyear + 1; 
  1488.     while (ry >= principletermyear[m - 1][index]) 
  1489.       index++; 
  1490.     int term = principletermmap[m - 1][4 * index + ry % 4]; 
  1491.     if ((ry == 171) && (m == 3)) 
  1492.       term = 21; 
  1493.     if ((ry == 181) && (m == 5)) 
  1494.       term = 21; 
  1495.     return term; 
  1496.   } 
  1497.   
  1498.   /** 
  1499.    * 用于判断输入的年份是否为闰年 
  1500.    * 
  1501.    * @param year 
  1502.    *      输入的年份 
  1503.    * @return true 表示闰年 
  1504.    */ 
  1505.   public static boolean isgregorianleapyear(int year) { 
  1506.     boolean isleap = false
  1507.     if (year % 4 == 0) 
  1508.       isleap = true
  1509.     if (year % 100 == 0) 
  1510.       isleap = false
  1511.     if (year % 400 == 0) 
  1512.       isleap = true
  1513.     return isleap; 
  1514.   } 
  1515.   
  1516.   public static int daysingregorianmonth(int y, int m) { 
  1517.     int d = daysingregorianmonth[m - 1]; 
  1518.     if (m == 2 && isgregorianleapyear(y)) 
  1519.       d++; // 公历闰年二月多一天 
  1520.     return d; 
  1521.   } 
  1522.   
  1523.   public static int daysinchinesemonth(int y, int m) { 
  1524.     // 注意:闰月 m < 0 
  1525.     int index = y - basechineseyear + baseindex; 
  1526.     int v = 0; 
  1527.     int l = 0; 
  1528.     int d = 30; 
  1529.     if (1 <= m && m <= 8) { 
  1530.       v = chinesemonths[2 * index]; 
  1531.       l = m - 1; 
  1532.       if (((v >> l) & 0x01) == 1) 
  1533.         d = 29; 
  1534.     } else if (9 <= m && m <= 12) { 
  1535.       v = chinesemonths[2 * index + 1]; 
  1536.       l = m - 9; 
  1537.       if (((v >> l) & 0x01) == 1) 
  1538.         d = 29; 
  1539.     } else { 
  1540.       v = chinesemonths[2 * index + 1]; 
  1541.       v = (v >> 4) & 0x0f; 
  1542.       if (v != math.abs(m)) { 
  1543.         d = 0; 
  1544.       } else { 
  1545.         d = 29; 
  1546.         for (int i = 0; i < bigleapmonthyears.length; i++) { 
  1547.           if (bigleapmonthyears[i] == index) { 
  1548.             d = 30; 
  1549.             break
  1550.           } 
  1551.         } 
  1552.       } 
  1553.     } 
  1554.     return d; 
  1555.   } 
  1556.   
  1557.   public static int nextchinesemonth(int y, int m) { 
  1558.     int n = math.abs(m) + 1; 
  1559.     if (m > 0) { 
  1560.       int index = y - basechineseyear + baseindex; 
  1561.       int v = chinesemonths[2 * index + 1]; 
  1562.       v = (v >> 4) & 0x0f; 
  1563.       if (v == m) 
  1564.         n = -m; 
  1565.     } 
  1566.     if (n == 13) 
  1567.       n = 1; 
  1568.     return n; 
  1569.   } 
  1570.   
  1571.   // 大闰月的闰年年份 
  1572.   private static int[] bigleapmonthyears = { 6, 14, 19, 25, 33, 36, 38, 41, 
  1573.       44, 52, 55, 79, 117, 136, 147, 150, 155, 158, 185, 193 }; 
  1574.   
  1575.   /** 
  1576.    * 用于获取24节气的值 
  1577.    * 
  1578.    * @return 24节气的值 
  1579.    */ 
  1580.   public string getsolartermsmsg() { 
  1581.     string str = ""
  1582.     string gm = string.valueof(gregorianmonth); 
  1583.     if (gm.length() == 1) 
  1584.       gm = ' ' + gm; 
  1585.     string cm = string.valueof(math.abs(chinesemonth)); 
  1586.     if (cm.length() == 1) 
  1587.       cm = ' ' + cm; 
  1588.     string gd = string.valueof(gregoriandate); 
  1589.     if (gd.length() == 1) 
  1590.       gd = ' ' + gd; 
  1591.     string cd = string.valueof(chinesedate); 
  1592.     if (cd.length() == 1) 
  1593.       cd = ' ' + cd; 
  1594.     if (gregoriandate == sectionalterm) { 
  1595.       str = " " + sectionaltermnames[gregorianmonth - 1]; 
  1596.     } else if (gregoriandate == principleterm) { 
  1597.       str = " " + principletermnames[gregorianmonth - 1]; 
  1598.     } 
  1599.     return str; 
  1600.   } 
  1601.   
  1602. /** 
  1603.  * 对公历日期的处理类 
  1604.  */ 
  1605. class gregorianutil { 
  1606.   private final static string[][] gre_festvial = { 
  1607.       // 一月 
  1608.       { "元旦"""""""""""""""""""""""""""""""
  1609.           """""""""""""""""""""""""""""" }, 
  1610.       // 二月 
  1611.       { """""""""""""""""""""""""""情人"""""
  1612.           """""""""""""""""""""""""""" }, 
  1613.       // 三月 
  1614.       { """""""""""""""妇女""""""""植树"""""""
  1615.           """"""""""""""""""""""""""""""
  1616.           "" }, 
  1617.       // 四月 
  1618.       { "愚人"""""""""""""""""""""""""""""""
  1619.           """""""""""""""""""""""""""""" }, 
  1620.       // 五月 
  1621.       { "劳动""""""青年"""""""""""""""""""""""
  1622.           """"""""""""""""""""""""""""""
  1623.           "" }, 
  1624.       // 六月 
  1625.       { "儿童"""""""""""""""""""""""""""""""
  1626.           """""""""""""""""""""""""""""" }, 
  1627.       // 七月 
  1628.       { "建党"""""""""""""""""""""""""""""""
  1629.           """""""""""""""""""""""""""""" }, 
  1630.       // 八月 
  1631.       { "建军"""""""""""""""""""""""""""""""
  1632.           """""""""""""""""""""""""""""" }, 
  1633.       // 九月 
  1634.       { """""""""""""""""""教师"""""""""""""
  1635.           """""""""""""""""""""""""""""" }, 
  1636.       // 十月 
  1637.       { "国庆"""""""""""""""""""""""""""""""
  1638.           """""""""""""""""""""""""""""" }, 
  1639.       // 十一月 
  1640.       { """""""""""""""""""""光棍"""""""""""
  1641.           """""""""""""""""""""""""""""" }, 
  1642.       // 十二月 
  1643.       { "艾滋病"""""""""""""""""""""""""""""
  1644.           """""""""""""""""""圣诞"""""""""
  1645.           """" }, }; 
  1646.   private int mmonth; 
  1647.   private int mday; 
  1648.   
  1649.   public gregorianutil(calendar calendar) { 
  1650.     mmonth = calendar.get(calendar.month); 
  1651.     mday = calendar.get(calendar.date); 
  1652.   } 
  1653.   
  1654.   public string getgremessage() { 
  1655.     return gre_festvial[mmonth][mday - 1]; 
  1656.   } 
  1657.   
  1658. class numberhelper { 
  1659.   public static string leftpad_tow_zero(int str) { 
  1660.     java.text.decimalformat format = new java.text.decimalformat("00"); 
  1661.     return format.format(str); 
  1662.   } 
  1663. /*****************将代码拷贝到一个文件中(end)***********************/ 
  1664.   
  1665. //辅助类 
  1666. package cc.util.android.view; 
  1667.   
  1668. import android.content.context; 
  1669. import android.content.res.resources; 
  1670. import android.view.view; 
  1671. import android.view.viewgroup; 
  1672. import android.view.viewgroup.marginlayoutparams; 
  1673. import android.widget.abslistview; 
  1674. import android.widget.gridview; 
  1675. import android.widget.listadapter; 
  1676. import android.widget.listview; 
  1677.   
  1678. /** 
  1679.  * @author wangcccong 
  1680.  * @version 1.140122 
  1681.  * create at:2014-02-26 
  1682.  */ 
  1683. public class viewutil { 
  1684.   
  1685.   /** 
  1686.    * 获取屏幕的宽度 
  1687.    * @param context 
  1688.    * @return 
  1689.    */ 
  1690.   public int getscreenwidth(context context) { 
  1691.     resources res = context.getresources(); 
  1692.     return res.getdisplaymetrics().widthpixels; 
  1693.   } 
  1694.     
  1695.   /** 
  1696.    * 获取屏幕高度 
  1697.    * @param context 
  1698.    * @return 
  1699.    */ 
  1700.   public int getscreenheight(context context) { 
  1701.     resources res = context.getresources(); 
  1702.     return res.getdisplaymetrics().heightpixels; 
  1703.   } 
  1704.     
  1705.   /** 
  1706.    * 描述:根据分辨率获得字体大小. 
  1707.    * 
  1708.    * @param screenwidth the screen width 
  1709.    * @param screenheight the screen height 
  1710.    * @param textsize the text size 
  1711.    * @return the int 
  1712.    */ 
  1713.   public static int resizetextsize(int screenwidth,int screenheight,int textsize){ 
  1714.     float ratio = 1; 
  1715.     try { 
  1716.       float ratiowidth = (float)screenwidth / 480; 
  1717.       float ratioheight = (float)screenheight / 800; 
  1718.       ratio = math.min(ratiowidth, ratioheight); 
  1719.     } catch (exception e) { 
  1720.     } 
  1721.     return math.round(textsize * ratio); 
  1722.   } 
  1723.     
  1724.   /** 
  1725.    * 
  1726.    * 描述:dip转换为px 
  1727.    * @param context 
  1728.    * @param dipvalue 
  1729.    * @return 
  1730.    * @throws 
  1731.    */ 
  1732.   public static int dip2px(context context, float dipvalue) { 
  1733.     final float scale = context.getresources().getdisplaymetrics().density; 
  1734.     return math.round(dipvalue * scale); 
  1735.   } 
  1736.   
  1737.   /** 
  1738.    * 
  1739.    * 描述:px转换为dip 
  1740.    * @param context 
  1741.    * @param pxvalue 
  1742.    * @return 
  1743.    * @throws 
  1744.    */ 
  1745.   public static int px2dip(context context, float pxvalue) { 
  1746.     final float scale = context.getresources().getdisplaymetrics().density; 
  1747.     return math.round(pxvalue / scale); 
  1748.   } 
  1749.     
  1750.   /** 
  1751.    * 
  1752.    * 描述:px转换为sp 
  1753.    * @param context 
  1754.    * @param pxvalue 
  1755.    * @return 
  1756.    * @throws 
  1757.    */ 
  1758.   public static int px2sp(context context, float pxvalue) { 
  1759.     final float scale = context.getresources().getdisplaymetrics().scaleddensity; 
  1760.     return math.round(pxvalue / scale); 
  1761.   } 
  1762.     
  1763.   /** 
  1764.    * 
  1765.    * 描述:sp转换为px 
  1766.    * @param context 
  1767.    * @param spvalue 
  1768.    * @return 
  1769.    * @throws 
  1770.    */ 
  1771.   public static int sp2px(context context, float spvalue) { 
  1772.     final float scale = context.getresources().getdisplaymetrics().scaleddensity; 
  1773.     return math.round(spvalue * scale); 
  1774.   } 
  1775.   
  1776. //使用方法 
  1777. //在xml中添加控件 
  1778. <cc.util.android.view.calendarview 
  1779.       android:id="@+id/calendar" 
  1780.       android:layout_width="match_parent" 
  1781.       android:layout_height="wrap_content" 
  1782.       android:background="@color/white"/> 
  1783. //在代码中 
  1784. calendarview calendarview = (calendarview) findviewbyid(r.id.calendar); 
  1785.     //设置标注日期 
  1786.     list<date> markdates = new arraylist<date>(); 
  1787.     markdates.add(new date()); 
  1788.     calendarview.setmarkdates(markdates); 
  1789.   
  1790.     //设置点击操作 
  1791.     calendarview.setoncalendarviewlistener(new oncalendarviewlistener() { 
  1792.         
  1793.       @override 
  1794.       public void oncalendaritemclick(calendarview view, date date) { 
  1795.         // todo auto-generated method stub 
  1796.         final simpledateformat format = new simpledateformat("yyyy年mm月dd日", locale.china); 
  1797.         toast.maketext(mainactivity.this, format.format(date), toast.length_short).show(); 
  1798.       } 
  1799.     }); 

所需图片:

Android实现自定义日历

Android实现自定义日历

Android实现自定义日历

Android实现自定义日历

Android实现自定义日历

以上所述就是本文的全部内容了,希望大家能够喜欢。