Android UI-自定义日历控件
本篇博客笔者给大家分享一个日历控件,这里有个需求:要求显示当前月的日期,左右可以切换月份来查看日期。
我们想一想会如何去实现这样的一个控件,有开源的,但可能不太满足我们的特定的需求,这里笔者自定义了一个,读者可以根据自己的需求来修改代码。下面来说一下实现的思路:
首先我们要显示当前月份,自然我们要计算出当前的日期,并且把每一天对应到具体的星期,
我们会有以下效果:
我们先想一下这样的效果用什么控件可以实现?很自然可以想到用网格视图GridView,但这里笔者使用的不是GridView, 因为使用GridView可能无法实现那个红色的圈圈,所以笔者决定自定义View,通过绘制来达到这样的效果。
这里我们定于一个日历卡,每一个月代表一个日历卡,我们通过计算每个月的日期,然后根据计算出来的位置绘制我们的数字。
我们知道,一个星期有七天,分别为星期日、星期一、星期二、星期三、星期四、星期五、星期六,这里有7列,一个月至少有28天,最多31天,所以至少应该有6行。组成6*7的方格图。
直接上代码:
[java] view
plaincopy
package com.xiaowu.calendar;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;  
/**
- 自定义日历卡
- @author wuwenjie
- 
*/ 
 public class CalendarCard extends View {private static final int TOTAL_COL = 7; // 7列 
 private static final int TOTAL_ROW = 6; // 6行private Paint mCirclePaint; // 绘制圆形的画笔 
 private Paint mTextPaint; // 绘制文本的画笔
 private int mViewWidth; // 视图的宽度
 private int mViewHeight; // 视图的高度
 private int mCellSpace; // 单元格间距
 private Row rows[] = new Row[TOTAL_ROW]; // 行数组,每个元素代表一行
 private static CustomDate mShowDate; // 自定义的日期,包括year,month,day
 private OnCellClickListener mCellClickListener; // 单元格点击回调事件
 private int touchSlop; //
 private boolean callBackCellSpace;private Cell mClickCell; 
 private float mDownX;
 private float mDownY;/** - 单元格点击的回调接口
- @author wuwenjie
- 
*/ 
 public interface OnCellClickListener {
 void clickDate(CustomDate date); // 回调点击的日期void changeDate(CustomDate date); // 回调滑动ViewPager改变的日期 
 }
 public CalendarCard(Context context, AttributeSet attrs, int defStyleAttr) { 
 super(context, attrs, defStyleAttr);
 init(context);
 }public CalendarCard(Context context, AttributeSet attrs) { 
 super(context, attrs);
 init(context);
 }public CalendarCard(Context context) { 
 super(context);
 init(context);
 }public CalendarCard(Context context, OnCellClickListener listener) { 
 super(context);
 this.mCellClickListener = listener;
 init(context);
 }private void init(Context context) { 
 mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
 mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
 mCirclePaint.setStyle(Paint.Style.FILL);
 mCirclePaint.setColor(Color.parseColor("#F24949")); // 红色圆形
 touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();initDate();} private void initDate() { 
 mShowDate = new CustomDate();
 fillDate();//
 }private void fillDate() { 
 int monthDay = DateUtil.getCurrentMonthDay(); // 今天
 int lastMonthDays = DateUtil.getMonthDays(mShowDate.year,
 mShowDate.month - 1); // 上个月的天数
 int currentMonthDays = DateUtil.getMonthDays(mShowDate.year,
 mShowDate.month); // 当前月的天数
 int firstDayWeek = DateUtil.getWeekDayFromDate(mShowDate.year,
 mShowDate.month);
 boolean isCurrentMonth = false;
 if (DateUtil.isCurrentMonth(mShowDate)) {
 isCurrentMonth = true;
 }
 int day = 0;
 for (int j = 0; j < TOTAL_ROW; j++) {
 rows[j] = new Row(j);
 for (int i = 0; i < TOTAL_COL; i++) {
 int position = i + j * TOTAL_COL; // 单元格位置
 // 这个月的
 if (position >= firstDayWeek
 && position < firstDayWeek + currentMonthDays) {
 day++;
 rows[j].cells[i] = new Cell(CustomDate.modifiDayForObject(
 mShowDate, day), State.CURRENT_MONTH_DAY, i, j);
 // 今天
 if (isCurrentMonth && day == monthDay ) {
 CustomDate date = CustomDate.modifiDayForObject(mShowDate, day);
 rows[j].cells[i] = new Cell(date, State.TODAY, i, j);
 }if (isCurrentMonth && day > monthDay) { // 如果比这个月的今天要大,表示还没到 rows[j].cells[i] = new Cell( CustomDate.modifiDayForObject(mShowDate, day), State.UNREACH_DAY, i, j); } // 过去一个月 } else if (position < firstDayWeek) { rows[j].cells[i] = new Cell(new CustomDate(mShowDate.year, mShowDate.month - 1, lastMonthDays - (firstDayWeek - position - 1)), State.PAST_MONTH_DAY, i, j); // 下个月 } else if (position >= firstDayWeek + currentMonthDays) { rows[j].cells[i] = new Cell((new CustomDate(mShowDate.year, mShowDate.month + 1, position - firstDayWeek - currentMonthDays + 1)), State.NEXT_MONTH_DAY, i, j); } } } mCellClickListener.changeDate(mShowDate);} @Override 
 protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 for (int i = 0; i < TOTAL_ROW; i++) {
 if (rows[i] != null) {
 rows[i].drawCells(canvas);
 }
 }
 }@Override 
 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
 super.onSizeChanged(w, h, oldw, oldh);
 mViewWidth = w;
 mViewHeight = h;
 mCellSpace = Math.min(mViewHeight / TOTAL_ROW, mViewWidth / TOTAL_COL);
 if (!callBackCellSpace) {
 callBackCellSpace = true;
 }
 mTextPaint.setTextSize(mCellSpace / 3);
 }@Override 
 public boolean onTouchEvent(MotionEvent event) {
 switch (event.getAction()) {
 case MotionEvent.ACTION_DOWN:
 mDownX = event.getX();
 mDownY = event.getY();
 break;
 case MotionEvent.ACTION_UP:
 float disX = event.getX() - mDownX;
 float disY = event.getY() - mDownY;
 if (Math.abs(disX) < touchSlop && Math.abs(disY) < touchSlop) {
 int col = (int) (mDownX / mCellSpace);
 int row = (int) (mDownY / mCellSpace);
 measureClickCell(col, row);
 }
 break;
 default:
 break;
 }return true;} /** - 计算点击的单元格
- @param col
- 
@param row 
 */
 private void measureClickCell(int col, int row) {
 if (col >= TOTAL_COL || row >= TOTAL_ROW)
 return;
 if (mClickCell != null) {
 rows[mClickCell.j].cells[mClickCell.i] = mClickCell;
 }
 if (rows[row] != null) {
 mClickCell = new Cell(rows[row].cells[col].date,
 rows[row].cells[col].state, rows[row].cells[col].i,
 rows[row].cells[col].j);CustomDate date = rows[row].cells[col].date; date.week = col; mCellClickListener.clickDate(date); // 刷新界面 update();} 
 }
 /** - 组元素
- @author wuwenjie
- 
*/ 
 class Row {
 public int j;Row(int j) { 
 this.j = j;
 }public Cell[] cells = new Cell[TOTAL_COL]; // 绘制单元格 
 public void drawCells(Canvas canvas) {
 for (int i = 0; i < cells.length; i++) {
 if (cells[i] != null) {
 cells[i].drawSelf(canvas);
 }
 }
 }
 } /** - 单元格元素
- @author wuwenjie
- 
*/ 
 class Cell {
 public CustomDate date;
 public State state;
 public int i;
 public int j;public Cell(CustomDate date, State state, int i, int j) { 
 super();
 this.date = date;
 this.state = state;
 this.i = i;
 this.j = j;
 }public void drawSelf(Canvas canvas) { 
 switch (state) {
 case TODAY: // 今天
 mTextPaint.setColor(Color.parseColor("#fffffe"));
 canvas.drawCircle((float) (mCellSpace (i + 0.5)),
 (float) ((j + 0.5) mCellSpace), mCellSpace / 3,
 mCirclePaint);
 break;
 case CURRENT_MONTH_DAY: // 当前月日期
 mTextPaint.setColor(Color.BLACK);
 break;
 case PAST_MONTH_DAY: // 过去一个月
 case NEXT_MONTH_DAY: // 下一个月
 mTextPaint.setColor(Color.parseColor("#fffffe"));
 break;
 case UNREACH_DAY: // 还未到的天
 mTextPaint.setColor(Color.GRAY);
 break;
 default:
 break;
 }
 // 绘制文字
 String content = date.day + "";
 canvas.drawText(content,
 (float) ((i + 0.5) * mCellSpace - mTextPaint
 .measureText(content) / 2), (float) ((j + 0.7)- mCellSpace - mTextPaint
 .measureText(content, 0, 1) / 2), mTextPaint);
 }
 }
 
- mCellSpace - mTextPaint
 /** 
- @author wuwenjie 单元格的状态 当前月日期,过去的月的日期,下个月的日期
 */
 enum State {
 TODAY,CURRENT_MONTH_DAY, PAST_MONTH_DAY, NEXT_MONTH_DAY, UNREACH_DAY;
 }
 // 从左往右划,上一个月 
 public void leftSlide() {
 if (mShowDate.month == 1) {
 mShowDate.month = 12;
 mShowDate.year -= 1;
 } else {
 mShowDate.month -= 1;
 }
 update();
 }// 从右往左划,下一个月 
 public void rightSlide() {
 if (mShowDate.month == 12) {
 mShowDate.month = 1;
 mShowDate.year += 1;
 } else {
 mShowDate.month += 1;
 }
 update();
 }public void update() { 
 fillDate();
 invalidate();
 }
}
/CustomCalendarView/src/com/xiaowu/calendar/DateUtil.java
[java] view
plaincopy
package com.xiaowu.calendar;
import android.annotation.SuppressLint;
import android.util.Log;  
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;  
public class DateUtil {
public static String[] weekName = { "周日", "周一", "周二", "周三", "周四", "周五","周六" };  
public static int getMonthDays(int year, int month) {  
    if (month > 12) {  
        month = 1;  
        year += 1;  
    } else if (month < 1) {  
        month = 12;  
        year -= 1;  
    }  
    int[] arr = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };  
    int days = 0;  
    if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {  
        arr[1] = 29; // 闰年2月29天  
    }  
    try {  
        days = arr[month - 1];  
    } catch (Exception e) {  
        e.getStackTrace();  
    }  
    return days;  
}  
public static int getYear() {  
    return Calendar.getInstance().get(Calendar.YEAR);  
}  
public static int getMonth() {  
    return Calendar.getInstance().get(Calendar.MONTH) + 1;  
}  
public static int getCurrentMonthDay() {  
    return Calendar.getInstance().get(Calendar.DAY_OF_MONTH);  
}  
public static int getWeekDay() {  
    return Calendar.getInstance().get(Calendar.DAY_OF_WEEK);  
}  
public static int getHour() {  
    return Calendar.getInstance().get(Calendar.HOUR_OF_DAY);  
}  
public static int getMinute() {  
    return Calendar.getInstance().get(Calendar.MINUTE);  
}  
public static CustomDate getNextSunday() {  
    Calendar c = Calendar.getInstance();  
    c.add(Calendar.DATE, 7 - getWeekDay()+1);  
    CustomDate date = new CustomDate(c.get(Calendar.YEAR),  
            c.get(Calendar.MONTH)+1, c.get(Calendar.DAY_OF_MONTH));  
    return date;  
}  
public static int[] getWeekSunday(int year, int month, int day, int pervious) {  
    int[] time = new int[3];  
    Calendar c = Calendar.getInstance();  
    c.set(Calendar.YEAR, year);  
    c.set(Calendar.MONTH, month);  
    c.set(Calendar.DAY_OF_MONTH, day);  
    c.add(Calendar.DAY_OF_MONTH, pervious);  
    time[0] = c.get(Calendar.YEAR);  
    time[1] = c.get(Calendar.MONTH )+1;  
    time[2] = c.get(Calendar.DAY_OF_MONTH);  
    return time;  
}  
public static int getWeekDayFromDate(int year, int month) {  
    Calendar cal = Calendar.getInstance();  
    cal.setTime(getDateFromString(year, month));  
    int week_index = cal.get(Calendar.DAY_OF_WEEK) - 1;  
    if (week_index < 0) {  
        week_index = 0;  
    }  
    return week_index;  
}  
@SuppressLint("SimpleDateFormat")  
public static Date getDateFromString(int year, int month) {  
    String dateString = year + "-" + (month > 9 ? month : ("0" + month))  
            + "-01";  
    Date date = null;  
    try {  
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");  
        date = sdf.parse(dateString);  
    } catch (ParseException e) {  
        System.out.println(e.getMessage());  
    }  
    return date;  
}  
public static boolean isToday(CustomDate date){  
    return(date.year == DateUtil.getYear() &&  
            date.month == DateUtil.getMonth()   
            && date.day == DateUtil.getCurrentMonthDay());  
}  
public static boolean isCurrentMonth(CustomDate date){  
    return(date.year == DateUtil.getYear() &&  
            date.month == DateUtil.getMonth());  
}  }
/CustomCalendarView/src/com/xiaowu/calendar/CustomDate.java、
[java] view
plaincopy
package com.xiaowu.calendar;
import java.io.Serializable;
public class CustomDate implements Serializable{  
private static final long serialVersionUID = 1L;  
public int year;  
public int month;  
public int day;  
public int week;  
public CustomDate(int year,int month,int day){  
    if(month > 12){  
        month = 1;  
        year++;  
    }else if(month <1){  
        month = 12;  
        year--;  
    }  
    this.year = year;  
    this.month = month;  
    this.day = day;  
}  
public CustomDate(){  
    this.year = DateUtil.getYear();  
    this.month = DateUtil.getMonth();  
    this.day = DateUtil.getCurrentMonthDay();  
}  
public static CustomDate modifiDayForObject(CustomDate date,int day){  
    CustomDate modifiDate = new CustomDate(date.year,date.month,day);  
    return modifiDate;  
}  
@Override  
public String toString() {  
    return year+"-"+month+"-"+day;  
}  
public int getYear() {  
    return year;  
}  
public void setYear(int year) {  
    this.year = year;  
}  
public int getMonth() {  
    return month;  
}  
public void setMonth(int month) {  
    this.month = month;  
}  
public int getDay() {  
    return day;  
}  
public void setDay(int day) {  
    this.day = day;  
}  
public int getWeek() {  
    return week;  
}  
public void setWeek(int week) {  
    this.week = week;  
}  }
所有绘制的操作在onDraw方面里实现,我这里定于了一个组对象Row、单元格元素Cell,通过Row[row].cell[col]来确定一个单元格,每次调用invalidate重绘视图。
接着,我们有一个需求需要左右切换,我们选用最熟悉的ViewPager,但这里有个问题,怎么实现无限循环呢,
这里我们传入一个日历卡数组,让ViewPager循环复用这几个日历卡,避免消耗内存。
/CustomCalendarView/src/com/xiaowu/calendar/CalendarViewAdapter.java
[java] view
plaincopy
package com.xiaowu.calendar;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;  
public class CalendarViewAdapter<V extends View> extends PagerAdapter {
public static final String TAG = "CalendarViewAdapter";
private V[] views;  
public CalendarViewAdapter(V[] views) {  
    super();  
    this.views = views;  
}  
@Override  
public Object instantiateItem(ViewGroup container, int position) {  
    if (((ViewPager) container).getChildCount() == views.length) {  
        ((ViewPager) container).removeView(views[position % views.length]);  
    }  
    ((ViewPager) container).addView(views[position % views.length], 0);  
    return views[position % views.length];  
}  
@Override  
public int getCount() {  
    return Integer.MAX_VALUE;  
}  
@Override  
public boolean isViewFromObject(View view, Object object) {  
    return view == ((View) object);  
}  
@Override  
public void destroyItem(ViewGroup container, int position, Object object) {  
    ((ViewPager) container).removeView((View) container);  
}  
public V[] getAllItems() {  
    return views;  
}  }
布局文件:
[html] view
plaincopy
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical" >  
<RelativeLayout  
    android:layout_width="match_parent"  
    android:layout_height="50dp"  
    android:background="#f6f1ea"  
     >  
    <ImageButton  
        android:id="@+id/btnPreMonth"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_centerVertical="true"  
        android:layout_marginRight="33dip"  
        android:layout_toLeftOf="@+id/tvCurrentMonth"  
        android:background="@drawable/ic_before" />  
    <ImageButton  
        android:id="@+id/btnNextMonth"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_centerVertical="true"  
        android:layout_marginLeft="33dip"  
        android:layout_toRightOf="@+id/tvCurrentMonth"  
        android:background="@drawable/ic_next" />  
    <TextView  
        android:id="@+id/tvCurrentMonth"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_centerInParent="true"  
        android:layout_centerVertical="true"  
        android:text="11月"  
        android:textColor="#323232"  
        android:textSize="22sp" />  
    <ImageButton  
        android:id="@+id/btnClose"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_alignParentRight="true"  
        android:layout_centerVertical="true"  
        android:layout_marginRight="15dp"  
        android:background="@drawable/ic_close" />  
</RelativeLayout>  
<LinearLayout  
    android:layout_width="match_parent"  
    android:layout_height="wrap_content"  
    android:layout_marginTop="15dp"  
    android:orientation="vertical"  
     >  
    <TableLayout  
        android:layout_width="match_parent"  
        android:layout_height="20dip"  
        android:layout_marginBottom="2dip"  
        android:layout_marginTop="2dip" >  
        <TableRow>  
            <TextView  
                style="@style/dateStyle"  
                android:text="@string/sunday"  
                android:textColor="@color/canlendar_text_color" />  
            <TextView  
                style="@style/dateStyle"  
                android:text="@string/monday"  
                android:textColor="@color/canlendar_text_color" />  
            <TextView  
                style="@style/dateStyle"  
                android:text="@string/thesday"  
                android:textColor="@color/canlendar_text_color" />  
            <TextView  
                style="@style/dateStyle"  
                android:text="@string/wednesday"  
                android:textColor="@color/canlendar_text_color" />  
            <TextView  
                style="@style/dateStyle"  
                android:text="@string/thursday"  
                android:textColor="@color/canlendar_text_color" />  
            <TextView  
                style="@style/dateStyle"  
                android:text="@string/friday"  
                android:textColor="@color/canlendar_text_color" />  
            <TextView  
                style="@style/dateStyle"  
                android:text="@string/saturday"  
                android:textColor="@color/canlendar_text_color" />  
        </TableRow>  
    </TableLayout>  
</LinearLayout>  
<LinearLayout  
    android:layout_width="match_parent"  
    android:layout_height="0dp"  
    android:orientation="vertical"   
    android:layout_weight="1"  
    android:layout_marginTop="15dp">  
    <android.support.v4.view.ViewPager  
        android:id="@+id/vp_calendar"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:layout_gravity="center"  
        android:background="@color/white" >  
    </android.support.v4.view.ViewPager>  
</LinearLayout>  </LinearLayout>
/CustomCalendarView/src/com/xiaowu/calendar/MainActivity.java
[java] view
plaincopy
package com.xiaowu.calendar;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.ImageButton;
import android.widget.TextView;  
import com.xiaowu.calendar.CalendarCard.OnCellClickListener;
public class MainActivity extends Activity implements OnClickListener, OnCellClickListener{
private ViewPager mViewPager;
private int mCurrentIndex = 498;
private CalendarCard[] mShowViews;
private CalendarViewAdapter<CalendarCard> adapter;
private SildeDirection mDirection = SildeDirection.NO_SILDE;
enum SildeDirection {
RIGHT, LEFT, NO_SILDE;
}  
private ImageButton preImgBtn, nextImgBtn;  
private TextView monthText;  
private ImageButton closeImgBtn;  
@Override  
protected void onCreate(Bundle savedInstanceState) {  
    super.onCreate(savedInstanceState);  
    requestWindowFeature(Window.FEATURE_NO_TITLE);  
    setContentView(R.layout.activity_main);  
    mViewPager = (ViewPager) this.findViewById(R.id.vp_calendar);  
    preImgBtn = (ImageButton) this.findViewById(R.id.btnPreMonth);  
    nextImgBtn = (ImageButton) this.findViewById(R.id.btnNextMonth);  
    monthText = (TextView) this.findViewById(R.id.tvCurrentMonth);  
    closeImgBtn = (ImageButton) this.findViewById(R.id.btnClose);  
    preImgBtn.setOnClickListener(this);  
    nextImgBtn.setOnClickListener(this);  
    closeImgBtn.setOnClickListener(this);  
    CalendarCard[] views = new CalendarCard[3];  
    for (int i = 0; i < 3; i++) {  
        views[i] = new CalendarCard(this, this);  
    }  
    adapter = new CalendarViewAdapter<>(views);  
    setViewPager();  
}  
private void setViewPager() {  
    mViewPager.setAdapter(adapter);  
    mViewPager.setCurrentItem(498);  
    mViewPager.setOnPageChangeListener(new OnPageChangeListener() {  
        @Override  
        public void onPageSelected(int position) {  
            measureDirection(position);  
            updateCalendarView(position);                 
        }  
        @Override  
        public void onPageScrolled(int arg0, float arg1, int arg2) {  
        }  
        @Override  
        public void onPageScrollStateChanged(int arg0) {  
        }  
    });  
}  
@Override  
public void onClick(View v) {  
    switch (v.getId()) {  
    case R.id.btnPreMonth:  
        mViewPager.setCurrentItem(mViewPager.getCurrentItem() - 1);  
        break;  
    case R.id.btnNextMonth:  
        mViewPager.setCurrentItem(mViewPager.getCurrentItem() + 1);  
        break;  
    case R.id.btnClose:  
        finish();  
        break;  
    default:  
        break;  
    }  
}  
@Override  
public void clickDate(CustomDate date) {  
}  
@Override  
public void changeDate(CustomDate date) {  
    monthText.setText(date.month + "月");  
}  
/** 
 * 计算方向 
 *  
 * @param arg0 
 */  
private void measureDirection(int arg0) {  
    if (arg0 > mCurrentIndex) {  
        mDirection = SildeDirection.RIGHT;  
    } else if (arg0 < mCurrentIndex) {  
        mDirection = SildeDirection.LEFT;  
    }  
    mCurrentIndex = arg0;  
}  
// 更新日历视图  
private void updateCalendarView(int arg0) {  
    mShowViews = adapter.getAllItems();  
    if (mDirection == SildeDirection.RIGHT) {  
        mShowViews[arg0 % mShowViews.length].rightSlide();  
    } else if (mDirection == SildeDirection.LEFT) {  
        mShowViews[arg0 % mShowViews.length].leftSlide();  
    }  
    mDirection = SildeDirection.NO_SILDE;  
}  }
用到的资源:
/CustomCalendarView/res/values/color.xml
[html] view
plaincopy
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="white">#ffffff</color>
<color name="canlendar_text_color">#323232</color>
</resources>  
/CustomCalendarView/res/values/strings.xml
[html] view
plaincopy
<?xml version="1.0" encoding="utf-8"?>
<resources>  
<string name="app_name">CustomCalendarView</string>  
<string name="hello_world">Hello world!</string>  
<string name="action_settings">Settings</string>  
<string name="sunday">日</string>  
<string name="monday">一</string>  
<string name="thesday">二</string>  
<string name="wednesday">三</string>  
<string name="thursday">四</string>  
<string name="friday">五</string>  
<string name="saturday">六</string>  </resources>
/CustomCalendarView/res/values/styles.xml
[html] view
plaincopy
<resources>
<!--  
    Base application theme, dependent on API level. This theme is replaced  
    by AppBaseTheme from res/values-vXX/styles.xml on newer devices.  
-->  
<style name="AppBaseTheme" parent="android:Theme.Light">  
    <!--  
        Theme customizations available in newer API levels can go in  
        res/values-vXX/styles.xml, while customizations related to  
        backward-compatibility can go here.  
    -->  
</style>  
<!-- Application theme. -->  
<style name="AppTheme" parent="AppBaseTheme">  
    <!-- All customizations that are NOT specific to a particular API-level can go here. -->  
</style>  
<style name="dateStyle">  
    <item name="android:layout_width">fill_parent</item>  
    <item name="android:layout_height">fill_parent</item>  
    <item name="android:layout_weight">1</item>  
    <item name="android:gravity">center</item>  
    <item name="android:textSize">16sp</item>  
</style>  </resources>
源码下载:http://download.csdn.net/detail/wwj_748/8312233
转自:http://blog.csdn.net/wwj_748/article/details/42244865