Android自定义控件之日历控件

来源:互联网 发布:淘宝怎么搜到假学生证 编辑:程序博客网 时间:2024/06/08 20:07

原文出处:http://blog.csdn.net/mr_dsw/article/details/48755993 

Android自定义控件之日历控件

三月份学习android,至今也有半年有余,中间也做过两个项目,但是依然感觉自己做的应用不是很有新意,比不上应用市场上那些应用如此绚丽。所以自己仍需继续努力。学习至今,仍感觉自定义控件是一块硬骨头,还没修炼到身后的内功,下面就切入正题,以一次项目的需求,来实现一个自定义的日历控件。效果图先来一发。

blob.png

我们分析下效果图,然后确定我们的需求。
(1)、绘制星期的自定义View,用于标识日期的礼拜。
(2)、绘制日期的自定义View。
(3)、绘制事务圆圈,从效果图中我们以红圈标识今日有事务。
(4)、绘制选中日期的颜色。
(5)、对选中日期进行点击事件的处理。

通过对效果图的分析,得出了我们的需求,我们在仔细分析效果图,发现里面就是绘制文字和绘制线条,所以我们只要回Canvas的这两个功能即可,主要的难点是如何将这些日期进行位置的安排,接下来我们就来逐个分析如何实现一个自定义View。

实现Week的自定义View

效果图

blob.png

分析下效果图,我们需要绘制上下两条线、然后绘制描述文字(日、一、二、三、四、五、六)。下面就讲解下我们的实现。先看着部分的源码,然后在分开讲解。

  1. public class WeekDayView extends View {
  2.         //上横线颜色
  3.         private int mTopLineColor = Color.parseColor("#CCE4F2");
  4.         //下横线颜色
  5.         private int mBottomLineColor = Color.parseColor("#CCE4F2");
  6.         //周一到周五的颜色
  7.         private int mWeedayColor = Color.parseColor("#1FC2F3");
  8.         //周六、周日的颜色
  9.         private int mWeekendColor = Color.parseColor("#fa4451");
  10.         //线的宽度
  11.         private int mStrokeWidth = 4;
  12.         private int mWeekSize = 14;
  13.         private Paint paint;
  14.         private DisplayMetrics mDisplayMetrics;
  15.         private String[] weekString = new String[]{"日","一","二","三","四","五","六"};
  16.         public WeekDayView(Context context, AttributeSet attrs) {
  17.             super(context, attrs);
  18.             mDisplayMetrics = getResources().getDisplayMetrics();
  19.             paint = new Paint();
  20.         }
  21.  
  22.         @Override
  23.         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  24.             int widthSize = MeasureSpec.getSize(widthMeasureSpec);
  25.             int widthMode = MeasureSpec.getMode(widthMeasureSpec);
  26.  
  27.             int heightSize = MeasureSpec.getSize(heightMeasureSpec);
  28.             int heightMode = MeasureSpec.getMode(heightMeasureSpec);
  29.  
  30.             if(heightMode == MeasureSpec.AT_MOST){
  31.                 heightSize = mDisplayMetrics.densityDpi * 30;
  32.             }
  33.             if(widthMode == MeasureSpec.AT_MOST){
  34.                 widthSize = mDisplayMetrics.densityDpi * 300;
  35.             }
  36.             setMeasuredDimension(widthSize, heightSize);
  37.         }
  38.  
  39.         @Override
  40.         protected void onDraw(Canvas canvas) {
  41.             int width = getWidth();
  42.             int height = getHeight();
  43.             //进行画上下线
  44.             paint.setStyle(Style.STROKE);
  45.             paint.setColor(mTopLineColor);
  46.             paint.setStrokeWidth(mStrokeWidth);
  47.             canvas.drawLine(0, 0, width, 0, paint);
  48.  
  49.             //画下横线
  50.             paint.setColor(mBottomLineColor);
  51.             canvas.drawLine(0, height, width, height, paint);
  52.             paint.setStyle(Style.FILL);
  53.             paint.setTextSize(mWeekSize * mDisplayMetrics.scaledDensity);
  54.             int columnWidth = width / 7;
  55.             for(int i=0;< weekString.length;i++){
  56.                 String text = weekString[i];
  57.                 int fontWidth = (int) paint.measureText(text);
  58.                 int startX = columnWidth * i + (columnWidth - fontWidth)/2;
  59.                 int startY = (int) (height/2 - (paint.ascent() + paint.descent())/2);
  60.                 if(text.indexOf("日") > -1|| text.indexOf("六") > -1){
  61.                     paint.setColor(mWeekendColor);
  62.                 }else{
  63.                     paint.setColor(mWeedayColor);
  64.                 }
  65.                 canvas.drawText(text, startX, startY, paint);
  66.             }
  67.         }
  68.  
  69.         /**
  70.          * 设置顶线的颜色
  71.          * @param mTopLineColor
  72.          */
  73.         public void setmTopLineColor(int mTopLineColor) {
  74.             this.mTopLineColor = mTopLineColor;
  75.         }
  76.  
  77.         /**
  78.          * 设置底线的颜色
  79.          * @param mBottomLineColor
  80.          */
  81.         public void setmBottomLineColor(int mBottomLineColor) {
  82.             this.mBottomLineColor = mBottomLineColor;
  83.         }
  84.  
  85.         /**
  86.          * 设置周一-五的颜色
  87.          * @return
  88.          */
  89.         public void setmWeedayColor(int mWeedayColor) {
  90.             this.mWeedayColor = mWeedayColor;
  91.         }
  92.  
  93.         /**
  94.          * 设置周六、周日的颜色
  95.          * @param mWeekendColor
  96.          */
  97.         public void setmWeekendColor(int mWeekendColor) {
  98.             this.mWeekendColor = mWeekendColor;
  99.         }
  100.  
  101.         /**
  102.          * 设置边线的宽度
  103.          * @param mStrokeWidth
  104.          */
  105.         public void setmStrokeWidth(int mStrokeWidth) {
  106.             this.mStrokeWidth = mStrokeWidth;
  107.         }
  108.  
  109.  
  110.         /**
  111.          * 设置字体的大小
  112.          * @param mWeekSize
  113.          */
  114.         public void setmWeekSize(int mWeekSize) {
  115.             this.mWeekSize = mWeekSize;
  116.         }
  117.  
  118.  
  119.         /**
  120.          * 设置星期的形式
  121.          * @param weekString
  122.          * 默认值  "日","一","二","三","四","五","六"
  123.          */
  124.         public void setWeekString(String[] weekString) {
  125.             this.weekString = weekString;
  126.         }
  127.     }

(1)、首先我们定义了我们需要的成员变量,比如上下线条的颜色、宽度、字体的大小、周期的表现形式。这些都是为了灵活定制而需要的。方便使用。
(2)、现在来看看onMeasure方法,我们知道在自定义view中,我们遇到wrap_content属性,这是view的大小可能就不是我们想要的了,所以我们在onMeasure方法中,指定此条件下的大小,即默认大小为300*30。
(3)、onDraw方法,我们在onDraw方法中进行我们需要内容的绘制。我们使用drawLine方法,进行上下横线的绘制,然后int columnWidth = width / 7;计算每列的宽度,为什么计算宽度呢?因为我们要将”日”,”一”,”二”,”三”,”四”,”五”,”六”这七个字放在对应格子的居中位置。通过drawText方法进行绘制文字,我们需要指定绘制文字的起始位置,为了达到居中的位置,我们需要进行计算。

  1. int startX = columnWidth * i + (columnWidth - fontWidth)/2;
  2. int startY = (int) (height/2 - (paint.ascent() + paint.descent())/2);

此处不是很了解的,可以参照下爱哥的文章。后面就是一些设置属性,没什么讲头。

至此很简单的实现了我们的week的自定义view。下面我们来分析下日期的实现。

实现日期Date的自定义View

类似WeekView的实现,我们在DateView中的难点也是如何放置这些日期date。先上源码,然后我们在具体分析:

  1. public class MonthDateView extends View {
  2.         private static final int NUM_COLUMNS = 7;
  3.         private static final int NUM_ROWS = 6;
  4.         private Paint mPaint;
  5.         private int mDayColor = Color.parseColor("#000000");
  6.         private int mSelectDayColor = Color.parseColor("#ffffff");
  7.         private int mSelectBGColor = Color.parseColor("#1FC2F3");
  8.         private int mCurrentColor = Color.parseColor("#ff0000");
  9.         private int mCurrYear,mCurrMonth,mCurrDay;
  10.         private int mSelYear,mSelMonth,mSelDay;
  11.         private int mColumnSize,mRowSize;
  12.         private DisplayMetrics mDisplayMetrics;
  13.         private int mDaySize = 18;
  14.         private TextView tv_date,tv_week;
  15.         private int weekRow;
  16.         private int [][] daysString;
  17.         private int mCircleRadius = 6;
  18.         private DateClick dateClick;
  19.         private int mCircleColor = Color.parseColor("#ff0000");
  20.         private List<Integer> daysHasThingList;
  21.         public MonthDateView(Context context, AttributeSet attrs) {
  22.             super(context, attrs);
  23.             mDisplayMetrics = getResources().getDisplayMetrics();
  24.             Calendar calendar = Calendar.getInstance();
  25.             mPaint = new Paint();
  26.             mCurrYear = calendar.get(Calendar.YEAR);
  27.             mCurrMonth = calendar.get(Calendar.MONTH);
  28.             mCurrDay = calendar.get(Calendar.DATE);
  29.             setSelectYearMonth(mCurrYear,mCurrMonth,mCurrDay);
  30.         }
  31.  
  32.         @Override
  33.         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  34.             int widthSize = MeasureSpec.getSize(widthMeasureSpec);
  35.             int widthMode = MeasureSpec.getMode(widthMeasureSpec);
  36.  
  37.             int heightSize = MeasureSpec.getSize(heightMeasureSpec);
  38.             int heightMode = MeasureSpec.getMode(heightMeasureSpec);
  39.  
  40.             if(heightMode == MeasureSpec.AT_MOST){
  41.                 heightSize = mDisplayMetrics.densityDpi * 200;
  42.             }
  43.             if(widthMode == MeasureSpec.AT_MOST){
  44.                 widthSize = mDisplayMetrics.densityDpi * 300;
  45.             }
  46.             setMeasuredDimension(widthSize, heightSize);
  47.         }
  48.  
  49.         @Override
  50.         protected void onDraw(Canvas canvas) {
  51.             initSize();
  52.             daysString = new int[6][7];
  53.             mPaint.setTextSize(mDaySize*mDisplayMetrics.scaledDensity);
  54.             String dayString;
  55.             int mMonthDays = DateUtils.getMonthDays(mSelYear, mSelMonth);
  56.             int weekNumber = DateUtils.getFirstDayWeek(mSelYear, mSelMonth);
  57.             Log.d("DateView", "DateView:" + mSelMonth+"月1号周" + weekNumber);
  58.             for(int day = 0;day < mMonthDays;day++){
  59.                 dayString = (day + 1) + "";
  60.                 int column = (day+weekNumber - 1) % 7;
  61.                 int row = (day+weekNumber - 1) / 7;
  62.                 daysString[row][column]=day + 1;
  63.                 int startX = (int) (mColumnSize * column + (mColumnSize - mPaint.measureText(dayString))/2);
  64.                 int startY = (int) (mRowSize * row + mRowSize/2 - (mPaint.ascent() + mPaint.descent())/2);
  65.                 if(dayString.equals(mSelDay+"")){
  66.                     //绘制背景色矩形
  67.                     int startRecX = mColumnSize * column;
  68.                     int startRecY = mRowSize * row;
  69.                     int endRecX = startRecX + mColumnSize;
  70.                     int endRecY = startRecY + mRowSize;
  71.                     mPaint.setColor(mSelectBGColor);
  72.                     canvas.drawRect(startRecX, startRecY, endRecX, endRecY, mPaint);
  73.                     //记录第几行,即第几周
  74.                     weekRow = row + 1;
  75.                 }
  76.                 //绘制事务圆形标志
  77.                 drawCircle(row,column,day + 1,canvas);
  78.                 if(dayString.equals(mSelDay+"")){
  79.                     mPaint.setColor(mSelectDayColor);
  80.                 }else if(dayString.equals(mCurrDay+"") && mCurrDay != mSelDay && mCurrMonth == mSelMonth){
  81.                     //正常月,选中其他日期,则今日为红色
  82.                     mPaint.setColor(mCurrentColor);
  83.                 }else{
  84.                     mPaint.setColor(mDayColor);
  85.                 }
  86.                 canvas.drawText(dayString, startX, startY, mPaint);
  87.                 if(tv_date != null){
  88.                     tv_date.setText(mSelYear + "年" + (mSelMonth + 1) + "月");
  89.                 }
  90.  
  91.                 if(tv_week != null){
  92.                     tv_week.setText("第" + weekRow  +"周");
  93.                 }
  94.             }
  95.         }
  96.  
  97.         private void drawCircle(int row,int column,int day,Canvas canvas){
  98.             if(daysHasThingList != null && daysHasThingList.size() >0){
  99.                 if(!daysHasThingList.contains(day))return;
  100.                 mPaint.setColor(mCircleColor);
  101.                 float circleX = (float) (mColumnSize * column + mColumnSize*0.8);
  102.                 float circley = (float) (mRowSize * row + mRowSize*0.2);
  103.                 canvas.drawCircle(circleX, circley, mCircleRadius, mPaint);
  104.             }
  105.         }
  106.         @Override
  107.         public boolean performClick() {
  108.             return super.performClick();
  109.         }
  110.  
  111.         private int downX = 0,downY = 0;
  112.         @Override
  113.         public boolean onTouchEvent(MotionEvent event) {
  114.             int eventCode=  event.getAction();
  115.             switch(eventCode){
  116.             case MotionEvent.ACTION_DOWN:
  117.                 downX = (int) event.getX();
  118.                 downY = (int) event.getY();
  119.                 break;
  120.             case MotionEvent.ACTION_MOVE:
  121.                 break;
  122.             case MotionEvent.ACTION_UP:
  123.                 int upX = (int) event.getX();
  124.                 int upY = (int) event.getY();
  125.                 if(Math.abs(upX-downX) < 10 && Math.abs(upY - downY) < 10){//点击事件
  126.                     performClick();
  127.                     doClickAction((upX + downX)/2,(upY + downY)/2);
  128.                 }
  129.                 break;
  130.             }
  131.             return true;
  132.         }
  133.  
  134.         /**
  135.          * 初始化列宽行高
  136.          */
  137.         private void initSize(){
  138.             mColumnSize = getWidth() / NUM_COLUMNS;
  139.             mRowSize = getHeight() / NUM_ROWS;
  140.         }
  141.  
  142.         /**
  143.          * 设置年月
  144.          * @param year
  145.          * @param month
  146.          */
  147.         private void setSelectYearMonth(int year,int month,int day){
  148.             mSelYear = year;
  149.             mSelMonth = month;
  150.             mSelDay = day;
  151.         }
  152.         /**
  153.          * 执行点击事件
  154.          * @param x
  155.          * @param y
  156.          */
  157.         private void doClickAction(int x,int y){
  158.             int row = y / mRowSize;
  159.             int column = x / mColumnSize;
  160.             setSelectYearMonth(mSelYear,mSelMonth,daysString[row][column]);
  161.             invalidate();
  162.             //执行activity发送过来的点击处理事件
  163.             if(dateClick != null){
  164.                 dateClick.onClickOnDate();
  165.             }
  166.         }
  167.  
  168.         /**
  169.          * 左点击,日历向后翻页
  170.          */
  171.         public void onLeftClick(){
  172.             int year = mSelYear;
  173.             int month = mSelMonth;
  174.             int day = mSelDay;
  175.             if(month == 0){//若果是1月份,则变成12月份
  176.                 year = mSelYear-1;
  177.                 month = 11;
  178.             }else if(DateUtils.getMonthDays(year, month) == day){
  179.                 //如果当前日期为该月最后一点,当向前推的时候,就需要改变选中的日期
  180.                 month = month-1;
  181.                 day = DateUtils.getMonthDays(year, month);
  182.             }else{
  183.                 month = month-1;
  184.             }
  185.             setSelectYearMonth(year,month,day);
  186.             invalidate();
  187.         }
  188.  
  189.         /**
  190.          * 右点击,日历向前翻页
  191.          */
  192.         public void onRightClick(){
  193.             int year = mSelYear;
  194.             int month = mSelMonth;
  195.             int day = mSelDay;
  196.             if(month == 11){//若果是12月份,则变成1月份
  197.                 year = mSelYear+1;
  198.                 month = 0;
  199.             }else if(DateUtils.getMonthDays(year, month) == day){
  200.                 //如果当前日期为该月最后一点,当向前推的时候,就需要改变选中的日期
  201.                 month = month + 1;
  202.                 day = DateUtils.getMonthDays(year, month);
  203.             }else{
  204.                 month = month + 1;
  205.             }
  206.             setSelectYearMonth(year,month,day);
  207.             invalidate();
  208.         }
  209.  
  210.         /**
  211.          * 获取选择的年份
  212.          * @return
  213.          */
  214.         public int getmSelYear() {
  215.             return mSelYear;
  216.         }
  217.         /**
  218.          * 获取选择的月份
  219.          * @return
  220.          */
  221.         public int getmSelMonth() {
  222.             return mSelMonth;
  223.         }
  224.         /**
  225.          * 获取选择的日期
  226.          * @param mSelDay
  227.          */
  228.         public int getmSelDay() {
  229.             return this.mSelDay;
  230.         }
  231.         /**
  232.          * 普通日期的字体颜色,默认黑色
  233.          * @param mDayColor
  234.          */
  235.         public void setmDayColor(int mDayColor) {
  236.             this.mDayColor = mDayColor;
  237.         }
  238.  
  239.         /**
  240.          * 选择日期的颜色,默认为白色
  241.          * @param mSelectDayColor
  242.          */
  243.         public void setmSelectDayColor(int mSelectDayColor) {
  244.             this.mSelectDayColor = mSelectDayColor;
  245.         }
  246.  
  247.         /**
  248.          * 选中日期的背景颜色,默认蓝色
  249.          * @param mSelectBGColor
  250.          */
  251.         public void setmSelectBGColor(int mSelectBGColor) {
  252.             this.mSelectBGColor = mSelectBGColor;
  253.         }
  254.         /**
  255.          * 当前日期不是选中的颜色,默认红色
  256.          * @param mCurrentColor
  257.          */
  258.         public void setmCurrentColor(int mCurrentColor) {
  259.             this.mCurrentColor = mCurrentColor;
  260.         }
  261.  
  262.         /**
  263.          * 日期的大小,默认18sp
  264.          * @param mDaySize
  265.          */
  266.         public void setmDaySize(int mDaySize) {
  267.             this.mDaySize = mDaySize;
  268.         }
  269.         /**
  270.          * 设置显示当前日期的控件
  271.          * @param tv_date
  272.          *      显示日期
  273.          * @param tv_week
  274.          *      显示周
  275.          */
  276.         public void setTextView(TextView tv_date,TextView tv_week){
  277.             this.tv_date = tv_date;
  278.             this.tv_week = tv_week;
  279.             invalidate();
  280.         }
  281.  
  282.         /**
  283.          * 设置事务天数
  284.          * @param daysHasThingList
  285.          */
  286.         public void setDaysHasThingList(List<Integer> daysHasThingList) {
  287.             this.daysHasThingList = daysHasThingList;
  288.         }
  289.  
  290.         /***
  291.          * 设置圆圈的半径,默认为6
  292.          * @param mCircleRadius
  293.          */
  294.         public void setmCircleRadius(int mCircleRadius) {
  295.             this.mCircleRadius = mCircleRadius;
  296.         }
  297.  
  298.         /**
  299.          * 设置圆圈的半径
  300.          * @param mCircleColor
  301.          */
  302.         public void setmCircleColor(int mCircleColor) {
  303.             this.mCircleColor = mCircleColor;
  304.         }
  305.  
  306.         /**
  307.          * 设置日期的点击回调事件
  308.          * @author shiwei.deng
  309.          *
  310.          */
  311.         public interface DateClick{
  312.             public void onClickOnDate();
  313.         }
  314.  
  315.         /**
  316.          * 设置日期点击事件
  317.          * @param dateClick
  318.          */
  319.         public void setDateClick(DateClick dateClick) {
  320.             this.dateClick = dateClick;
  321.         }
  322.  
  323.         /**
  324.          * 跳转至今天
  325.          */
  326.         public void setTodayToView(){
  327.             setSelectYearMonth(mCurrYear,mCurrMonth,mCurrDay);
  328.             invalidate();
  329.         }
  330.     }

(1)、首先我们还是定义了一些我们需要的成员变量,比如,字体的颜色、圆圈的颜色、选中的背景色、同样我们需要记录下我们正确的年月日、以及选中的年月日来进行区分,主要就这么多。
(2)、然后进行重写onMeasure方法,类似于WeekView,不做过多解释,差不多。
(3)、在onDraw方法中进行绘制,绘制的原理,我们根据Calendar获取当前月份的天数,以及第一天是礼拜几,只有计算出礼拜几,我们才知道我们的日历从哪列开始,这样我们就可以计算出每次绘制日期的位置:

  1. int column = (day+weekNumber - 1) % 7;
  2.     int row = (day+weekNumber - 1) / 7;
  3.     daysString[row][column]=day + 1;
  4.     int startX = (int) (mColumnSize * column + (mColumnSize - mPaint.measureText(dayString))/2);
  5.     int startY = (int) (mRowSize * row + mRowSize/2 - (mPaint.ascent() + mPaint.descent())/2);

一个礼拜有七天,我们根据日期号和起始计算出日期的对应行列,然后在乘以行列宽,就可以计算出每个日期号的其实位置。这样我们就可以通过drawText进行日期的绘制。我们有一个成员变量记录选中的日期号,然后进行绘制选中的背景色,如下代码:

  1. if(dayString.equals(mSelDay+"")){
  2.         //绘制背景色矩形
  3.         int startRecX = mColumnSize * column;
  4.         int startRecY = mRowSize * row;
  5.         int endRecX = startRecX + mColumnSize;
  6.         int endRecY = startRecY + mRowSize;
  7.         mPaint.setColor(mSelectBGColor);
  8.         canvas.drawRect(startRecX, startRecY, endRecX, endRecY, mPaint);
  9.         //记录第几行,即第几周
  10.         weekRow = row + 1;
  11.     }

(4)、我们还有一个需求,就是绘制事务标志,我们定义了List daysHasThingList的list对象,这个对象我们用来’装’事务的日期号。然后我们在onDraw方法中判断日期是否包含在这个list中,然后绘制对应的圆圈。

  1. private void drawCircle(int row,int column,int day,Canvas canvas){
  2.         if(daysHasThingList != null && daysHasThingList.size() >0){
  3.             if(!daysHasThingList.contains(day))return;
  4.             mPaint.setColor(mCircleColor);
  5.             float circleX = (float) (mColumnSize * column + mColumnSize*0.8);
  6.             float circley = (float) (mRowSize * row + mRowSize*0.2);
  7.             canvas.drawCircle(circleX, circley, mCircleRadius, mPaint);
  8.         }
  9.     }

(5)、至此,日期的绘制和事务都完成了,但是还没有点击事件进行切换日期的选择,这怎么办呢?所以我们需要重写View的onTouchEvent方法,然后判断点击事件,根据获取的X、Y值,计算出我们选择行列,然后我们在根据行列在daysString中获取我们选中的日期,设置选中日期,然后刷新视图。

  1. public boolean onTouchEvent(MotionEvent event) {
  2.         int eventCode=  event.getAction();
  3.         switch(eventCode){
  4.         case MotionEvent.ACTION_DOWN:
  5.             downX = (int) event.getX();
  6.             downY = (int) event.getY();
  7.             break;
  8.         case MotionEvent.ACTION_MOVE:
  9.             break;
  10.         case MotionEvent.ACTION_UP:
  11.             int upX = (int) event.getX();
  12.             int upY = (int) event.getY();
  13.             if(Math.abs(upX-downX) < 10 && Math.abs(upY - downY) < 10){//点击事件
  14.                 performClick();
  15.                 doClickAction((upX + downX)/2,(upY + downY)/2);
  16.             }
  17.             break;
  18.         }
  19.         return true;
  20.     }

(5)、有的需求是进行点击事情的处理,这时我们只需要写一个简单的回调,然后在activity中进行处理即可。

  1. private void doClickAction(int x,int y){
  2.         int row = y / mRowSize;
  3.         int column = x / mColumnSize;
  4.         setSelectYearMonth(mSelYear,mSelMonth,daysString[row][column]);
  5.         invalidate();
  6.         //执行activity发送过来的点击处理事件
  7.         if(dateClick != null){
  8.             dateClick.onClickOnDate();
  9.         }
  10.     }
  11.  
  12.     /**
  13.      * 设置日期的点击回调事件
  14.      * @author shiwei.deng
  15.      *
  16.      */
  17.     public interface DateClick{
  18.         public void onClickOnDate();
  19.     }
  20.  
  21.     /**
  22.      * 设置日期点击事件
  23.      * @param dateClick
  24.      */
  25.     public void setDateClick(DateClick dateClick) {
  26.         this.dateClick = dateClick;
  27.     }

(6)主要的处理已经完成,剩下的需要我们获取日期的显示以及显示第几周、点击【今】返回到今天,这些处理的逻辑就是设置选中的日期,然后刷新视图。代码就不贴了,上面的源码注释的挺详细的。

最后就是我们使用自定义View进行显示。如:

  1. <?xml version="1.0" encoding="utf-8"?>
  2.     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:layout_width="fill_parent"
  4.     android:layout_height="fill_parent"
  5.     android:layout_centerInParent="true"
  6.     android:orientation="vertical" >
  7.     <!-- 日历时间选择栏 -->
  8.     <RelativeLayout
  9.         android:layout_width="fill_parent"
  10.         android:layout_height="wrap_content"
  11.         android:gravity="center_vertical"
  12.         android:background="#ffffff"
  13.         android:layout_marginLeft="10dp"
  14.         android:layout_marginRight="10dp"
  15.         android:paddingTop="3dp">
  16.         <ImageView
  17.              android:id="@+id/iv_left"
  18.              android:layout_width="wrap_content"
  19.              android:layout_height="wrap_content"
  20.              android:layout_alignParentLeft="true"
  21.              android:contentDescription="@null"
  22.              android:background="@drawable/left_arrow" />
  23.         <ImageView
  24.              android:id="@+id/iv_right"
  25.              android:layout_width="wrap_content"
  26.              android:layout_height="wrap_content"
  27.              android:layout_alignParentRight="true"
  28.              android:contentDescription="@null"
  29.              android:background="@drawable/right_arrow" />
  30.         <LinearLayout
  31.              android:id="@+id/date_operator_ll"
  32.              android:layout_width="fill_parent"
  33.              android:layout_height="wrap_content"
  34.              android:layout_gravity="center_vertical"
  35.              android:gravity="center"
  36.              android:layout_centerInParent="true"
  37.              android:orientation="horizontal" >
  38.           <TextView
  39.               android:id="@+id/tv_today"
  40.               android:layout_width="25dp"
  41.               android:layout_height="25dp"
  42.               android:layout_marginRight="5dp"
  43.               android:text="今"
  44.               android:gravity="center"
  45.               android:background="#FFD700"
  46.               android:textColor="#ffffff"
  47.               android:textSize="17sp" />
  48.  
  49.           <TextView
  50.               android:id="@+id/date_text"
  51.               style="@style/myschedule_current_month_tv"
  52.               android:layout_width="wrap_content"
  53.               android:layout_height="wrap_content"
  54.               android:gravity="center_horizontal"
  55.               android:textColor="#93C73C"
  56.               android:textSize="20sp"
  57.               android:text="" />
  58.            <TextView
  59.               android:id="@+id/week_text"
  60.               style="@style/myschedule_current_month_tv"
  61.               android:layout_width="wrap_content"
  62.               android:layout_height="wrap_content"
  63.               android:gravity="center_horizontal"
  64.               android:layout_marginLeft="10dp"
  65.               android:textColor="#93C73C"
  66.               android:textSize="20sp"
  67.               android:text="" />
  68.          </LinearLayout>
  69.     </RelativeLayout>
  70.     <LinearLayout
  71.             android:layout_width="fill_parent"
  72.             android:layout_height="wrap_content"
  73.             android:layout_marginLeft="10dp"
  74.             android:layout_marginRight="10dp"
  75.             android:background="#ffffff"
  76.             android:orientation="vertical" >
  77.  
  78.             <com.dsw.datepicker.WeekDayView
  79.                 android:layout_width="match_parent"
  80.                 android:layout_height="30dp" />
  81.             <com.dsw.datepicker.MonthDateView
  82.                 android:id="@+id/monthDateView"
  83.                 android:layout_width="fill_parent"
  84.                 android:layout_height="200dp" />
  85.         </LinearLayout>
  86.     </LinearLayout>

这样我们在activity中就能使用了:

  1. public class MainActivity extends FragmentActivity {
  2.     private ImageView iv_left;
  3.     private ImageView iv_right;
  4.     private TextView tv_date;
  5.     private TextView tv_week;
  6.     private TextView tv_today;
  7.     private MonthDateView monthDateView;
  8.     @Override
  9.     protected void onCreate(Bundle savedInstanceState) {
  10.         super.onCreate(savedInstanceState);
  11.         List<Integer> list = new ArrayList<Integer>();
  12.         list.add(10);
  13.         list.add(12);
  14.         list.add(15);
  15.         list.add(16);
  16.         setContentView(R.layout.activity_date);
  17.         iv_left = (ImageView) findViewById(R.id.iv_left);
  18.         iv_right = (ImageView) findViewById(R.id.iv_right);
  19.         monthDateView = (MonthDateView) findViewById(R.id.monthDateView);
  20.         tv_date = (TextView) findViewById(R.id.date_text);
  21.         tv_week  =(TextView) findViewById(R.id.week_text);
  22.         tv_today = (TextView) findViewById(R.id.tv_today);
  23.         monthDateView.setTextView(tv_date,tv_week);
  24.         monthDateView.setDaysHasThingList(list);
  25.         monthDateView.setDateClick(new DateClick() {
  26.  
  27.             @Override
  28.             public void onClickOnDate() {
  29.                 Toast.makeText(getApplication(), "点击了:" + monthDateView.getmSelDay(), Toast.LENGTH_SHORT).show();
  30.             }
  31.         });
  32.         setOnlistener();
  33.     }
  34.  
  35.     private void setOnlistener(){
  36.         iv_left.setOnClickListener(new OnClickListener() {
  37.  
  38.             @Override
  39.             public void onClick(View v) {
  40.                 monthDateView.onLeftClick();
  41.             }
  42.         });
  43.  
  44.         iv_right.setOnClickListener(new OnClickListener() {
  45.  
  46.             @Override
  47.             public void onClick(View v) {
  48.                 monthDateView.onRightClick();
  49.             }
  50.         });
  51.  
  52.         tv_today.setOnClickListener(new OnClickListener() {
  53.  
  54.             @Override
  55.             public void onClick(View v) {
  56.                 monthDateView.setTodayToView();
  57.             }
  58.         });
  59.     }
  60.     }

至此,全部的内容已经完成,一个简单的自定义view的使用,在实际项目中使用颇多,当然这个例子还有很多完善的地方,比如在onTouchEvent中进行滑动的监视,通过滑动来进行日期的修改,这些有兴趣的同学可以试试。 

20150926222104453.gif

欢迎大家留言交流。

源码下载

作者:mr_dsw 欢迎转载,与人分享是进步的源泉!

转载请保留地址:http://blog.csdn.net/mr_dsw

0 0
原创粉丝点击