开源项目之Android Calender(日历组件)
Calender 是 Android 平台的一个日历显示组件,可以显示一整月历。项目适合初学者学习组件开发,项目如图:
该组件是在ImageView基础上扩展出来的,而Cell 是组件的格子,负责显示日期等。
public class Cell { private static final String TAG = "Cell"; protected Rect mBound = null; protected int mDayOfMonth = 1; // from 1 to 31 protected Paint mPaint = new Paint(Paint.SUBPIXEL_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG); int dx, dy; public Cell(int dayOfMon, Rect rect, float textSize, boolean bold) { mDayOfMonth = dayOfMon; mBound = rect; mPaint.setTextSize(textSize/* 26f */); mPaint.setColor(Color.BLACK); if (bold) mPaint.setFakeBoldText(true); dx = (int) mPaint.measureText(String.valueOf(mDayOfMonth)) / 2; dy = (int) (-mPaint.ascent() + mPaint.descent()) / 2; } public Cell(int dayOfMon, Rect rect, float textSize) { this(dayOfMon, rect, textSize, false); } protected void draw(Canvas canvas) { //自绘 canvas.drawText(String.valueOf(mDayOfMonth), mBound.centerX() - dx, mBound.centerY() + dy, mPaint); } public int getDayOfMonth() { //日期 return mDayOfMonth; } public boolean hitTest(int x, int y) { //是否单击 return mBound.contains(x, y); } public Rect getBound() { //获取范围 return mBound; } public String toString() { return String.valueOf(mDayOfMonth) + "(" + mBound.toString() + ")"; } }
关键是CalendarView,它负责布局 显示、操作等工作,源码如下:
public class CalendarView extends ImageView { private static int WEEK_TOP_MARGIN = 74; private static int WEEK_LEFT_MARGIN = 40; private static int CELL_WIDTH = 58; private static int CELL_HEIGH = 53; private static int CELL_MARGIN_TOP = 92; private static int CELL_MARGIN_LEFT = 39; private static float CELL_TEXT_SIZE; private static final String TAG = "CalendarView"; private Calendar mRightNow = null; private Drawable mWeekTitle = null; private Cell mToday = null; private Cell[][] mCells = new Cell[6][7]; private OnCellTouchListener mOnCellTouchListener = null; MonthDisplayHelper mHelper; Drawable mDecoration = null; public interface OnCellTouchListener { public void onTouch(Cell cell); } public CalendarView(Context context) { this(context, null); } public CalendarView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CalendarView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mDecoration = context.getResources().getDrawable( R.drawable.typeb_calendar_today); initCalendarView(); } private void initCalendarView() { mRightNow = Calendar.getInstance(); // prepare static vars Resources res = getResources(); WEEK_TOP_MARGIN = (int) res.getDimension(R.dimen.week_top_margin); WEEK_LEFT_MARGIN = (int) res.getDimension(R.dimen.week_left_margin); CELL_WIDTH = (int) res.getDimension(R.dimen.cell_width); CELL_HEIGH = (int) res.getDimension(R.dimen.cell_heigh); CELL_MARGIN_TOP = (int) res.getDimension(R.dimen.cell_margin_top); CELL_MARGIN_LEFT = (int) res.getDimension(R.dimen.cell_margin_left); CELL_TEXT_SIZE = res.getDimension(R.dimen.cell_text_size); // set background setImageResource(R.drawable.background); mWeekTitle = res.getDrawable(R.drawable.calendar_week); mHelper = new MonthDisplayHelper(mRightNow.get(Calendar.YEAR), mRightNow.get(Calendar.MONTH)); } private void initCells() { class _calendar { public int day; public boolean thisMonth; public _calendar(int d, boolean b) { day = d; thisMonth = b; } public _calendar(int d) { this(d, false); } } ; _calendar tmp[][] = new _calendar[6][7]; for (int i = 0; i < tmp.length; i++) { int n[] = mHelper.getDigitsForRow(i); for (int d = 0; d < n.length; d++) { if (mHelper.isWithinCurrentMonth(i, d)) tmp[i][d] = new _calendar(n[d], true); else tmp[i][d] = new _calendar(n[d]); } } Calendar today = Calendar.getInstance(); int thisDay = 0; mToday = null; if (mHelper.getYear() == today.get(Calendar.YEAR) && mHelper.getMonth() == today.get(Calendar.MONTH)) { thisDay = today.get(Calendar.DAY_OF_MONTH); } // build cells Rect Bound = new Rect(CELL_MARGIN_LEFT, CELL_MARGIN_TOP, CELL_WIDTH + CELL_MARGIN_LEFT, CELL_HEIGH + CELL_MARGIN_TOP); for (int week = 0; week < mCells.length; week++) { for (int day = 0; day < mCells[week].length; day++) { if (tmp[week][day].thisMonth) { if (day == 0 || day == 6) mCells[week][day] = new RedCell(tmp[week][day].day, new Rect(Bound), CELL_TEXT_SIZE); else mCells[week][day] = new Cell(tmp[week][day].day, new Rect(Bound), CELL_TEXT_SIZE); } else { mCells[week][day] = new GrayCell(tmp[week][day].day, new Rect(Bound), CELL_TEXT_SIZE); } Bound.offset(CELL_WIDTH, 0); // move to next column // get today if (tmp[week][day].day == thisDay && tmp[week][day].thisMonth) { mToday = mCells[week][day]; mDecoration.setBounds(mToday.getBound()); } } Bound.offset(0, CELL_HEIGH); // move to next row and first column Bound.left = CELL_MARGIN_LEFT; Bound.right = CELL_MARGIN_LEFT + CELL_WIDTH; } } @Override public void onLayout(boolean changed, int left, int top, int right, int bottom) { Rect re = getDrawable().getBounds(); WEEK_LEFT_MARGIN = CELL_MARGIN_LEFT = (right - left - re.width()) / 2; mWeekTitle.setBounds(WEEK_LEFT_MARGIN, WEEK_TOP_MARGIN, WEEK_LEFT_MARGIN + mWeekTitle.getMinimumWidth(), WEEK_TOP_MARGIN + mWeekTitle.getMinimumHeight()); initCells(); super.onLayout(changed, left, top, right, bottom); } public void setTimeInMillis(long milliseconds) { mRightNow.setTimeInMillis(milliseconds); initCells(); this.invalidate(); } public int getYear() { return mHelper.getYear(); } public int getMonth() { return mHelper.getMonth(); } public void nextMonth() { mHelper.nextMonth(); initCells(); invalidate(); } public void previousMonth() { mHelper.previousMonth(); initCells(); invalidate(); } public boolean firstDay(int day) { return day == 1; } public boolean lastDay(int day) { return mHelper.getNumberOfDaysInMonth() == day; } public void goToday() { Calendar cal = Calendar.getInstance(); mHelper = new MonthDisplayHelper(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)); initCells(); invalidate(); } public Calendar getDate() { return mRightNow; } @Override public boolean onTouchEvent(MotionEvent event) { if (mOnCellTouchListener != null) { for (Cell[] week : mCells) { for (Cell day : week) { if (day.hitTest((int) event.getX(), (int) event.getY())) { mOnCellTouchListener.onTouch(day); } } } } return super.onTouchEvent(event); } public void setOnCellTouchListener(OnCellTouchListener p) { mOnCellTouchListener = p; } @Override protected void onDraw(Canvas canvas) { // draw background super.onDraw(canvas); mWeekTitle.draw(canvas); // draw cells for (Cell[] week : mCells) { for (Cell day : week) { day.draw(canvas); } } // draw today if (mDecoration != null && mToday != null) { mDecoration.draw(canvas); } } public class GrayCell extends Cell { public GrayCell(int dayOfMon, Rect rect, float s) { super(dayOfMon, rect, s); mPaint.setColor(Color.LTGRAY); } } private class RedCell extends Cell { public RedCell(int dayOfMon, Rect rect, float s) { super(dayOfMon, rect, s); mPaint.setColor(0xdddd0000); } } }
是不是非常简单?