[Java] Android系统自定义实现日历控件 →→→→→进入此内容的聊天室

来自 , 2020-03-05, 写在 Java, 查看 140 次.
URL http://www.code666.cn/view/adc8ca1b
  1. 注:此功能在在Activity中,由三大块组成:头(上月按扭,下月按扭,当前年月文本),日历块(星期区域,日期区域),描述区域
  2.  
  3. Activity:
  4. /**
  5.  * Android实现日历控件
  6.  * 注:Calendar时间与现在实的时间在月份上需要+1,因为月份是0-11
  7.  */
  8. public class CalenderActivity extends Activity {
  9.  
  10.     private ArrayList<DateWidgetDayView> days = new ArrayList<DateWidgetDayView>();
  11.      
  12.         //颜色代码常量
  13.     public static int Calendar_WeekBgColor = 0;
  14.     public static int Calendar_DayBgColor = 0;
  15.     public static int IsHoliday_BgColor = 0;
  16.     public static int UnPresentMonth_FontColor = 0;
  17.     public static int IsPresentMonth_FontColor = 0;
  18.     public static int IsToday_BgColor = 0;
  19.     public static int Special_Reminder = 0;
  20.     public static int Common_Reminder = 0;
  21.     public static int Calendar_WeekFontColor = 0;
  22.  
  23.     /**
  24.      *  表格中的第一天,一般上月的某一天
  25.      */
  26.     public static Calendar mFirstDateOfPanel = Calendar.getInstance();
  27.     private Calendar mTodayDate = Calendar.getInstance();// 初始日期,即当天
  28.     private Calendar mSelectedDate = Calendar.getInstance();//选中的日期,如果未选中则为1970-1-1
  29.     private Calendar mViewDate = Calendar.getInstance();
  30.  
  31.     // 当前操作日期
  32.     private int firstDayOfWeek = Calendar.SUNDAY;// 是星期日
  33.     private int currentMonth = 0;
  34.     private int currentYear = 0;
  35.  
  36.     private int displayWidth = 0;// 屏幕总宽度
  37.     private int cell_Width = 0; // 日期单元格宽度
  38.     private int cell_Height = 35; // 日期单元格高度
  39.  
  40.     // 页面控件
  41.     TextView currentYAndM = null;
  42.     Button preMonthButton = null;
  43.     Button nextMonthButton = null;
  44.     LinearLayout mainLayout = null;
  45.     LinearLayout calendarLayout = null;
  46.     LinearLayout contentLayout = null;
  47.     TextView contentText = null;
  48.  
  49.     // 数据源
  50.     Boolean[] msgs = null;
  51.  
  52.     Calendar startDate = null;//表格的第一天的日期
  53.  
  54.     @Override
  55.     public void onCreate(Bundle savedInstanceState) {
  56.         super.onCreate(savedInstanceState);
  57.  
  58.         setContentView(R.layout.calendar_main);
  59.         this.viewModel = new BlogViewModel(this);
  60.  
  61.         // 获得屏幕宽和高,并計算出屏幕寬度分七等份的大小
  62.         WindowManager windowManager = getWindowManager();
  63.         Display display = windowManager.getDefaultDisplay();
  64.         displayWidth = display.getWidth();
  65.         cell_Width = displayWidth / 7 + 1;
  66.  
  67.         // 制定布局文件,并设置属性
  68.         mainLayout = (LinearLayout) this.findViewById(R.id.date_calender_framelayout);
  69.         currentYAndM = (TextView) findViewById(R.id.Top_Date);
  70.         preMonthButton = (Button) findViewById(R.id.btn_pre_month);
  71.         nextMonthButton = (Button) findViewById(R.id.btn_next_month);
  72.  
  73.         preMonthButton.setOnClickListener(new OnClickPreMonthListener());
  74.         nextMonthButton.setOnClickListener(new OnClickNextMonthListener());
  75.  
  76.         // 计算本月日历中的第一天(一般是上月的某天),并更新日历
  77.         mFirstDateOfPanel = getCalendarStartDate();
  78.         this.mTodayDate = getTodayDate();
  79.         this.startDate = getStartDate();
  80.  
  81.         /*
  82.          *  初始化日期视图
  83.          *  Calendar部分
  84.          */
  85.         View calendarView = generateCalendarView();
  86.         this.mainLayout.addView(calendarView);
  87.  
  88.         //刷新日期视图
  89.         this.refreshCalendar();
  90.  
  91.         /*
  92.          * Description 部分
  93.          */
  94.         ScrollView view = new ScrollView(this);
  95.         contentLayout = createLayout(LinearLayout.VERTICAL);
  96.         contentLayout.setPadding(5, 2, 0, 0);
  97.  
  98.         contentText = new TextView(this);
  99.         contentText.setTextColor(Color.BLACK);
  100.         contentText.setTextSize(18);
  101.          
  102.         contentLayout.addView(contentText);
  103.  
  104.         LinearLayout.LayoutParams Param1 = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
  105.         view.addView(contentLayout, Param1);
  106.         mainLayout.setBackgroundColor(Color.WHITE);
  107.         mainLayout.addView(view);
  108.  
  109.         /* 新建线程
  110.         new Thread() {
  111.             @Override
  112.             public void run() {
  113.                 int day = getIndexFromDates(mTodayDate, startDate);
  114.                                      
  115.                 Log.i("sys", "初始时  day = "+day);
  116.             }
  117.         }.start();*/
  118.  
  119.         Calendar_WeekBgColor = this.getResources().getColor(R.color.Calendar_WeekBgColor);
  120.         Calendar_DayBgColor = this.getResources().getColor(R.color.Calendar_DayBgColor);
  121.         IsHoliday_BgColor = this.getResources().getColor(R.color.isHoliday_BgColor);
  122.         UnPresentMonth_FontColor = this.getResources().getColor(R.color.unPresentMonth_FontColor);
  123.         IsPresentMonth_FontColor = this.getResources().getColor(R.color.isPresentMonth_FontColor);
  124.         IsToday_BgColor = this.getResources().getColor(R.color.isToday_BgColor);
  125.         Special_Reminder = this.getResources().getColor(R.color.specialReminder);
  126.         Common_Reminder = this.getResources().getColor(R.color.commonReminder);
  127.         Calendar_WeekFontColor = this.getResources().getColor(R.color.Calendar_WeekFontColor);
  128.     }
  129.  
  130.     protected String getDateShortString(Calendar date) {
  131.         String returnString = date.get(Calendar.YEAR) + "-";
  132.         returnString += date.get(Calendar.MONTH) + 1 + "-";
  133.         returnString += date.get(Calendar.DAY_OF_MONTH);
  134.  
  135.         return returnString;
  136.     }
  137.  
  138.     /**
  139.      * Return the Date's index of {@link returnDate} from {@link datesList};
  140.      * First is Today's index
  141.      *
  142.      * @param now
  143.      *            today
  144.      * @param returnDate
  145.      *            click date
  146.      * @return
  147.      */
  148.     private int getIndexFromDates(Calendar now, Calendar returnDate) {
  149.         Calendar cNow = (Calendar) now.clone();
  150.         Calendar cReturnDate = (Calendar) returnDate.clone();
  151.         CalenderUtil.setTimeToMidnight(cNow);
  152.         CalenderUtil.setTimeToMidnight(cReturnDate);
  153.  
  154.         long todayMs = cNow.getTimeInMillis();
  155.         long returnMs = cReturnDate.getTimeInMillis();
  156.         long intervalMs = todayMs - returnMs;
  157.         int index = CalenderUtil.millisecondsToDays(intervalMs);
  158.         Log.i("sys", "Index = " + index);
  159.         return index;
  160.     }
  161.  
  162.     /**
  163.      * 生成日期视图 即初始化calendarLayout
  164.      *
  165.      * @return
  166.      */
  167.     private View generateCalendarView() {
  168.         calendarLayout = createLayout(LinearLayout.VERTICAL);
  169.         // layContent.setPadding(1, 0, 1, 0);
  170.         calendarLayout.setBackgroundColor(Color.argb(255, 105, 105, 103));
  171.         calendarLayout.addView(generateCalendarWeekRows());
  172.         days.clear();
  173.  
  174.         for (int iRow = 0; iRow < 6; iRow++) {
  175.             calendarLayout.addView(generateCalendarDayRows());
  176.         }
  177.  
  178.         return calendarLayout;
  179.     }
  180.  
  181.     /**
  182.      * 生成星期View
  183.      *
  184.      * @return View
  185.      */
  186.     private View generateCalendarWeekRows() {
  187.         LinearLayout weekLayoutRow = createLayout(LinearLayout.HORIZONTAL);
  188.         weekLayoutRow.setBackgroundColor(Color.argb(255, 207, 207, 205));
  189.  
  190.         for (int iDay = 0; iDay < 7; iDay++) {
  191.             DateWidgetWeekView dayView = new DateWidgetWeekView(this, cell_Width, cell_Height);
  192.  
  193.             final int iWeekDay = CalenderUtil.getWeekDay(iDay, firstDayOfWeek);
  194.             dayView.setData(iWeekDay);
  195.             weekLayoutRow.addView(dayView);
  196.         }
  197.  
  198.         return weekLayoutRow;
  199.     }
  200.  
  201.     /**
  202.      * 生成日期行View
  203.      *
  204.      * @return View
  205.      */
  206.     private View generateCalendarDayRows() {
  207.         LinearLayout layRow = createLayout(LinearLayout.HORIZONTAL);
  208.         //TODO  日期数据消息给添加属性
  209.          
  210.         for (int iDay = 0; iDay < 7; iDay++) {
  211.             DateWidgetDayView dateDayView = new DateWidgetDayView(this, cell_Width, cell_Width);
  212.             dateDayView.setItemClick(mOnDayCellClick);
  213.             days.add(dateDayView);
  214.             layRow.addView(dateDayView);
  215.         }
  216.  
  217.         return layRow;
  218.     }
  219.  
  220.     /**
  221.      * 由于本日历上的日期都是从周一开始的,此方法可推算出上月在本月日历中显示的天数 计算出本月第一行1号前的空格数
  222.      */
  223.     private void updateStartDateForPanel() {
  224.         currentMonth = mFirstDateOfPanel.get(Calendar.MONTH);
  225.         currentYear = mFirstDateOfPanel.get(Calendar.YEAR);
  226.         mFirstDateOfPanel.set(Calendar.DAY_OF_MONTH, 1);
  227.         mFirstDateOfPanel.set(Calendar.HOUR_OF_DAY, 0);
  228.         mFirstDateOfPanel.set(Calendar.MINUTE, 0);
  229.         mFirstDateOfPanel.set(Calendar.SECOND, 0);
  230.         // 显示当前是的年月在Header
  231.         updateCurrentMonthDisplay();
  232.         int iDay = 0;// 前面的空格数
  233.         int iStartDay = firstDayOfWeek;// 当天的星期角标
  234.  
  235.         if (iStartDay == Calendar.MONDAY) {
  236.             iDay = mFirstDateOfPanel.get(Calendar.DAY_OF_WEEK) - Calendar.MONDAY;
  237.             if (iDay < 0)
  238.                 iDay = 6;
  239.         }
  240.  
  241.         if (iStartDay == Calendar.SUNDAY) {
  242.             iDay = mFirstDateOfPanel.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY;
  243.             if (iDay < 0)
  244.                 iDay = 6;
  245.         }
  246.  
  247.         mFirstDateOfPanel.add(Calendar.DAY_OF_WEEK, -iDay);// 得出-2,即前面从上月30号开始
  248.     }
  249.  
  250.     /**
  251.      *  更新日历数据并设置日期
  252.      *  给days中的DateWidgetDayView元素添加Text
  253.      */
  254.     private void refreshCalendar() {
  255.         DateWidgetDayView dayView = null;
  256.          
  257.         boolean isSelected = false;
  258.         final boolean bIsSelection = (mSelectedDate.getTimeInMillis() != 0);
  259.         final int iSelectedYear = mSelectedDate.get(Calendar.YEAR);
  260.         final int iSelectedMonth = mSelectedDate.get(Calendar.MONTH);
  261.         final int iSelectedDay = mSelectedDate.get(Calendar.DAY_OF_MONTH);
  262.          
  263.         //取得表格中的第一天(一般为上月)
  264.         mViewDate.setTimeInMillis(mFirstDateOfPanel.getTimeInMillis());
  265.  
  266.         for (int i = 0; i < days.size(); i++) {
  267.             final int iYear = mViewDate.get(Calendar.YEAR);
  268.             final int iMonth = mViewDate.get(Calendar.MONTH);
  269.             final int iDay = mViewDate.get(Calendar.DAY_OF_MONTH);
  270.             final int iDayOfWeek = mViewDate.get(Calendar.DAY_OF_WEEK);
  271.              
  272.             dayView = days.get(i);
  273.  
  274.             // Check isToday
  275.             boolean isToday = false;
  276.  
  277.             if (mTodayDate.get(Calendar.YEAR) == iYear && mTodayDate.get(Calendar.MONTH) == iMonth && mTodayDate.get(Calendar.DAY_OF_MONTH) == iDay) {
  278.                 isToday = true;
  279.             }
  280.  
  281.             // Check isHoliday
  282.             boolean isHoliday = false;
  283.             if ((iDayOfWeek == Calendar.SATURDAY) || (iDayOfWeek == Calendar.SUNDAY))
  284.                 isHoliday = true;
  285.             /*if ((iMonth == Calendar.JANUARY) && (iDay == 1))
  286.                 isHoliday = true;*///在格里高利历和罗马儒略历中一年中的第一个月是 JANUARY,它为 0;最后一个月取决于一年中的月份数。
  287.  
  288.             // Check isSelected
  289.             isSelected = false;
  290.  
  291.             if (bIsSelection)
  292.                 if ((iSelectedDay == iDay) && (iSelectedMonth == iMonth) && (iSelectedYear == iYear)) {
  293.                     isSelected = true;
  294.                 }
  295.  
  296.             dayView.setSelected(isSelected);
  297.  
  298.             // Check hasMSG
  299.             boolean hasMSG = false;
  300.  
  301.             if (msgs != null && msgs[i] == true ){
  302.                 //TODO
  303.             }
  304.  
  305.             if (isSelected){
  306.                 dayView.setFocusable(true);
  307.             }
  308.  
  309.             dayView.setData(iYear, iMonth, iDay, isToday, isHoliday, currentMonth, hasMSG);
  310.  
  311.             mViewDate.add(Calendar.DAY_OF_MONTH, 1);
  312.             Log.i("sys", "mViewDate : "+iYear+"-"+iMonth+"-"+iDay);
  313.             Log.i("sys", "mFirstDateOfPanel : "+mFirstDateOfPanel.get(Calendar.YEAR)+"-"+mFirstDateOfPanel.get(Calendar.MONTH)+"-"+mFirstDateOfPanel.get(Calendar.DAY_OF_MONTH));
  314.         }
  315.         Log.i("sys", "mSelectedDate : "+iSelectedYear+"-"+iSelectedMonth+"-"+iSelectedDay);
  316.         Log.i("sys", "startDate : "+startDate.get(Calendar.YEAR)+"-"+startDate.get(Calendar.MONTH)+"-"+startDate.get(Calendar.DAY_OF_MONTH));
  317.  
  318.         calendarLayout.invalidate();
  319.     }
  320.      
  321.     /**
  322.      *  设置当天日期和第并计算出前面第一个星期天的日期{@link mFirstDateOfPanel}
  323.      * @return
  324.      */
  325.     private Calendar getCalendarStartDate() {
  326.         mTodayDate.setTimeInMillis(System.currentTimeMillis());
  327.         mTodayDate.setFirstDayOfWeek(firstDayOfWeek);
  328.  
  329.         // 如果没有选中日期,则设置当前日期为 ?
  330.         if (mSelectedDate.getTimeInMillis() == 0) {
  331.             mFirstDateOfPanel.setTimeInMillis(System.currentTimeMillis());
  332.             mFirstDateOfPanel.setFirstDayOfWeek(firstDayOfWeek);
  333.         } else {
  334.             mFirstDateOfPanel.setTimeInMillis(mSelectedDate.getTimeInMillis());
  335.             mFirstDateOfPanel.setFirstDayOfWeek(firstDayOfWeek);
  336.         }
  337.  
  338.         updateStartDateForPanel();
  339.         return mFirstDateOfPanel;
  340.     }
  341.      
  342.     /**
  343.      * 得到当前日历表中的第一天
  344.      *
  345.      * @return Calendar
  346.      */
  347.     public Calendar getStartDate() {
  348.         int iDay = 0;
  349.         Calendar cal_Now = Calendar.getInstance();
  350.         cal_Now.set(Calendar.DAY_OF_MONTH, 1);
  351.         cal_Now.set(Calendar.HOUR_OF_DAY, 0);
  352.         cal_Now.set(Calendar.MINUTE, 0);
  353.         cal_Now.set(Calendar.SECOND, 0);
  354.         cal_Now.setFirstDayOfWeek(Calendar.SUNDAY);
  355.  
  356.         iDay = cal_Now.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY;
  357.  
  358.         if (iDay < 0) {
  359.             iDay = 6;
  360.         }
  361.  
  362.         cal_Now.add(Calendar.DAY_OF_WEEK, -iDay);
  363.  
  364.         return cal_Now;
  365.     }
  366.  
  367.     public Calendar getTodayDate() {
  368.         Calendar cal_Today = Calendar.getInstance();
  369.         cal_Today.set(Calendar.HOUR_OF_DAY, 0);
  370.         cal_Today.set(Calendar.MINUTE, 0);
  371.         cal_Today.set(Calendar.SECOND, 0);
  372.         cal_Today.setFirstDayOfWeek(Calendar.MONDAY);
  373.  
  374.         return cal_Today;
  375.     }
  376.  
  377.     /**
  378.      * 更新日历标题上显示的年月
  379.      */
  380.     private void updateCurrentMonthDisplay() {
  381.         String date = mFirstDateOfPanel.get(Calendar.YEAR) + "年" + (mFirstDateOfPanel.get(Calendar.MONTH) + 1) + "月";
  382.         currentYAndM.setText(date);
  383.     }
  384.  
  385.     /**
  386.      *  点击上月按钮,触发事件
  387.      * @author Win7
  388.      */
  389.      
  390.     // 生成布局LinearLayout
  391.     private LinearLayout createLayout(int iOrientation) {
  392.         LinearLayout lay = new LinearLayout(this);
  393.         lay.setLayoutParams(new LayoutParams(android.view.ViewGroup.LayoutParams.FILL_PARENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT));
  394.         lay.setOrientation(iOrientation);
  395.  
  396.         return lay;
  397.     }
  398.      
  399.     class OnClickPreMonthListener implements OnClickListener {
  400.         @Override
  401.         public void onClick(View v) {
  402.             contentText.setText("aaaa");
  403.             mSelectedDate.setTimeInMillis(0);
  404.             currentMonth--;
  405.  
  406.             if (currentMonth == -1) {
  407.                 currentMonth = 11;
  408.                 currentYear--;
  409.             }
  410.  
  411.             mFirstDateOfPanel.set(Calendar.DAY_OF_MONTH, 1);
  412.             mFirstDateOfPanel.set(Calendar.MONTH, currentMonth);
  413.             mFirstDateOfPanel.set(Calendar.YEAR, currentYear);
  414.             mFirstDateOfPanel.set(Calendar.HOUR_OF_DAY, 0);
  415.             mFirstDateOfPanel.set(Calendar.MINUTE, 0);
  416.             mFirstDateOfPanel.set(Calendar.SECOND, 0);
  417.             mFirstDateOfPanel.set(Calendar.MILLISECOND, 0);
  418.             updateStartDateForPanel();
  419.  
  420.             startDate = (Calendar) mFirstDateOfPanel.clone();
  421.  
  422.             // 新建线程
  423.             new Thread() {
  424.                 @Override
  425.                 public void run() {
  426.                     int day = getIndexFromDates(mTodayDate, startDate);
  427.                                         //day是算出当前显示的月份面版第一天与当天的天数
  428.                     Log.i("sys", "点击上月时  day = "+day);
  429.                 }
  430.             }.start();
  431.  
  432.             refreshCalendar();
  433.         }
  434.  
  435.     }
  436.  
  437.     /**
  438.      *  点击下月按钮,触发事件
  439.      * @author Win7
  440.      */
  441.     class OnClickNextMonthListener implements OnClickListener {
  442.         @Override
  443.         public void onClick(View v) {
  444.             contentText.setText("");
  445.             mSelectedDate.setTimeInMillis(0);
  446.             currentMonth++;
  447.  
  448.             if (currentMonth == 12) {
  449.                 currentMonth = 0;
  450.                 currentYear++;
  451.             }
  452.  
  453.             mFirstDateOfPanel.set(Calendar.DAY_OF_MONTH, 1);
  454.             mFirstDateOfPanel.set(Calendar.MONTH, currentMonth);
  455.             mFirstDateOfPanel.set(Calendar.YEAR, currentYear);
  456.             updateStartDateForPanel();
  457.  
  458.             startDate = (Calendar) mFirstDateOfPanel.clone();
  459.  
  460.             // 新建线程
  461.             new Thread() {
  462.                 @Override
  463.                 public void run() {
  464.                     int day = 5;
  465.                     Log.i("sys", "点击下月时  day = "+day);
  466.                 }
  467.             }.start();
  468.  
  469.             refreshCalendar();
  470.         }
  471.     }
  472.  
  473.     // 点击日历,触发事件
  474.     private DateWidgetDayView.OnDateItemClickListener mOnDayCellClick = new DateWidgetDayView.OnDateItemClickListener() {
  475.         public void OnClick(DateWidgetDayView item) {
  476.             mSelectedDate.setTimeInMillis(item.getDate().getTimeInMillis());
  477.              
  478.             int day = getIndexFromDates(mSelectedDate, startDate);
  479.  
  480.             contentText.setText(getDateShortString(mSelectedDate));
  481.             contentText.setText("无数据");
  482.                  
  483.             Log.i("sys", "mFirstDateOfPanel=" + mFirstDateOfPanel.get(Calendar.DATE) + " calCalendar=" + mViewDate.get(Calendar.DATE) + " mTodayDate=" + mTodayDate.get(Calendar.DATE)
  484.                     + " mSelectedDate=" + mSelectedDate.get(Calendar.DATE) +" day = "+day);
  485.             item.setSelected(true);
  486.             refreshCalendar();
  487.         }
  488.     };
  489.      
  490.     @Deprecated
  491.     public Calendar getEndDate(Calendar startDate) {
  492.         // Calendar end = GetStartDate(enddate);
  493.         Calendar endDate = Calendar.getInstance();
  494.         endDate = (Calendar) startDate.clone();
  495.         endDate.add(Calendar.DAY_OF_MONTH, 41);
  496.         return endDate;
  497.     }
  498. }
  499.  
  500.  
  501. 星期View
  502.  
  503. public class DateWidgetWeekView extends View {
  504.     // 字体大小
  505.     private final static int fTextSize = 22;
  506.     private Paint pt = new Paint();
  507.     private RectF rect = new RectF();
  508.     private int iWeekDay = -1;
  509.  
  510.     public DateWidgetWeekView(Context context, int iWidth, int iHeight) {
  511.         super(context);
  512.         setLayoutParams(new LayoutParams(iWidth, iHeight));
  513.     }
  514.  
  515.     @Override
  516.     protected void onDraw(Canvas canvas) {
  517.         super.onDraw(canvas);
  518.  
  519.         // 设置矩形大小
  520.         rect.set(0, 0, this.getWidth(), this.getHeight());
  521.         rect.inset(1, 1);
  522.  
  523.         // 绘制日历头部
  524.         drawDayHeader(canvas);
  525.     }
  526.  
  527.     private void drawDayHeader(Canvas canvas) {
  528.         // 画矩形,并设置矩形画笔的颜色
  529.         pt.setColor(CalenderActivity.Calendar_WeekBgColor);
  530.         canvas.drawRect(rect, pt);
  531.  
  532.         // 写入日历头部,设置画笔参数
  533.         pt.setTypeface(null);
  534.         pt.setTextSize(fTextSize);
  535.         pt.setAntiAlias(true);
  536.         pt.setFakeBoldText(true);
  537.         pt.setColor(CalenderActivity.Calendar_WeekFontColor);
  538.          
  539.         // draw day name
  540.         final String sDayName = CalenderUtil.getWeekDayName(iWeekDay);
  541.         final int iPosX = (int) rect.left + ((int) rect.width() >> 1)
  542.                 - ((int) pt.measureText(sDayName) >> 1);
  543.         final int iPosY = (int) (this.getHeight()
  544.                 - (this.getHeight() - getTextHeight()) / 2 - pt
  545.                 .getFontMetrics().bottom);
  546.         canvas.drawText(sDayName, iPosX, iPosY, pt);
  547.     }
  548.  
  549.     // 得到字体高度
  550.     private int getTextHeight() {
  551.         return (int) (-pt.ascent() + pt.descent());
  552.     }
  553.  
  554.     // 得到一星期的第几天的文本标记
  555.     public void setData(int iWeekDay) {
  556.         this.iWeekDay = iWeekDay;
  557.     }
  558. }
  559.  
  560.  
  561. 日期View
  562.  
  563. /**
  564.  * 日历控件单元格绘制类
  565.  * @Description: 日历控件单元格绘制类
  566.  
  567.  * @FileName: DateWidgetDayView.java
  568.  */
  569. public class DateWidgetDayView extends View {
  570.     // 字体大小
  571.     private static final int fTextSize = 28;
  572.      
  573.     // 基本元素
  574.     private OnDateItemClickListener itemClick = null;
  575.     private Paint mPaint = new Paint();
  576.     private RectF rect = new RectF();
  577.     private String sDate = "";
  578.  
  579.     // 当前日期
  580.     private int iDateYear = 0;
  581.     private int iDateMonth = 0;
  582.     private int iDateDay = 0;
  583.  
  584.     // 布尔变量
  585.     private boolean hasSelected = false;
  586.     private boolean isActiveMonth = false;
  587.     private boolean isToday = false;
  588.     private boolean isTouchedDown = false;
  589.     private boolean isHoliday = false;
  590.     private boolean hasMSG = false;
  591.  
  592.     public static int ANIM_ALPHA_DURATION = 100;
  593.  
  594.     public interface OnDateItemClickListener {
  595.         public void OnClick(DateWidgetDayView item);
  596.     }
  597.  
  598.     // 构造函数
  599.     public DateWidgetDayView(Context context, int iWidth, int iHeight) {
  600.         super(context);
  601.         setFocusable(true);
  602.         setLayoutParams(new LayoutParams(iWidth, iHeight));
  603.     }
  604.  
  605.     // 取变量值
  606.     public Calendar getDate() {
  607.         Calendar calDate = Calendar.getInstance();
  608.         calDate.clear();
  609.         calDate.set(Calendar.YEAR, iDateYear);
  610.         calDate.set(Calendar.MONTH, iDateMonth);
  611.         calDate.set(Calendar.DAY_OF_MONTH, iDateDay);
  612.         return calDate;
  613.     }
  614.      
  615.     // 是否有消息
  616.     public boolean hasMSG() {
  617.         return this.hasMSG;
  618.     }
  619.  
  620.     // 是否假期
  621.     public boolean isHoliday() {
  622.         return this.isHoliday;
  623.     }
  624.          
  625.     // 设置变量值
  626.     public void setData(int iYear, int iMonth, int iDay, Boolean bToday,
  627.             Boolean bHoliday, int iActiveMonth, boolean hasRecord) {
  628.         iDateYear = iYear;
  629.         iDateMonth = iMonth;
  630.         iDateDay = iDay;
  631.  
  632.         this.sDate = Integer.toString(iDateDay);
  633.         this.isActiveMonth = (iDateMonth == iActiveMonth);
  634.         this.isToday = bToday;
  635.         this.isHoliday = bHoliday;
  636.         this.hasMSG = hasRecord;
  637.     }
  638.  
  639.     // 重载绘制方法
  640.     @Override
  641.     protected void onDraw(Canvas canvas) {
  642.         // TODO Auto-generated method stub
  643.         super.onDraw(canvas);
  644.  
  645.         rect.set(0, 0, this.getWidth(), this.getHeight());
  646.         rect.inset(1, 1);
  647.  
  648.         final boolean bFocused = IsViewFocused();
  649.  
  650.         drawDayView(canvas, bFocused);
  651.         drawDayNumber(canvas);
  652.     }
  653.  
  654.     public boolean IsViewFocused() {
  655.         return (this.isFocused() || isTouchedDown);
  656.     }
  657.  
  658.     // 绘制日历方格
  659.     private void drawDayView(Canvas canvas, boolean bFocused) {
  660.  
  661.         if (hasSelected || bFocused) {
  662.             LinearGradient lGradBkg = null;
  663.  
  664.             if (bFocused) {
  665.                 lGradBkg = new LinearGradient(rect.left, 0, rect.right, 0,
  666.                         0xffaa5500, 0xffffddbb, Shader.TileMode.CLAMP);
  667.             }
  668.  
  669.             if (hasSelected) {
  670.                 lGradBkg = new LinearGradient(rect.left, 0, rect.right, 0,
  671.                         0xff225599, 0xffbbddff, Shader.TileMode.CLAMP);
  672.             }
  673.  
  674.             if (lGradBkg != null) {
  675.                 mPaint.setShader(lGradBkg);
  676.                 canvas.drawRect(rect, mPaint);
  677.             }
  678.  
  679.             mPaint.setShader(null);
  680.  
  681.         } else {
  682.             mPaint.setColor(getColorBkg(isHoliday, isToday));
  683.             canvas.drawRect(rect, mPaint);
  684.         }
  685.          
  686.         if(isHoliday){
  687.             mPaint.setColor(CalenderActivity.IsHoliday_BgColor);
  688.             canvas.drawRect(rect, mPaint);
  689.         }
  690.  
  691.         if (hasMSG) {
  692.             markHasMSGReminder(canvas, CalenderActivity.Special_Reminder);
  693.         }
  694.         // else if (!hasRecord && !bToday && !bSelected) {
  695.         // CreateReminder(canvas, Calendar_TestActivity.Calendar_DayBgColor);
  696.         // }
  697.     }
  698.  
  699.     // 绘制日历中的数字
  700.     public void drawDayNumber(Canvas canvas) {
  701.         // draw day number
  702.         mPaint.setTypeface(null);
  703.         mPaint.setAntiAlias(true);
  704.         mPaint.setShader(null);
  705.         mPaint.setFakeBoldText(true);
  706.         mPaint.setTextSize(fTextSize);
  707.         mPaint.setColor(CalenderActivity.IsPresentMonth_FontColor);
  708.         mPaint.setUnderlineText(false);
  709.          
  710.         if (!isActiveMonth)
  711.             mPaint.setColor(CalenderActivity.UnPresentMonth_FontColor);
  712.  
  713.         if (isToday)
  714.             mPaint.setUnderlineText(true);
  715.  
  716.         final int iPosX = (int) rect.left + ((int) rect.width() >> 1) - ((int) mPaint.measureText(sDate) >> 1);
  717.  
  718.         final int iPosY = (int) (this.getHeight() - (this.getHeight() - getTextHeight()) / 2 - mPaint .getFontMetrics().bottom);
  719.  
  720.         canvas.drawText(sDate, iPosX, iPosY, mPaint);
  721.  
  722.         mPaint.setUnderlineText(false);
  723.     }
  724.  
  725.     // 得到字体高度
  726.     private int getTextHeight() {
  727.         return (int) (-mPaint.ascent() + mPaint.descent());
  728.     }
  729.  
  730.     // 根据条件返回不同颜色值
  731.     public static int getColorBkg(boolean bHoliday, boolean bToday) {
  732.         if (bToday)
  733.             return CalenderActivity.IsToday_BgColor;
  734.         // if (bHoliday) //如需周末有特殊背景色,可去掉注释
  735.         // return Calendar_TestActivity.isHoliday_BgColor;
  736.         return CalenderActivity.Calendar_DayBgColor;
  737.     }
  738.  
  739.     // 设置是否被选中
  740.     @Override
  741.     public void setSelected(boolean bEnable) {
  742.         if (this.hasSelected != bEnable) {
  743.             this.hasSelected = bEnable;
  744.             this.invalidate();
  745.         }
  746.     }
  747.  
  748.     public void setItemClick(OnDateItemClickListener itemClick) {
  749.         this.itemClick = itemClick;
  750.     }
  751.  
  752.     public void doItemClick() {
  753.         if (itemClick != null)
  754.             itemClick.OnClick(this);
  755.     }
  756.  
  757.     // 点击事件
  758.     @Override
  759.     public boolean onTouchEvent(MotionEvent event) {
  760.         boolean bHandled = false;
  761.         if (event.getAction() == MotionEvent.ACTION_DOWN) {
  762.             bHandled = true;
  763.             isTouchedDown = true;
  764.             invalidate();
  765.             startAlphaAnimIn(DateWidgetDayView.this);
  766.         }
  767.         if (event.getAction() == MotionEvent.ACTION_CANCEL) {
  768.             bHandled = true;
  769.             isTouchedDown = false;
  770.             invalidate();
  771.         }
  772.         if (event.getAction() == MotionEvent.ACTION_UP) {
  773.             bHandled = true;
  774.             isTouchedDown = false;
  775.             invalidate();
  776.             doItemClick();
  777.         }
  778.         return bHandled;
  779.     }
  780.  
  781.     // 点击事件
  782.     @Override
  783.     public boolean onKeyDown(int keyCode, KeyEvent event) {
  784.         boolean bResult = super.onKeyDown(keyCode, event);
  785.         if ((keyCode == KeyEvent.KEYCODE_DPAD_CENTER)
  786.                 || (keyCode == KeyEvent.KEYCODE_ENTER)) {
  787.             doItemClick();
  788.         }
  789.         return bResult;
  790.     }
  791.  
  792.     // 不透明度渐变
  793.     public static void startAlphaAnimIn(View view) {
  794.         AlphaAnimation anim = new AlphaAnimation(0.5F, 1);
  795.         anim.setDuration(ANIM_ALPHA_DURATION);
  796.         anim.startNow();
  797.         view.startAnimation(anim);
  798.     }
  799.  
  800.     //右上角画倒三角
  801.     public void markHasMSGReminder(Canvas canvas, int Color) {
  802.         mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
  803.         mPaint.setColor(Color);
  804.         Path path = new Path();
  805.         path.moveTo(rect.right - rect.width() / 4, rect.top);
  806.         path.lineTo(rect.right, rect.top);
  807.         path.lineTo(rect.right, rect.top + rect.width() / 4);
  808.         path.lineTo(rect.right - rect.width() / 4, rect.top);
  809.         path.close();
  810.         canvas.drawPath(path, mPaint);
  811.     }
  812. }
  813.  
  814. 工具类:
  815.  
  816. public class CalenderUtil {
  817.     private final static String[] vecStrWeekDayNames = getWeekDayNames();
  818.  
  819.     private static String[] getWeekDayNames() {
  820.         String[] vec = new String[10];
  821.  
  822.         vec[Calendar.SUNDAY] = "星期日";
  823.         vec[Calendar.MONDAY] = "星期一";
  824.         vec[Calendar.TUESDAY] = "星期二";
  825.         vec[Calendar.WEDNESDAY] = "星期三";
  826.         vec[Calendar.THURSDAY] = "星期四";
  827.         vec[Calendar.FRIDAY] = "星期五";
  828.         vec[Calendar.SATURDAY] = "星期六";
  829.          
  830.         return vec;
  831.     }
  832.  
  833.     public static String getWeekDayName(int iDay) {
  834.         return vecStrWeekDayNames[iDay];
  835.     }
  836.      
  837.     public static int getWeekDay(int index, int iFirstDayOfWeek) {
  838.         int iWeekDay = -1;
  839.  
  840.         if (iFirstDayOfWeek == Calendar.MONDAY) {
  841.             iWeekDay = index + Calendar.MONDAY;
  842.              
  843.             if (iWeekDay > Calendar.SATURDAY)
  844.                 iWeekDay = Calendar.SUNDAY;
  845.         }
  846.  
  847.         if (iFirstDayOfWeek == Calendar.SUNDAY) {
  848.             iWeekDay = index + Calendar.SUNDAY;
  849.         }
  850.  
  851.         return iWeekDay;
  852.     }
  853.      
  854.     /**
  855.      * Calculate the days with milliseconds
  856.      * @param intervalMs
  857.      * @return
  858.      */
  859.     public static int millisecondsToDays(long intervalMs) {
  860.         return Math.round((intervalMs / (1000 * 86400)));
  861.     }
  862.  
  863.     /**
  864.      * Return the milliseconds from 1970 to just
  865.      * @param calendar
  866.      */
  867.     public static void setTimeToMidnight(Calendar calendar) {
  868.         calendar.set(Calendar.HOUR_OF_DAY, 0);
  869.         calendar.set(Calendar.MINUTE, 0);
  870.         calendar.set(Calendar.SECOND, 0);
  871.         calendar.set(Calendar.MILLISECOND, 0);
  872.     }
  873. }
  874.  
  875.  
  876. calendar_main.xml:
  877. <?xml version="1.0" encoding="utf-8"?>
  878. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  879.     android:layout_width="fill_parent"
  880.     android:layout_height="fill_parent"
  881.     android:gravity="center_horizontal"
  882.     android:orientation="vertical" >
  883.  
  884.     <RelativeLayout
  885.         android:id="@+id/relativeLayout1"
  886.         android:layout_width="fill_parent"
  887.         android:layout_height="60dip"
  888.         android:background="#EDE8DD" >
  889.  
  890.         <TextView
  891.             android:id="@+id/Top_Date"
  892.             android:layout_width="150dip"
  893.             android:layout_height="wrap_content"
  894.             android:layout_centerInParent="true"
  895.             android:gravity="center_horizontal|center"
  896.             android:textColor="#424139"
  897.             android:textSize="19sp"
  898.             android:textStyle="bold" />
  899.  
  900.         <Button
  901.             android:id="@+id/btn_pre_month"
  902.             android:layout_width="wrap_content"
  903.             android:layout_height="wrap_content"
  904.             android:layout_alignParentLeft="true"
  905.             android:layout_centerVertical="true"
  906.             android:layout_marginLeft="30dp"
  907.             android:background="@drawable/previous_month"
  908.             android:text="" />
  909.  
  910.         <Button
  911.             android:id="@+id/btn_next_month"
  912.             android:layout_width="wrap_content"
  913.             android:layout_height="wrap_content"
  914.             android:layout_alignParentRight="true"
  915.             android:layout_centerVertical="true"
  916.             android:layout_marginRight="30dp"
  917.             android:background="@drawable/next_month"
  918.             android:text="" />
  919.     </RelativeLayout>
  920.      
  921.     <LinearLayout
  922.         android:id="@+id/date_calender_framelayout"
  923.         android:layout_height="fill_parent"
  924.         android:layout_width="fill_parent"
  925.         ></LinearLayout>
  926.  
  927. </LinearLayout>
  928. //java/6812

回复 "Android系统自定义实现日历控件"

这儿你可以回复上面这条便签

captcha