自定義可以顯示考勤狀態的日曆控制元件
阿新 • • 發佈:2019-02-05
最近專案中要做一個可顯示考勤狀態的日曆,於是就整理了一下寫了一個demo。先看一下專案中的效果圖:
圖1:
圖2:
下面來看一下demo的效果圖:
不會做動圖,只能發圖片了。。。
初始化會顯示今天所在月的考勤,並選中今天(圖3):
點選按鈕“上一個月”或者點選日曆上一月的單元格(上圖中的3月26日-31日),都會重新整理到上一個月(圖4):
點選按鈕“下一個月”或者點選日曆下一月的單元格,都會重新整理到下一個月(圖5):
點選單元格,顯示選中的日期(圖6):
下面來看下demo的程式碼:
主介面MainActivity:
/**
* Created by ysc on 2017/4/1.
*/
public class MainActivity extends Activity implements MyCalendarView.OnItemClickListener {
private TextView tv;
private MyCalendarView mMyCalendarView;//自定義的日曆控制元件
//ClockStates:考勤狀態
private List<ClockStates> lists;
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = ((TextView) findViewById(R.id.tv));
mMyCalendarView = ((MyCalendarView) findViewById(R.id.mcv));
//點選日曆單元格的回撥
mMyCalendarView.setOnItemClickListener(this);
//使用造的資料看看效果(而我們在專案開發中是聯網獲取的當月考勤資料)
initData();
}
//點選上一個月
public void last(View view) {
mMyCalendarView.clickLeftMonth();
tv.setText(mMyCalendarView.getYearAndmonth());
//TODO 聯網載入上個月的考勤得到一個新lists設定給日曆
lists.clear();//這裡因為沒有聯網資料,那麼我們清空掉之前造的資料,看看有資料到沒資料切換的效果
mMyCalendarView.setClockStates(lists);
}
//點選下一個月
public void next(View view) {
mMyCalendarView.clickRightMonth();
tv.setText(mMyCalendarView.getYearAndmonth());
//TODO 聯網載入上個月的考勤得到一個新lists設定給日曆
lists.clear();//這裡因為沒有聯網資料,那麼我們清空掉之前造的資料,看一下有資料到沒資料切換的效果
mMyCalendarView.setClockStates(lists);
}
@Override
public void OnItemClick(Date date) {
String selectDate = getStringByFormat(date, "yyyy-MM-dd");//2017-03-31
int selectYear = Integer.parseInt(selectDate.split("-")[0]);
int selectMonth = Integer.parseInt(selectDate.split("-")[1]);
Toast.makeText(MainActivity.this, selectDate, Toast.LENGTH_SHORT).show();
if (mMyCalendarView.isLastMonth(selectYear, selectMonth)) {//點選的那一天是當天顯示月的上一個月
mMyCalendarView.clickLeftMonth();
tv.setText(mMyCalendarView.getYearAndmonth());
//TODO 實際開發中我是聯網載入上個月的考勤,得到lists,再設定給日曆
lists.clear();//這裡因為沒有聯網資料,那麼我們清空掉之前造的資料,看看效果
mMyCalendarView.setClockStates(lists);
} else if (mMyCalendarView.isNextMonth(selectYear, selectMonth)) {//是下一個月
mMyCalendarView.clickRightMonth();
tv.setText(mMyCalendarView.getYearAndmonth());
//TODO 實際開發中我是聯網載入下個月的考勤,得到lists,再設定給日曆
lists.clear();//這裡因為沒有聯網資料,那麼我們清空掉之前造的資料,看看效果
mMyCalendarView.setClockStates(lists);
}
}
/**
* 描述:Date型別轉化為String型別.
*
* @param date the date
* @param format the format
* @return String String型別日期時間
*/
public String getStringByFormat(Date date, String format) {
SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat(format);
String strDate = null;
try {
strDate = mSimpleDateFormat.format(date);
} catch (Exception e) {
e.printStackTrace();
}
return strDate;
}
//造點考勤資料
private void initData(){
lists = new ArrayList<>();
lists.add(new ClockStates("2017-04-01","1"));
lists.add(new ClockStates("2017-04-02","2"));
lists.add(new ClockStates("2017-04-03","3"));
lists.add(new ClockStates("2017-04-04","4"));
lists.add(new ClockStates("2017-04-05","1"));
lists.add(new ClockStates("2017-04-06","2"));
lists.add(new ClockStates("2017-04-07","3"));
lists.add(new ClockStates("2017-04-08","4"));
lists.add(new ClockStates("2017-04-09","1"));
lists.add(new ClockStates("2017-04-10","2"));
lists.add(new ClockStates("2017-04-11","3"));
lists.add(new ClockStates("2017-04-12","4"));
lists.add(new ClockStates("2017-04-13","1"));
lists.add(new ClockStates("2017-04-14","2"));
lists.add(new ClockStates("2017-04-15","4"));
lists.add(new ClockStates("2017-04-16","3"));
lists.add(new ClockStates("2017-04-17","1"));
lists.add(new ClockStates("2017-04-18","2"));
lists.add(new ClockStates("2017-04-19","3"));
lists.add(new ClockStates("2017-04-20","4"));
lists.add(new ClockStates("2017-04-21","2"));
lists.add(new ClockStates("2017-04-22","1"));
lists.add(new ClockStates("2017-04-23","1"));
lists.add(new ClockStates("2017-04-24","1"));
lists.add(new ClockStates("2017-04-25","1"));
lists.add(new ClockStates("2017-04-26","1"));
lists.add(new ClockStates("2017-04-27","1"));
lists.add(new ClockStates("2017-04-28","1"));
lists.add(new ClockStates("2017-04-29","1"));
lists.add(new ClockStates("2017-04-30","1"));
mMyCalendarView.setClockStates(lists);
}
}
佈局activity_main :
<?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:orientation="vertical"
tools:context="com.yuan.calendardemo.MainActivity">
<com.yuan.calendardemo.Widget.MyCalendarView
android:id="@+id/mcv"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<LinearLayout
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="wrap_content">
<Button
android:onClick="last"
android:text="上一個月"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="40dp" />
<TextView
android:id="@+id/tv"
android:layout_width="0dp"
android:text="2017年4月"
android:gravity="center"
android:layout_weight="1"
android:layout_height="40dp" />
<Button
android:onClick="next"
android:text="下一個月"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="40dp" />
</LinearLayout>
</LinearLayout>
考勤狀態的bean類:
/**
* Created by ysc on 2017/4/1.
*/
public class ClockStates {
private String date;// 日期 年-月-日
private String dateType;// 1表示正常,2.異常,3.休息,4.曠工
public ClockStates(String date, String dateType) {
this.date = date;
this.dateType = dateType;
}
public ClockStates() {
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getDateType() {
return dateType;
}
public void setDateType(String dateType) {
this.dateType = dateType;
}
}
然後重點就是自定義的日曆控制元件了MyCalendarView:
/**
* Created by ysc on 2017/4/1.
*/
public class MyCalendarView extends View implements View.OnTouchListener {
private Date selectedStartDate; //選中開始的月
private Date selectedEndDate; //選中結束的月
private Date curDate; // 當前日曆顯示的月
private Date today; // 今天的日期文字顯示紅色
private Date downDate; // 手指按下狀態時臨時日期
private Date showFirstDate, showLastDate; // 日曆顯示的第一個日期和最後一個日期
private int downIndex = -1; // 按下的格子索引
private Calendar calendar;
private Surface surface;
private int[] date = new int[42]; // 日曆顯示數字
private int curStartIndex, curEndIndex; // 當前顯示月的日曆起始的索引
private List<ClockStates> mLists = null;// 考勤狀態集合 (年-月-日 1/2/3/4)
//由於點選單元格我們要做相應的處理,所以這裡做一個介面回撥:
private OnItemClickListener onItemClickListener;//日曆格子的點選監聽器
// 給控制元件設定監聽事件
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public MyCalendarView(Context context) {
super(context);
init();
}
public MyCalendarView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
//初始化資料
private void init() {
curDate = selectedStartDate = selectedEndDate = today = new Date();//初始化
calendar = Calendar.getInstance();//獲取日曆
calendar.setTime(curDate);//日曆設定當前月
surface = new Surface();
surface.density = getResources().getDisplayMetrics().density;//取螢幕的密度
setBackgroundColor(surface.bgColor);
setOnTouchListener(this);
}
//測量控制元件
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
surface.width = getResources().getDisplayMetrics().widthPixels;//整個控制元件的寬度
surface.height = (int) (getResources().getDisplayMetrics().heightPixels * 1 / 2);//控制元件的高度取螢幕高度的一半
widthMeasureSpec = MeasureSpec.makeMeasureSpec(surface.width, MeasureSpec.EXACTLY);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(surface.height, MeasureSpec.EXACTLY);
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
if (changed) {
surface.init();
}
super.onLayout(changed, left, top, right, bottom);
}
//畫圖
@Override
protected void onDraw(Canvas canvas) {
// 畫 星期(日 一 二……)
float weekTextY = surface.monthHeight + surface.weekHeight * 3 / 5f;
for (int i = 0; i < surface.weekText.length; i++) {
float weekTextX = i * surface.cellWidth
+ (surface.cellWidth - surface.weekPaint.measureText(surface.weekText[i])) / 2f;
canvas.drawText(surface.weekText[i], weekTextX, weekTextY, surface.weekPaint);
}
// 計算日期
calculateDate();
// 按下狀態,選擇狀態背景色
drawDownOrSelectedBg(canvas);
//單元格內的文字繪製
int todayIndex = -1;
calendar.setTime(curDate);
String curYearAndMonth = calendar.get(Calendar.YEAR) + "" + calendar.get(Calendar.MONTH);//當前年月
calendar.setTime(today);
String todayYearAndMonth = calendar.get(Calendar.YEAR) + "" + calendar.get(Calendar.MONTH);//今天所在的年月
if (curYearAndMonth.equals(todayYearAndMonth)) {
int todayNumber = calendar.get(Calendar.DAY_OF_MONTH);//獲取 今天的日期(日)
todayIndex = curStartIndex + todayNumber - 1;//今天日期的索引
}
int stateIndex = 0;//記錄當月 有狀態的索引
String signText = "";//考勤的標記
int signColor = 0;//考勤標記的顏色
for (int i = 0; i < 42; i++) {
int tColor = Color.parseColor("#000000");// 文字顏色
if (todayIndex != -1 && i == todayIndex) {// 設定選中當天的背景
if (todayIndex == downIndex || downIndex == -1) {
tColor = Color.parseColor("#ffffff");//今天的日期 剛好是你按下時的日期
}
}
//把日曆當前月之外的日期設定為灰暗色
if (isLastMonth(i)) {// 上一個月的日期顏色
tColor = surface.borderColor;
} else if (isNextMonth(i)) {// 下一個月的日期顏色
tColor = surface.borderColor;
}
//索引不是上一個月的,從本月第一天開始
if (!isLastMonth(i) && !isNextMonth(i) && mLists != null && stateIndex < mLists.size()) {
switch (Integer.parseInt(mLists.get(stateIndex).getDateType())) {
case 1://正常
signText = surface.signText[1];
signColor = surface.zcColor;
break;
case 2://異常
signText = surface.signText[2];
signColor = surface.ycColor;
break;
case 3://休息
signText = surface.signText[3];
signColor = surface.xxColor;
break;
case 4://曠工
signText = surface.signText[4];
signColor = surface.kgColor;
break;
}
//畫 考勤狀態標記
drawSignText(canvas, i, signText, signColor);
stateIndex++;
}
//畫日期
drawCellText(canvas, i, date[i] + "", tColor);
}
// 畫邊框
canvas.drawPath(surface.boxPath, surface.borderPaint);
super.onDraw(canvas);
}
//計算日期
private void calculateDate() {
calendar.setTime(curDate);
calendar.set(Calendar.DAY_OF_MONTH, 1);
int dayInWeek = calendar.get(Calendar.DAY_OF_WEEK);
int monthStart = dayInWeek;
if (monthStart == 1) {
monthStart = 8;
}
monthStart -= 1; // 以日為開頭-1,以星期一為開頭-2
curStartIndex = monthStart;
date[monthStart] = 1;
// last month
if (monthStart > 0) {
calendar.set(Calendar.DAY_OF_MONTH, 0);
int dayInmonth = calendar.get(Calendar.DAY_OF_MONTH);
for (int i = monthStart - 1; i >= 0; i--) {
date[i] = dayInmonth;
dayInmonth--;
}
calendar.set(Calendar.DAY_OF_MONTH, date[0]);
}
showFirstDate = calendar.getTime();
// this month
calendar.setTime(curDate);
calendar.add(Calendar.MONTH, 1);
calendar.set(Calendar.DAY_OF_MONTH, 0);
// Log.d(TAG, "m:" + calendar.get(Calendar.MONTH) + " d:" +
// calendar.get(Calendar.DAY_OF_MONTH));
int monthDay = calendar.get(Calendar.DAY_OF_MONTH);
for (int i = 1; i < monthDay; i++) {
date[monthStart + i] = i + 1;
}
curEndIndex = monthStart + monthDay;
// next month
for (int i = monthStart + monthDay; i < 42; i++) {
date[i] = i - (monthStart + monthDay) + 1;
}
if (curEndIndex < 42) {
// 顯示了下一月的
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
calendar.set(Calendar.DAY_OF_MONTH, date[41]);
showLastDate = calendar.getTime();
}
/**
* 畫 單元格內的文字
*
* @param canvas
* @param index
* @param text
*/
private void drawCellText(Canvas canvas, int index, String text, int color) {
int x = getXByIndex(index);//列數
int y = getYByIndex(index);//行數
surface.datePaint.setColor(color);
//月高+星期高+(行數-1)*單元格高+單元格高*0.75f
float cellY = surface.monthHeight + surface.weekHeight + (y - 1) * surface.cellHeight
+ surface.cellHeight * 1 / 2f;
//單元格寬 * (列數-1)+(單元格寬—文字寬)/2f
float cellX = (surface.cellWidth * (x - 1)) + (surface.cellWidth - surface.datePaint.measureText(text)) / 2f;
canvas.drawText(text, cellX, cellY, surface.datePaint);
}
/**
* 畫 單元格內的標記(正常 異常 休息……)
*
* @param canvas
* @param index
* @param text
* @param color
*/
private void drawSignText(Canvas canvas, int index, String text, int color) {
int x = getXByIndex(index);//列數
int y = getYByIndex(index);//行數
surface.signPaint.setColor(color);
//月高+星期高+(行數-1)*單元格高+單元格高*0.75f
float cellY = surface.monthHeight + surface.weekHeight + (y - 1) * surface.cellHeight
+ surface.cellHeight * 1 / 2f + surface.cellHeight * 1 / 3;
//單元格寬 * (列數-1)+(單元格寬—文字寬)/2f
float cellX = (surface.cellWidth * (x - 1)) + (surface.cellWidth - surface.signPaint.measureText(text)) / 2f;
canvas.drawText(text, cellX, cellY, surface.signPaint);
}
/**
* 畫格子的背景
*
* @param canvas
* @param index
* @param color
*/
private void drawCellBg(Canvas canvas, int index, int color) {
int x = getXByIndex(index);
int y = getYByIndex(index);
surface.cellBgPaint.setColor(color);
float left = surface.cellWidth * (x - 1) + surface.borderWidth - 1;
float top = surface.monthHeight + surface.weekHeight + (y - 1) * surface.cellHeight + surface.borderWidth - 1;
canvas.drawRect(left, top, left + surface.cellWidth - surface.borderWidth + 1,
top + surface.cellHeight - surface.borderWidth + 1, surface.cellBgPaint);
}
/**
* 把 一個月的考勤狀態設定給日曆
*
* @param lists
*/
public void setClockStates(List<ClockStates> lists) {
this.mLists = lists;
invalidate();
}
//畫 按下或者選擇日期時的背景
private void drawDownOrSelectedBg(Canvas canvas) {
// 按下未擡起的背景
if (downDate != null) {
drawCellBg(canvas, downIndex, surface.cellDownColor);
}
// 選擇的背景
if (!selectedEndDate.before(showFirstDate) && !selectedStartDate.after(showLastDate)) {
int[] section = new int[]{-1, -1};
calendar.setTime(curDate);
calendar.add(Calendar.MONTH, -1);
findSelectedIndex(0, curStartIndex, calendar, section);
if (section[1] == -1) {
calendar.setTime(curDate);
findSelectedIndex(curStartIndex, curEndIndex, calendar, section);
}
if (section[1] == -1) {
calendar.setTime(curDate);
calendar.add(Calendar.MONTH, 1);
findSelectedIndex(curEndIndex, 42, calendar, section);
}
if (section[0] == -1) {
section[0] = 0;
}
if (section[1] == -1) {
section[1] = 41;
}
for (int i = section[0]; i <= section[1]; i++) {
drawCellBg(canvas, i, surface.cellSelectedColor);
}
}
}
//查到 選中單元格的索引
private void findSelectedIndex(int startIndex, int endIndex, Calendar calendar, int[] section) {
for (int i = startIndex; i < endIndex; i++) {
calendar.set(Calendar.DAY_OF_MONTH, date[i]);
Date temp = calendar.getTime();
if (temp.compareTo(selectedStartDate) == 0) {
section[0] = i;
}
if (temp.compareTo(selectedEndDate) == 0) {
section[1] = i;
return;
}
}
}
//獲取 選中開始的月
public Date getSelectedStartDate() {
return selectedStartDate;
}
//獲取 選中結束的月
public Date getSelectedEndDate() {
return selectedEndDate;
}
//當前點選的索引是不是上一個月的
private boolean isLastMonth(int i) {
if (i < curStartIndex) {
return true;
}
return false;
}
//當前點選的索引是不是下一個月的
private boolean isNextMonth(int i) {
if (i >= curEndIndex) {
return true;
}
return false;
}
//判斷當前點選的格子(所在的年月)是不是上個月的
public boolean isLastMonth(int year, int month) {
calendar.setTime(curDate);
int showYear = calendar.get(Calendar.YEAR);
int showMonth = calendar.get(Calendar.MONTH) + 1;
if (year == showYear && month == showMonth - 1) {
return true;
}
if (year == showYear - 1 && year == 12) {
return true;
}
return false;
}
//判斷當前點選的格子(所在的年月)是不是下個月的
public boolean isNextMonth(int year, int month) {
calendar.setTime(curDate);
int showYear = calendar.get(Calendar.YEAR);
int showMonth = calendar.get(Calendar.MONTH) + 1;
if (year == showYear && month == showMonth + 1) {
return true;
}
if (year == showYear + 1 && year == 1) {
return true;
}
return false;
}
//根據單元格的索引獲取 所在的列數
private int getXByIndex(int i) {
return i % 7 + 1; // 1 2 3 4 5 6 7
}
//根據單元格所在的索引獲取 所在的行數
private int getYByIndex(int i) {
return i / 7 + 1; // 1 2 3 4 5 6
}
/**
* 獲得當前應該顯示的年月
*
* @return 格式:xxxx年x月
*/
public String getYearAndmonth() {
calendar.setTime(curDate);
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1;
return year + "年" + month + "月";
}
/**
* 獲得當前應該顯示的年月
*
* @return 格式:xxxx,x
*/
public String getYearAndmonths() {
calendar.setTime(curDate);
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1;
StringBuffer str = new StringBuffer();
str.append(year);
str.append(",");
str.append(month);
return str.toString();
}
// 點選上一月
public String clickLeftMonth() {
calendar.setTime(curDate);
calendar.add(Calendar.MONTH, -1);
curDate = calendar.getTime();
invalidate();
return getYearAndmonth();
}
// 點選下一月
public String clickRightMonth() {
calendar.setTime(curDate);
calendar.add(Calendar.MONTH, 1);
curDate = calendar.getTime();
invalidate();
return getYearAndmonth();
}
/**
* 跳轉到指定的年月
*
* @param year 指定的年(格式:2017)
* @param month 指定的月(格式:1,2……11,……)
* @return 當前的月份 格式:2017年3月
*/
public String clickSpecifiedMonth(int year, int month) {
calendar.setTime(curDate);
calendar.get(Calendar.YEAR);
int addMonth = 0;//要跳轉多少個月
if (year == calendar.get(Calendar.YEAR)) {
addMonth = month - calendar.get(Calendar.MONTH) - 1;
calendar.add(Calendar.MONTH, addMonth);
} else if (year < calendar.get(Calendar.YEAR)) {
addMonth = (calendar.get(Calendar.YEAR) - year) * 12 + calendar.get(Calendar.MONTH) + 1 - month;
calendar.add(Calendar.MONTH, -addMonth);
} else {
addMonth = (year - calendar.get(Calendar.YEAR)) * 12 + month - calendar.get(Calendar.MONTH) - 1;
calendar.add(Calendar.MONTH, addMonth);
}
curDate = calendar.getTime();
invalidate();
return getYearAndmonth();
}
//設定選中的單元格
private void setSelectedDateByCoor(float x, float y) {
//按下日期單元格(不包括星期)
if (y > surface.monthHeight + surface.weekHeight) {
int m = (int) (Math.floor(x / surface.cellWidth) + 1);//單元格的列數
//單元格的行數(不包括星期)
int n = (int) (Math
.floor((y - (surface.monthHeight + surface.weekHeight)) / Float.valueOf(surface.cellHeight)) + 1);
downIndex = (n - 1) * 7 + m - 1;//計算索引 從0開始記起
calendar.setTime(curDate);
if (isLastMonth(downIndex)) {
calendar.add(Calendar.MONTH, -1);
} else if (isNextMonth(downIndex)) {
calendar.add(Calendar.MONTH, 1);
}
calendar.set(Calendar.DAY_OF_MONTH, date[downIndex]);
downDate = calendar.getTime();
}
invalidate();
}
//觸控單元格的事件處理
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
setSelectedDateByCoor(event.getX(), event.getY());
break;
case MotionEvent.ACTION_UP:
if (downDate != null) {
selectedStartDate = selectedEndDate = downDate;//選中開始的月=選中結束的月 = 按下時的月
// 響應監聽事件
onItemClickListener.OnItemClick(selectedStartDate);
downDate = null;
invalidate();
}
break;
}
return true;
}
// 監聽介面
public interface OnItemClickListener {
void OnItemClick(Date date);
}
/**
* 外觀:
* 1. 佈局尺寸 2. 文字顏色,大小 3. 當前日期的顏色,選擇的日期顏色
*/
private class Surface {
public float density; //密度(設定邊框寬度使用)
public int width; // 整個控制元件的寬度
public int height; // 整個控制元件的高度
public float monthHeight; // 顯示月的高度?
public float weekHeight; // 顯示星期的高度
public float cellWidth; // 日期方框寬度
public float cellHeight; // 日期單元格高度
public float borderWidth;//邊框的寬度
public int bgColor = Color.parseColor("#FFFFFF");// 背景顏色
// 原來的 日期 天數 的文字字型顏色 private int textColor = Color.BLACK;
private int textColor = Color.parseColor("#999999");// Color.rgb(90, 90, 90);文字顏色
private int btnColor = Color.parseColor("#666666");//
private int borderColor = Color.parseColor("#CCCCCC");// 背景邊框線
public int cellDownColor = Color.parseColor("#FF9900");//格子按下時的顏色
public int cellSelectedColor = Color.parseColor("#FF7700");// 格子 選中背景
//畫筆
public Paint borderPaint;//邊框畫筆
public Paint monthPaint;//畫月 的畫筆
public Paint weekPaint;//畫 星期的畫筆
public Paint datePaint;//畫日期(日)的畫筆
public Paint monthChangeBtnPaint;//月份改變的畫筆
public Paint cellBgPaint;//格子背景的畫筆
public Path boxPath; // 邊框路徑
public Paint signPaint;//標記畫筆
//資料
public String[] weekText = {"日", "一", "二", "三", "四", "五", "六"};
public String[] monthText = {"一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"};
public String[] signText = {"", "√", "異常", "休", "曠"};
/**
* 獲取不同狀態時的顏色值(用在日期下面標記的顏色)
* 1.正常,2.異常,3.休息,4.曠工
*/
public int zcColor = getResources().getColor(R.color.zc_clock);// 正常
public int ycColor = getResources().getColor(R.color.yc_clock);// 異常
public int xxColor = getResources().getColor(R.color.xx_clock);// 休息
public int kgColor = getResources().getColor(R.color.kg_clock);// 曠
//外觀初始化
public void init() {
float temp = height / 7f;
monthHeight = 0;
weekHeight = (float) ((temp + temp * 0.3f) * 0.7);//星期的高度
cellHeight = (height - monthHeight - weekHeight) / 6f;//日期(日)單元格的高度= 總-月-星期
cellWidth = width / 7f;//單元格的寬度
//畫邊框
borderPaint = new Paint();
borderPaint.setColor(borderColor);//設定邊框的顏色
borderPaint.setStyle(Paint.Style.STROKE);//設定畫筆的樣式:輪廓線
borderWidth = (float) (0.5 * density);//邊框的寬度
borderWidth = borderWidth < 1 ? 1 : borderWidth;//邊框的寬度跟螢幕適配
borderPaint.setStrokeWidth(borderWidth);//設定邊框的寬度
//畫月份
monthPaint = new Paint();
monthPaint.setColor(textColor);//月份文字的顏色
monthPaint.setAntiAlias(true);//抗鋸齒
float textSize = cellHeight * 0.4f;//月 文字的大小(為單元格的0.4)
monthPaint.setTextSize(textSize);//設定月 文字的大小
//畫 星期
weekPaint = new Paint();
weekPaint.setColor(textColor);//星期 的文字顏色
weekPaint.setAntiAlias(true);
float weekTextSize = weekHeight * 0.4f;
weekPaint.setTextSize(weekTextSize);//設定星期 文字的大小?
//畫 日期(日)
datePaint = new Paint();
datePaint.setColor(textColor);//畫筆顏色
datePaint.setAntiAlias(true);//抗鋸齒
float cellTextSize = cellHeight * 0.4f;//單元格內文字的大小
datePaint.setTextSize(cellTextSize);//設定文字大小
//畫 標記(“