Android自定义日历控件

 

Android UI-自定义日历控件

  9738人阅读  评论(27)  收藏  举报

Android UI-自定义日历控件


2014年博客之星,投票地址点击打开链接

本篇博客笔者给大家分享一个日历控件,这里有个需求:要求显示当前月的日期,左右可以切换月份来查看日期。

我们想一想会如何去实现这样的一个控件,有开源的,但可能不太满足我们的特定的需求,这里笔者自定义了一个,读者可以根据自己的需求来修改代码。下面来说一下实现的思路:

首先我们要显示当前月份,自然我们要计算出当前的日期,并且把每一天对应到具体的星期,我们会有以下效果:

我们先想一下这样的效果用什么控件可以实现?很自然可以想到用网格视图GridView,但这里笔者使用的不是GridView, 因为使用GridView可能无法实现那个红色的圈圈,所以笔者决定自定义View,通过绘制来达到这样的效果。

这里我们定于一个日历卡,每一个月代表一个日历卡,我们通过计算每个月的日期,然后根据计算出来的位置绘制我们的数字。

我们知道,一个星期有七天,分别为星期日、星期一、星期二、星期三、星期四、星期五、星期六,这里有7列,一个月至少有28天,最多31天,所以至少应该有6行。组成6*7的方格图。

直接上代码:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.xiaowu.calendar;  
  2.   
  3. import android.content.Context;  
  4. import android.graphics.Canvas;  
  5. import android.graphics.Color;  
  6. import android.graphics.Paint;  
  7. import android.util.AttributeSet;  
  8. import android.view.MotionEvent;  
  9. import android.view.View;  
  10. import android.view.ViewConfiguration;  
  11.   
  12. /** 
  13.  * 自定义日历卡 
  14.  *  
  15.  * @author wuwenjie 
  16.  *  
  17.  */  
  18. public class CalendarCard extends View {  
  19.   
  20.     private static final int TOTAL_COL = 7// 7列  
  21.     private static final int TOTAL_ROW = 6// 6行  
  22.   
  23.     private Paint mCirclePaint; // 绘制圆形的画笔  
  24.     private Paint mTextPaint; // 绘制文本的画笔  
  25.     private int mViewWidth; // 视图的宽度  
  26.     private int mViewHeight; // 视图的高度  
  27.     private int mCellSpace; // 单元格间距  
  28.     private Row rows[] = new Row[TOTAL_ROW]; // 行数组,每个元素代表一行  
  29.     private static CustomDate mShowDate; // 自定义的日期,包括year,month,day  
  30.     private OnCellClickListener mCellClickListener; // 单元格点击回调事件  
  31.     private int touchSlop; //  
  32.     private boolean callBackCellSpace;  
  33.   
  34.     private Cell mClickCell;  
  35.     private float mDownX;  
  36.     private float mDownY;  
  37.   
  38.     /** 
  39.      * 单元格点击的回调接口 
  40.      *  
  41.      * @author wuwenjie 
  42.      *  
  43.      */  
  44.     public interface OnCellClickListener {  
  45.         void clickDate(CustomDate date); // 回调点击的日期  
  46.   
  47.         void changeDate(CustomDate date); // 回调滑动ViewPager改变的日期  
  48.     }  
  49.   
  50.     public CalendarCard(Context context, AttributeSet attrs, int defStyleAttr) {  
  51.         super(context, attrs, defStyleAttr);  
  52.         init(context);  
  53.     }  
  54.   
  55.     public CalendarCard(Context context, AttributeSet attrs) {  
  56.         super(context, attrs);  
  57.         init(context);  
  58.     }  
  59.   
  60.     public CalendarCard(Context context) {  
  61.         super(context);  
  62.         init(context);  
  63.     }  
  64.   
  65.     public CalendarCard(Context context, OnCellClickListener listener) {  
  66.         super(context);  
  67.         this.mCellClickListener = listener;  
  68.         init(context);  
  69.     }  
  70.   
  71.     private void init(Context context) {  
  72.         mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);  
  73.         mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);  
  74.         mCirclePaint.setStyle(Paint.Style.FILL);  
  75.         mCirclePaint.setColor(Color.parseColor("#F24949")); // 红色圆形  
  76.         touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();  
  77.   
  78.         initDate();  
  79.     }  
  80.   
  81.     private void initDate() {  
  82.         mShowDate = new CustomDate();  
  83.         fillDate();//  
  84.     }  
  85.   
  86.     private void fillDate() {  
  87.         int monthDay = DateUtil.getCurrentMonthDay(); // 今天  
  88.         int lastMonthDays = DateUtil.getMonthDays(mShowDate.year,  
  89.                 mShowDate.month - 1); // 上个月的天数  
  90.         int currentMonthDays = DateUtil.getMonthDays(mShowDate.year,  
  91.                 mShowDate.month); // 当前月的天数  
  92.         int firstDayWeek = DateUtil.getWeekDayFromDate(mShowDate.year,  
  93.                 mShowDate.month);  
  94.         boolean isCurrentMonth = false;  
  95.         if (DateUtil.isCurrentMonth(mShowDate)) {  
  96.             isCurrentMonth = true;  
  97.         }  
  98.         int day = 0;  
  99.         for (int j = 0; j < TOTAL_ROW; j++) {  
  100.             rows[j] = new Row(j);  
  101.             for (int i = 0; i < TOTAL_COL; i++) {  
  102.                 int position = i + j * TOTAL_COL; // 单元格位置  
  103.                 // 这个月的  
  104.                 if (position >= firstDayWeek  
  105.                         && position < firstDayWeek + currentMonthDays) {  
  106.                     day++;  
  107.                     rows[j].cells[i] = new Cell(CustomDate.modifiDayForObject(  
  108.                             mShowDate, day), State.CURRENT_MONTH_DAY, i, j);  
  109.                     // 今天  
  110.                     if (isCurrentMonth && day == monthDay ) {  
  111.                         CustomDate date = CustomDate.modifiDayForObject(mShowDate, day);  
  112.                         rows[j].cells[i] = new Cell(date, State.TODAY, i, j);  
  113.                     }  
  114.   
  115.                     if (isCurrentMonth && day > monthDay) { // 如果比这个月的今天要大,表示还没到  
  116.                         rows[j].cells[i] = new Cell(  
  117.                                 CustomDate.modifiDayForObject(mShowDate, day),  
  118.                                 State.UNREACH_DAY, i, j);  
  119.                     }  
  120.   
  121.                     // 过去一个月  
  122.                 } else if (position < firstDayWeek) {  
  123.                     rows[j].cells[i] = new Cell(new CustomDate(mShowDate.year,  
  124.                             mShowDate.month - 1, lastMonthDays  
  125.                                     - (firstDayWeek - position - 1)),  
  126.                             State.PAST_MONTH_DAY, i, j);  
  127.                     // 下个月  
  128.                 } else if (position >= firstDayWeek + currentMonthDays) {  
  129.                     rows[j].cells[i] = new Cell((new CustomDate(mShowDate.year,  
  130.                             mShowDate.month + 1, position - firstDayWeek  
  131.                                     - currentMonthDays + 1)),  
  132.                             State.NEXT_MONTH_DAY, i, j);  
  133.                 }  
  134.             }  
  135.         }  
  136.         mCellClickListener.changeDate(mShowDate);  
  137.     }  
  138.   
  139.     @Override  
  140.     protected void onDraw(Canvas canvas) {  
  141.         super.onDraw(canvas);  
  142.         for (int i = 0; i < TOTAL_ROW; i++) {  
  143.             if (rows[i] != null) {  
  144.                 rows[i].drawCells(canvas);  
  145.             }  
  146.         }  
  147.     }  
  148.   
  149.     @Override  
  150.     protected void onSizeChanged(int w, int h, int oldw, int oldh) {  
  151.         super.onSizeChanged(w, h, oldw, oldh);  
  152.         mViewWidth = w;  
  153.         mViewHeight = h;  
  154.         mCellSpace = Math.min(mViewHeight / TOTAL_ROW, mViewWidth / TOTAL_COL);  
  155.         if (!callBackCellSpace) {  
  156.             callBackCellSpace = true;  
  157.         }  
  158.         mTextPaint.setTextSize(mCellSpace / 3);  
  159.     }  
  160.   
  161.     @Override  
  162.     public boolean onTouchEvent(MotionEvent event) {  
  163.         switch (event.getAction()) {  
  164.         case MotionEvent.ACTION_DOWN:  
  165.             mDownX = event.getX();  
  166.             mDownY = event.getY();  
  167.             break;  
  168.         case MotionEvent.ACTION_UP:  
  169.             float disX = event.getX() - mDownX;  
  170.             float disY = event.getY() - mDownY;  
  171.             if (Math.abs(disX) < touchSlop && Math.abs(disY) < touchSlop) {  
  172.                 int col = (int) (mDownX / mCellSpace);  
  173.                 int row = (int) (mDownY / mCellSpace);  
  174.                 measureClickCell(col, row);  
  175.             }  
  176.             break;  
  177.         default:  
  178.             break;  
  179.         }  
  180.   
  181.         return true;  
  182.     }  
  183.   
  184.     /** 
  185.      * 计算点击的单元格 
  186.      * @param col 
  187.      * @param row 
  188.      */  
  189.     private void measureClickCell(int col, int row) {  
  190.         if (col >= TOTAL_COL || row >= TOTAL_ROW)  
  191.             return;  
  192.         if (mClickCell != null) {  
  193.             rows[mClickCell.j].cells[mClickCell.i] = mClickCell;  
  194.         }  
  195.         if (rows[row] != null) {  
  196.             mClickCell = new Cell(rows[row].cells[col].date,  
  197.                     rows[row].cells[col].state, rows[row].cells[col].i,  
  198.                     rows[row].cells[col].j);  
  199.   
  200.             CustomDate date = rows[row].cells[col].date;  
  201.             date.week = col;  
  202.             mCellClickListener.clickDate(date);  
  203.   
  204.             // 刷新界面  
  205.             update();  
  206.         }  
  207.     }  
  208.   
  209.     /** 
  210.      * 组元素 
  211.      *  
  212.      * @author wuwenjie 
  213.      *  
  214.      */  
  215.     class Row {  
  216.         public int j;  
  217.   
  218.         Row(int j) {  
  219.             this.j = j;  
  220.         }  
  221.   
  222.         public Cell[] cells = new Cell[TOTAL_COL];  
  223.   
  224.         // 绘制单元格  
  225.         public void drawCells(Canvas canvas) {  
  226.             for (int i = 0; i < cells.length; i++) {  
  227.                 if (cells[i] != null) {  
  228.                     cells[i].drawSelf(canvas);  
  229.                 }  
  230.             }  
  231.         }  
  232.   
  233.     }  
  234.   
  235.     /** 
  236.      * 单元格元素 
  237.      *  
  238.      * @author wuwenjie 
  239.      *  
  240.      */  
  241.     class Cell {  
  242.         public CustomDate date;  
  243.         public State state;  
  244.         public int i;  
  245.         public int j;  
  246.   
  247.         public Cell(CustomDate date, State state, int i, int j) {  
  248.             super();  
  249.             this.date = date;  
  250.             this.state = state;  
  251.             this.i = i;  
  252.             this.j = j;  
  253.         }  
  254.   
  255.         public void drawSelf(Canvas canvas) {  
  256.             switch (state) {  
  257.             case TODAY: // 今天  
  258.                 mTextPaint.setColor(Color.parseColor("#fffffe"));  
  259.                 canvas.drawCircle((float) (mCellSpace * (i + 0.5)),  
  260.                         (float) ((j + 0.5) * mCellSpace), mCellSpace / 3,  
  261.                         mCirclePaint);  
  262.                 break;  
  263.             case CURRENT_MONTH_DAY: // 当前月日期  
  264.                 mTextPaint.setColor(Color.BLACK);  
  265.                 break;  
  266.             case PAST_MONTH_DAY: // 过去一个月  
  267.             case NEXT_MONTH_DAY: // 下一个月  
  268.                 mTextPaint.setColor(Color.parseColor("#fffffe"));  
  269.                 break;  
  270.             case UNREACH_DAY: // 还未到的天  
  271.                 mTextPaint.setColor(Color.GRAY);  
  272.                 break;  
  273.             default:  
  274.                 break;  
  275.             }  
  276.             // 绘制文字  
  277.             String content = date.day + "";  
  278.             canvas.drawText(content,  
  279.                     (float) ((i + 0.5) * mCellSpace - mTextPaint  
  280.                             .measureText(content) / 2), (float) ((j + 0.7)  
  281.                             * mCellSpace - mTextPaint  
  282.                             .measureText(content, 01) / 2), mTextPaint);  
  283.         }  
  284.     }  
  285.   
  286.     /** 
  287.      *  
  288.      * @author wuwenjie 单元格的状态 当前月日期,过去的月的日期,下个月的日期 
  289.      */  
  290.     enum State {  
  291.         TODAY,CURRENT_MONTH_DAY, PAST_MONTH_DAY, NEXT_MONTH_DAY, UNREACH_DAY;  
  292.     }  
  293.   
  294.     // 从左往右划,上一个月  
  295.     public void leftSlide() {  
  296.         if (mShowDate.month == 1) {  
  297.             mShowDate.month = 12;  
  298.             mShowDate.year -= 1;  
  299.         } else {  
  300.             mShowDate.month -= 1;  
  301.         }  
  302.         update();  
  303.     }  
  304.   
  305.     // 从右往左划,下一个月  
  306.     public void rightSlide() {  
  307.         if (mShowDate.month == 12) {  
  308.             mShowDate.month = 1;  
  309.             mShowDate.year += 1;  
  310.         } else {  
  311.             mShowDate.month += 1;  
  312.         }  
  313.         update();  
  314.     }  
  315.   
  316.     public void update() {  
  317.         fillDate();  
  318.         invalidate();  
  319.     }  
  320.   
  321. }  

  

/CustomCalendarView/src/com/xiaowu/calendar/DateUtil.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.xiaowu.calendar;  
  2.   
  3. import android.annotation.SuppressLint;  
  4. import android.util.Log;  
  5.   
  6. import java.text.ParseException;  
  7. import java.text.SimpleDateFormat;  
  8. import java.util.Calendar;  
  9. import java.util.Date;  
  10. import java.util.GregorianCalendar;  
  11.   
  12.   
  13. public class DateUtil {  
  14.   
  15.     public static String[] weekName = { "周日""周一""周二""周三""周四""周五","周六" };  
  16.   
  17.     public static int getMonthDays(int year, int month) {  
  18.         if (month > 12) {  
  19.             month = 1;  
  20.             year += 1;  
  21.         } else if (month < 1) {  
  22.             month = 12;  
  23.             year -= 1;  
  24.         }  
  25.         int[] arr = { 312831303130313130313031 };  
  26.         int days = 0;  
  27.   
  28.         if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {  
  29.             arr[1] = 29// 闰年2月29天  
  30.         }  
  31.   
  32.         try {  
  33.             days = arr[month - 1];  
  34.         } catch (Exception e) {  
  35.             e.getStackTrace();  
  36.         }  
  37.   
  38.         return days;  
  39.     }  
  40.       
  41.     public static int getYear() {  
  42.         return Calendar.getInstance().get(Calendar.YEAR);  
  43.     }  
  44.   
  45.     public static int getMonth() {  
  46.         return Calendar.getInstance().get(Calendar.MONTH) + 1;  
  47.     }  
  48.   
  49.     public static int getCurrentMonthDay() {  
  50.         return Calendar.getInstance().get(Calendar.DAY_OF_MONTH);  
  51.     }  
  52.   
  53.     public static int getWeekDay() {  
  54.         return Calendar.getInstance().get(Calendar.DAY_OF_WEEK);  
  55.     }  
  56.   
  57.     public static int getHour() {  
  58.         return Calendar.getInstance().get(Calendar.HOUR_OF_DAY);  
  59.     }  
  60.     public static int getMinute() {  
  61.         return Calendar.getInstance().get(Calendar.MINUTE);  
  62.     }  
  63.     public static CustomDate getNextSunday() {  
  64.           
  65.         Calendar c = Calendar.getInstance();  
  66.         c.add(Calendar.DATE, 7 - getWeekDay()+1);  
  67.         CustomDate date = new CustomDate(c.get(Calendar.YEAR),  
  68.                 c.get(Calendar.MONTH)+1, c.get(Calendar.DAY_OF_MONTH));  
  69.         return date;  
  70.     }  
  71.   
  72.     public static int[] getWeekSunday(int year, int month, int day, int pervious) {  
  73.         int[] time = new int[3];  
  74.         Calendar c = Calendar.getInstance();  
  75.         c.set(Calendar.YEAR, year);  
  76.         c.set(Calendar.MONTH, month);  
  77.         c.set(Calendar.DAY_OF_MONTH, day);  
  78.         c.add(Calendar.DAY_OF_MONTH, pervious);  
  79.         time[0] = c.get(Calendar.YEAR);  
  80.         time[1] = c.get(Calendar.MONTH )+1;  
  81.         time[2] = c.get(Calendar.DAY_OF_MONTH);  
  82.         return time;  
  83.   
  84.     }  
  85.   
  86.     public static int getWeekDayFromDate(int year, int month) {  
  87.         Calendar cal = Calendar.getInstance();  
  88.         cal.setTime(getDateFromString(year, month));  
  89.         int week_index = cal.get(Calendar.DAY_OF_WEEK) - 1;  
  90.         if (week_index < 0) {  
  91.             week_index = 0;  
  92.         }  
  93.         return week_index;  
  94.     }  
  95.   
  96.     @SuppressLint("SimpleDateFormat")  
  97.     public static Date getDateFromString(int year, int month) {  
  98.         String dateString = year + "-" + (month > 9 ? month : ("0" + month))  
  99.                 + "-01";  
  100.         Date date = null;  
  101.         try {  
  102.             SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");  
  103.             date = sdf.parse(dateString);  
  104.         } catch (ParseException e) {  
  105.             System.out.println(e.getMessage());  
  106.         }  
  107.         return date;  
  108.     }  
  109.     public static boolean isToday(CustomDate date){  
  110.         return(date.year == DateUtil.getYear() &&  
  111.                 date.month == DateUtil.getMonth()   
  112.                 && date.day == DateUtil.getCurrentMonthDay());  
  113.     }  
  114.       
  115.     public static boolean isCurrentMonth(CustomDate date){  
  116.         return(date.year == DateUtil.getYear() &&  
  117.                 date.month == DateUtil.getMonth());  
  118.     }  
  119. }  


/CustomCalendarView/src/com/xiaowu/calendar/CustomDate.java、

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.xiaowu.calendar;  
  2.   
  3. import java.io.Serializable;  
  4. public class CustomDate implements Serializable{  
  5.       
  6.       
  7.     private static final long serialVersionUID = 1L;  
  8.     public int year;  
  9.     public int month;  
  10.     public int day;  
  11.     public int week;  
  12.       
  13.     public CustomDate(int year,int month,int day){  
  14.         if(month > 12){  
  15.             month = 1;  
  16.             year++;  
  17.         }else if(month <1){  
  18.             month = 12;  
  19.             year--;  
  20.         }  
  21.         this.year = year;  
  22.         this.month = month;  
  23.         this.day = day;  
  24.     }  
  25.       
  26.     public CustomDate(){  
  27.         this.year = DateUtil.getYear();  
  28.         this.month = DateUtil.getMonth();  
  29.         this.day = DateUtil.getCurrentMonthDay();  
  30.     }  
  31.       
  32.     public static CustomDate modifiDayForObject(CustomDate date,int day){  
  33.         CustomDate modifiDate = new CustomDate(date.year,date.month,day);  
  34.         return modifiDate;  
  35.     }  
  36.     @Override  
  37.     public String toString() {  
  38.         return year+"-"+month+"-"+day;  
  39.     }  
  40.   
  41.     public int getYear() {  
  42.         return year;  
  43.     }  
  44.   
  45.     public void setYear(int year) {  
  46.         this.year = year;  
  47.     }  
  48.   
  49.     public int getMonth() {  
  50.         return month;  
  51.     }  
  52.   
  53.     public void setMonth(int month) {  
  54.         this.month = month;  
  55.     }  
  56.   
  57.     public int getDay() {  
  58.         return day;  
  59.     }  
  60.   
  61.     public void setDay(int day) {  
  62.         this.day = day;  
  63.     }  
  64.   
  65.     public int getWeek() {  
  66.         return week;  
  67.     }  
  68.   
  69.     public void setWeek(int week) {  
  70.         this.week = week;  
  71.     }  
  72.   
  73. }  



  所有绘制的操作在onDraw方面里实现,我这里定于了一个组对象Row、单元格元素Cell,通过Row[row].cell[col]来确定一个单元格,每次调用invalidate重绘视图。

接着,我们有一个需求需要左右切换,我们选用最熟悉的ViewPager,但这里有个问题,怎么实现无限循环呢,

这里我们传入一个日历卡数组,让ViewPager循环复用这几个日历卡,避免消耗内存。

/CustomCalendarView/src/com/xiaowu/calendar/CalendarViewAdapter.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.xiaowu.calendar;  
  2.   
  3. import android.support.v4.view.PagerAdapter;  
  4. import android.support.v4.view.ViewPager;  
  5. import android.view.View;  
  6. import android.view.ViewGroup;  
  7.   
  8. public class CalendarViewAdapter<V extends View> extends PagerAdapter {  
  9.     public static final String TAG = "CalendarViewAdapter";  
  10.     private V[] views;  
  11.   
  12.     public CalendarViewAdapter(V[] views) {  
  13.         super();  
  14.         this.views = views;  
  15.     }  
  16.   
  17.       
  18.     @Override  
  19.     public Object instantiateItem(ViewGroup container, int position) {  
  20.               
  21.         if (((ViewPager) container).getChildCount() == views.length) {  
  22.             ((ViewPager) container).removeView(views[position % views.length]);  
  23.         }  
  24.           
  25.         ((ViewPager) container).addView(views[position % views.length], 0);  
  26.         return views[position % views.length];  
  27.     }  
  28.   
  29.     @Override  
  30.     public int getCount() {  
  31.         return Integer.MAX_VALUE;  
  32.     }  
  33.   
  34.     @Override  
  35.     public boolean isViewFromObject(View view, Object object) {  
  36.         return view == ((View) object);  
  37.     }  
  38.   
  39.     @Override  
  40.     public void destroyItem(ViewGroup container, int position, Object object) {  
  41.         ((ViewPager) container).removeView((View) container);  
  42.     }  
  43.       
  44.     public V[] getAllItems() {  
  45.         return views;  
  46.     }  
  47.   
  48. }  

布局文件:

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     xmlns:tools="http://schemas.android.com/tools"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent"  
  6.     android:background="@color/white"  
  7.     android:orientation="vertical" >  
  8.   
  9.     <RelativeLayout  
  10.         android:layout_width="match_parent"  
  11.         android:layout_height="50dp"  
  12.         android:background="#f6f1ea"  
  13.          >  
  14.   
  15.         <ImageButton  
  16.             android:id="@+id/btnPreMonth"  
  17.             android:layout_width="wrap_content"  
  18.             android:layout_height="wrap_content"  
  19.             android:layout_centerVertical="true"  
  20.             android:layout_marginRight="33dip"  
  21.             android:layout_toLeftOf="@+id/tvCurrentMonth"  
  22.             android:background="@drawable/ic_before" />  
  23.   
  24.         <ImageButton  
  25.             android:id="@+id/btnNextMonth"  
  26.             android:layout_width="wrap_content"  
  27.             android:layout_height="wrap_content"  
  28.             android:layout_centerVertical="true"  
  29.             android:layout_marginLeft="33dip"  
  30.             android:layout_toRightOf="@+id/tvCurrentMonth"  
  31.             android:background="@drawable/ic_next" />  
  32.   
  33.         <TextView  
  34.             android:id="@+id/tvCurrentMonth"  
  35.             android:layout_width="wrap_content"  
  36.             android:layout_height="wrap_content"  
  37.             android:layout_centerInParent="true"  
  38.             android:layout_centerVertical="true"  
  39.             android:text="11月"  
  40.             android:textColor="#323232"  
  41.             android:textSize="22sp" />  
  42.   
  43.         <ImageButton  
  44.             android:id="@+id/btnClose"  
  45.             android:layout_width="wrap_content"  
  46.             android:layout_height="wrap_content"  
  47.             android:layout_alignParentRight="true"  
  48.             android:layout_centerVertical="true"  
  49.             android:layout_marginRight="15dp"  
  50.             android:background="@drawable/ic_close" />  
  51.     </RelativeLayout>  
  52.   
  53.     <LinearLayout  
  54.         android:layout_width="match_parent"  
  55.         android:layout_height="wrap_content"  
  56.         android:layout_marginTop="15dp"  
  57.         android:orientation="vertical"  
  58.          >  
  59.   
  60.         <TableLayout  
  61.             android:layout_width="match_parent"  
  62.             android:layout_height="20dip"  
  63.             android:layout_marginBottom="2dip"  
  64.             android:layout_marginTop="2dip" >  
  65.   
  66.             <TableRow>  
  67.   
  68.                 <TextView  
  69.                     style="@style/dateStyle"  
  70.                     android:text="@string/sunday"  
  71.                     android:textColor="@color/canlendar_text_color" />  
  72.   
  73.                 <TextView  
  74.                     style="@style/dateStyle"  
  75.                     android:text="@string/monday"  
  76.                     android:textColor="@color/canlendar_text_color" />  
  77.                 <TextView  
  78.                     style="@style/dateStyle"  
  79.                     android:text="@string/thesday"  
  80.                     android:textColor="@color/canlendar_text_color" />  
  81.   
  82.                 <TextView  
  83.                     style="@style/dateStyle"  
  84.                     android:text="@string/wednesday"  
  85.                     android:textColor="@color/canlendar_text_color" />  
  86.   
  87.                 <TextView  
  88.                     style="@style/dateStyle"  
  89.                     android:text="@string/thursday"  
  90.                     android:textColor="@color/canlendar_text_color" />  
  91.   
  92.                 <TextView  
  93.                     style="@style/dateStyle"  
  94.                     android:text="@string/friday"  
  95.                     android:textColor="@color/canlendar_text_color" />  
  96.   
  97.                 <TextView  
  98.                     style="@style/dateStyle"  
  99.                     android:text="@string/saturday"  
  100.                     android:textColor="@color/canlendar_text_color" />  
  101.             </TableRow>  
  102.         </TableLayout>  
  103.     </LinearLayout>  
  104.   
  105.     <LinearLayout  
  106.         android:layout_width="match_parent"  
  107.         android:layout_height="0dp"  
  108.         android:orientation="vertical"   
  109.         android:layout_weight="1"  
  110.         android:layout_marginTop="15dp">  
  111.   
  112.         <android.support.v4.view.ViewPager  
  113.             android:id="@+id/vp_calendar"  
  114.             android:layout_width="match_parent"  
  115.             android:layout_height="wrap_content"  
  116.             android:layout_gravity="center"  
  117.             android:background="@color/white" >  
  118.         </android.support.v4.view.ViewPager>  
  119.     </LinearLayout>  
  120.   
  121. </LinearLayout>  


/CustomCalendarView/src/com/xiaowu/calendar/MainActivity.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.xiaowu.calendar;  
  2.   
  3.   
  4. import android.app.Activity;  
  5. import android.os.Bundle;  
  6. import android.support.v4.view.ViewPager;  
  7. import android.support.v4.view.ViewPager.OnPageChangeListener;  
  8. import android.view.View;  
  9. import android.view.View.OnClickListener;  
  10. import android.view.Window;  
  11. import android.widget.ImageButton;  
  12. import android.widget.TextView;  
  13.   
  14. import com.xiaowu.calendar.CalendarCard.OnCellClickListener;  
  15.   
  16. public class MainActivity extends Activity implements OnClickListener, OnCellClickListener{  
  17.     private ViewPager mViewPager;  
  18.     private int mCurrentIndex = 498;  
  19.     private CalendarCard[] mShowViews;  
  20.     private CalendarViewAdapter<CalendarCard> adapter;  
  21.     private SildeDirection mDirection = SildeDirection.NO_SILDE;  
  22.     enum SildeDirection {  
  23.         RIGHT, LEFT, NO_SILDE;  
  24.     }  
  25.       
  26.     private ImageButton preImgBtn, nextImgBtn;  
  27.     private TextView monthText;  
  28.     private ImageButton closeImgBtn;  
  29.   
  30.     @Override  
  31.     protected void onCreate(Bundle savedInstanceState) {  
  32.         super.onCreate(savedInstanceState);  
  33.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  34.         setContentView(R.layout.activity_main);  
  35.         mViewPager = (ViewPager) this.findViewById(R.id.vp_calendar);  
  36.         preImgBtn = (ImageButton) this.findViewById(R.id.btnPreMonth);  
  37.         nextImgBtn = (ImageButton) this.findViewById(R.id.btnNextMonth);  
  38.         monthText = (TextView) this.findViewById(R.id.tvCurrentMonth);  
  39.         closeImgBtn = (ImageButton) this.findViewById(R.id.btnClose);  
  40.         preImgBtn.setOnClickListener(this);  
  41.         nextImgBtn.setOnClickListener(this);  
  42.         closeImgBtn.setOnClickListener(this);  
  43.           
  44.         CalendarCard[] views = new CalendarCard[3];  
  45.         for (int i = 0; i < 3; i++) {  
  46.             views[i] = new CalendarCard(thisthis);  
  47.         }  
  48.         adapter = new CalendarViewAdapter<>(views);  
  49.         setViewPager();  
  50.   
  51.     }  
  52.   
  53.     private void setViewPager() {  
  54.         mViewPager.setAdapter(adapter);  
  55.         mViewPager.setCurrentItem(498);  
  56.         mViewPager.setOnPageChangeListener(new OnPageChangeListener() {  
  57.               
  58.             @Override  
  59.             public void onPageSelected(int position) {  
  60.                 measureDirection(position);  
  61.                 updateCalendarView(position);                 
  62.             }  
  63.               
  64.             @Override  
  65.             public void onPageScrolled(int arg0, float arg1, int arg2) {  
  66.                   
  67.             }  
  68.               
  69.             @Override  
  70.             public void onPageScrollStateChanged(int arg0) {  
  71.                   
  72.             }  
  73.         });  
  74.     }  
  75.   
  76.     @Override  
  77.     public void onClick(View v) {  
  78.         switch (v.getId()) {  
  79.         case R.id.btnPreMonth:  
  80.             mViewPager.setCurrentItem(mViewPager.getCurrentItem() - 1);  
  81.             break;  
  82.         case R.id.btnNextMonth:  
  83.             mViewPager.setCurrentItem(mViewPager.getCurrentItem() + 1);  
  84.             break;  
  85.         case R.id.btnClose:  
  86.             finish();  
  87.             break;  
  88.         default:  
  89.             break;  
  90.         }  
  91.     }  
  92.   
  93.     @Override  
  94.     public void clickDate(CustomDate date) {  
  95.           
  96.     }  
  97.   
  98.     @Override  
  99.     public void changeDate(CustomDate date) {  
  100.         monthText.setText(date.month + "月");  
  101.     }  
  102.   
  103.     /** 
  104.      * 计算方向 
  105.      *  
  106.      * @param arg0 
  107.      */  
  108.     private void measureDirection(int arg0) {  
  109.   
  110.         if (arg0 > mCurrentIndex) {  
  111.             mDirection = SildeDirection.RIGHT;  
  112.   
  113.         } else if (arg0 < mCurrentIndex) {  
  114.             mDirection = SildeDirection.LEFT;  
  115.         }  
  116.         mCurrentIndex = arg0;  
  117.     }  
  118.   
  119.     // 更新日历视图  
  120.     private void updateCalendarView(int arg0) {  
  121.         mShowViews = adapter.getAllItems();  
  122.         if (mDirection == SildeDirection.RIGHT) {  
  123.             mShowViews[arg0 % mShowViews.length].rightSlide();  
  124.         } else if (mDirection == SildeDirection.LEFT) {  
  125.             mShowViews[arg0 % mShowViews.length].leftSlide();  
  126.         }  
  127.         mDirection = SildeDirection.NO_SILDE;  
  128.     }  
  129.   
  130.   
  131.       
  132. }  


用到的资源:

/CustomCalendarView/res/values/color.xml

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.     <color name="white">#ffffff</color>  
  4.      <color name="canlendar_text_color">#323232</color>  
  5. </resources>  


/CustomCalendarView/res/values/strings.xml

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.   
  4.     <string name="app_name">CustomCalendarView</string>  
  5.     <string name="hello_world">Hello world!</string>  
  6.     <string name="action_settings">Settings</string>  
  7.   
  8.       
  9.     <string name="sunday"></string>  
  10.     <string name="monday"></string>  
  11.     <string name="thesday"></string>  
  12.     <string name="wednesday"></string>  
  13.     <string name="thursday"></string>  
  14.     <string name="friday"></string>  
  15.     <string name="saturday"></string>  
  16.       
  17. </resources>  

/CustomCalendarView/res/values/styles.xml

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <resources>  
  2.   
  3.     <!--  
  4.         Base application theme, dependent on API level. This theme is replaced  
  5.         by AppBaseTheme from res/values-vXX/styles.xml on newer devices.  
  6.     -->  
  7.     <style name="AppBaseTheme" parent="android:Theme.Light">  
  8.         <!--  
  9.             Theme customizations available in newer API levels can go in  
  10.             res/values-vXX/styles.xml, while customizations related to  
  11.             backward-compatibility can go here.  
  12.         -->  
  13.     </style>  
  14.   
  15.     <!-- Application theme. -->  
  16.     <style name="AppTheme" parent="AppBaseTheme">  
  17.         <!-- All customizations that are NOT specific to a particular API-level can go here. -->  
  18.     </style>  
  19.       
  20.     <style name="dateStyle">  
  21.         <item name="android:layout_width">fill_parent</item>  
  22.         <item name="android:layout_height">fill_parent</item>  
  23.         <item name="android:layout_weight">1</item>  
  24.         <item name="android:gravity">center</item>  
  25.         <item name="android:textSize">16sp</item>  
  26.     </style>  
  27.   
  28. </resources>  

版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值