[Android教程] Android系统自定义实现日历控件
2016-04-20 17:02
701 查看
注:此功能在在Activity中,由三大块组成:头(上月按扭,下月按扭,当前年月文本),日历块(星期区域,日期区域),描述区域
Activity:
/**
* Android实现日历控件
* 注:Calendar时间与现在实的时间在月份上需要+1,因为月份是0-11
*/
public class CalenderActivity extends Activity {
http://m.nvzi91.cn/gongjingmilan/29426.html
private ArrayList<DateWidgetDayView> days = new ArrayList<DateWidgetDayView>();
//颜色代码常量
public static int Calendar_WeekBgColor = 0;
public static int Calendar_DayBgColor = 0;
public static int IsHoliday_BgColor = 0;
public static int UnPresentMonth_FontColor = 0;
public static int IsPresentMonth_FontColor = 0;
public static int IsToday_BgColor = 0;
public static int Special_Reminder = 0;
public static int Common_Reminder = 0;
public static int Calendar_WeekFontColor = 0;
/**
* 表格中的第一天,一般上月的某一天
*/
public static Calendar mFirstDateOfPanel = Calendar.getInstance();
private Calendar mTodayDate = Calendar.getInstance();// 初始日期,即当天
private Calendar mSelectedDate = Calendar.getInstance();//选中的日期,如果未选中则为1970-1-1
private Calendar mViewDate = Calendar.getInstance();
// 当前操作日期
private int firstDayOfWeek = Calendar.SUNDAY;// 是星期日
private int currentMonth = 0;
private int currentYear = 0;
private int displayWidth = 0;// 屏幕总宽度
private int cell_Width = 0; // 日期单元格宽度
private int cell_Height = 35; // 日期单元格高度
// 页面控件
TextView currentYAndM = null;
Button preMonthButton = null;
Button nextMonthButton = null;
LinearLayout mainLayout = null;
LinearLayout calendarLayout = null;
LinearLayout contentLayout = null;
TextView contentText = null;
// 数据源
Boolean[] msgs = null;
Calendar startDate = null;//表格的第一天的日期
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.calendar_main);
this.viewModel = new BlogViewModel(this);
// 获得屏幕宽和高,并計算出屏幕寬度分七等份的大小
WindowManager windowManager = getWindowManager();
Display display = windowManager.getDefaultDisplay();
displayWidth = display.getWidth();
cell_Width = displayWidth / 7 + 1;
// 制定布局文件,并设置属性
mainLayout = (LinearLayout) this.findViewById(R.id.date_calender_framelayout);
currentYAndM = (TextView) findViewById(R.id.Top_Date);
preMonthButton = (Button) findViewById(R.id.btn_pre_month);
nextMonthButton = (Button) findViewById(R.id.btn_next_month);
preMonthButton.setOnClickListener(new OnClickPreMonthListener());
nextMonthButton.setOnClickListener(new OnClickNextMonthListener());
// 计算本月日历中的第一天(一般是上月的某天),并更新日历
mFirstDateOfPanel = getCalendarStartDate();
this.mTodayDate = getTodayDate();
this.startDate = getStartDate();
/*
* 初始化日期视图
* Calendar部分
*/
View calendarView = generateCalendarView();
this.mainLayout.addView(calendarView);
//刷新日期视图
this.refreshCalendar();
/*
* Description 部分
*/
ScrollView view = new ScrollView(this);
contentLayout = createLayout(LinearLayout.VERTICAL);
contentLayout.setPadding(5, 2, 0, 0);
contentText = new TextView(this);
contentText.setTextColor(Color.BLACK);
contentText.setTextSize(18);
contentLayout.addView(contentText);
LinearLayout.LayoutParams Param1 = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
view.addView(contentLayout, Param1);
mainLayout.setBackgroundColor(Color.WHITE);
mainLayout.addView(view);
/* 新建线程
new Thread() {
@Override
public void run() {
int day = getIndexFromDates(mTodayDate, startDate);
Log.i("sys", "初始时 day = "+day);
}
}.start();*/
Calendar_WeekBgColor = this.getResources().getColor(R.color.Calendar_WeekBgColor);
Calendar_DayBgColor = this.getResources().getColor(R.color.Calendar_DayBgColor);
IsHoliday_BgColor = this.getResources().getColor(R.color.isHoliday_BgColor);
UnPresentMonth_FontColor = this.getResources().getColor(R.color.unPresentMonth_FontColor);
IsPresentMonth_FontColor = this.getResources().getColor(R.color.isPresentMonth_FontColor);
IsToday_BgColor = this.getResources().getColor(R.color.isToday_BgColor);
Special_Reminder = this.getResources().getColor(R.color.specialReminder);
Common_Reminder = this.getResources().getColor(R.color.commonReminder);
Calendar_WeekFontColor = this.getResources().getColor(R.color.Calendar_WeekFontColor);
}
protected String getDateShortString(Calendar date) {
String returnString = date.get(Calendar.YEAR) + "-";
returnString += date.get(Calendar.MONTH) + 1 + "-";
returnString += date.get(Calendar.DAY_OF_MONTH);
return returnString;
}
/**
* Return the Date's index of {@LINK returnDate} from {@link datesList};
* First is Today's index
*
* @param now
* today
* @param returnDate
* click date
* @return
*/http://m.nvzi91.cn/gongjingfeida/29428.html
private int getIndexFromDates(Calendar now, Calendar returnDate) {
Calendar cNow = (Calendar) now.clone();
Calendar cReturnDate = (Calendar) returnDate.clone();
CalenderUtil.setTimeToMidnight(cNow);
CalenderUtil.setTimeToMidnight(cReturnDate);
long todayMs = cNow.getTimeInMillis();
long returnMs = cReturnDate.getTimeInMillis();
long intervalMs = todayMs - returnMs;
int index = CalenderUtil.millisecondsToDays(intervalMs);
Log.i("sys", "Index = " + index);
return index;
}
/**
* 生成日期视图 即初始化calendarLayout
*
* @return
*/
private View generateCalendarView() {
calendarLayout = createLayout(LinearLayout.VERTICAL);
// layContent.setPadding(1, 0, 1, 0);
calendarLayout.setBackgroundColor(Color.argb(255, 105, 105, 103));
calendarLayout.addView(generateCalendarWeekRows());
days.clear();
for (int iRow = 0; iRow < 6; iRow++) {
calendarLayout.addView(generateCalendarDayRows());
}
return calendarLayout;
}
/**
* 生成星期View
*
* @return View
*/
private View generateCalendarWeekRows() {
LinearLayout weekLayoutRow = createLayout(LinearLayout.HORIZONTAL);
weekLayoutRow.setBackgroundColor(Color.argb(255, 207, 207, 205));
for (int iDay = 0; iDay < 7; iDay++) {
DateWidgetWeekView dayView = new DateWidgetWeekView(this, cell_Width, cell_Height);
final int iWeekDay = CalenderUtil.getWeekDay(iDay, firstDayOfWeek);
dayView.setData(iWeekDay);
weekLayoutRow.addView(dayView);
}
return weekLayoutRow;
}
/**
* 生成日期行View
*
* @return View
*/
private View generateCalendarDayRows() {
LinearLayout layRow = createLayout(LinearLayout.HORIZONTAL);
//TODO 日期数据消息给添加属性
for (int iDay = 0; iDay < 7; iDay++) {
DateWidgetDayView dateDayView = new DateWidgetDayView(this, cell_Width, cell_Width);
dateDayView.setItemClick(mOnDayCellClick);
days.add(dateDayView);
layRow.addView(dateDayView);
}
return layRow;
}
/**
* 由于本日历上的日期都是从周一开始的,此方法可推算出上月在本月日历中显示的天数 计算出本月第一行1号前的空格数
*/
private void updateStartDateForPanel() {
currentMonth = mFirstDateOfPanel.get(Calendar.MONTH);
currentYear = mFirstDateOfPanel.get(Calendar.YEAR);
mFirstDateOfPanel.set(Calendar.DAY_OF_MONTH, 1);
mFirstDateOfPanel.set(Calendar.HOUR_OF_DAY, 0);
mFirstDateOfPanel.set(Calendar.MINUTE, 0);
mFirstDateOfPanel.set(Calendar.SECOND, 0);
// 显示当前是的年月在Header
updateCurrentMonthDisplay();
int iDay = 0;// 前面的空格数
int iStartDay = firstDayOfWeek;// 当天的星期角标
if (iStartDay == Calendar.MONDAY) {
iDay = mFirstDateOfPanel.get(Calendar.DAY_OF_WEEK) - Calendar.MONDAY;
if (iDay < 0)
iDay = 6;
}
if (iStartDay == Calendar.SUNDAY) {
iDay = mFirstDateOfPanel.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY;
if (iDay < 0)
iDay = 6;
}
mFirstDateOfPanel.add(Calendar.DAY_OF_WEEK, -iDay);// 得出-2,即前面从上月30号开始
}
/**
* 更新日历数据并设置日期
* 给days中的DateWidgetDayView元素添加Text
*/
private void refreshCalendar() {
DateWidgetDayView dayView = null;
boolean isSelected = false;
final boolean bIsSelection = (mSelectedDate.getTimeInMillis() != 0);
final int iSelectedYear = mSelectedDate.get(Calendar.YEAR);
final int iSelectedMonth = mSelectedDate.get(Calendar.MONTH);
final int iSelectedDay = mSelectedDate.get(Calendar.DAY_OF_MONTH);
//取得表格中的第一天(一般为上月)
mViewDate.setTimeInMillis(mFirstDateOfPanel.getTimeInMillis());
for (int i = 0; i < days.size(); i++) {
final int iYear = mViewDate.get(Calendar.YEAR);
final int iMonth = mViewDate.get(Calendar.MONTH);
final int iDay = mViewDate.get(Calendar.DAY_OF_MONTH);
final int iDayOfWeek = mViewDate.get(Calendar.DAY_OF_WEEK);
dayView = days.get(i);
// Check isToday
boolean isToday = false;
if (mTodayDate.get(Calendar.YEAR) == iYear && mTodayDate.get(Calendar.MONTH) == iMonth && mTodayDate.get(Calendar.DAY_OF_MONTH) == iDay) {
isToday = true;
}
// Check isHoliday
boolean isHoliday = false;
if ((iDayOfWeek == Calendar.SATURDAY) || (iDayOfWeek == Calendar.SUNDAY))
isHoliday = true;
/*if ((iMonth == Calendar.JANUARY) && (iDay == 1))
isHoliday = true;*///在格里高利历和罗马儒略历中一年中的第一个月是 JANUARY,它为 0;最后一个月取决于一年中的月份数。
// Check isSelected
isSelected = false;
if (bIsSelection)
if ((iSelectedDay == iDay) && (iSelectedMonth == iMonth) && (iSelectedYear == iYear)) {
isSelected = true;
}
dayView.setSelected(isSelected);
// Check hasMSG
boolean hasMSG = false;
if (msgs != null && msgs[i] == true ){
//TODO
}
if (isSelected){
dayView.setFocusable(true);
}
dayView.setData(iYear, iMonth, iDay, isToday, isHoliday, currentMonth, hasMSG);
mViewDate.add(Calendar.DAY_OF_MONTH, 1);
Log.i("sys", "mViewDate : "+iYear+"-"+iMonth+"-"+iDay);
Log.i("sys", "mFirstDateOfPanel : "+mFirstDateOfPanel.get(Calendar.YEAR)+"-"+mFirstDateOfPanel.get(Calendar.MONTH)+"-"+mFirstDateOfPanel.get(Calendar.DAY_OF_MONTH));
}
Log.i("sys", "mSelectedDate : "+iSelectedYear+"-"+iSelectedMonth+"-"+iSelectedDay);
Log.i("sys", "startDate : "+startDate.get(Calendar.YEAR)+"-"+startDate.get(Calendar.MONTH)+"-"+startDate.get(Calendar.DAY_OF_MONTH));
calendarLayout.invalidate();
}
/**
* 设置当天日期和第并计算出前面第一个星期天的日期{@link mFirstDateOfPanel}
* @return
*/
private Calendar getCalendarStartDate() {
mTodayDate.setTimeInMillis(System.currentTimeMillis());
mTodayDate.setFirstDayOfWeek(firstDayOfWeek);
http://m.nvzi91.cn/gongjingmilan/29429.html
// 如果没有选中日期,则设置当前日期为 ?
if (mSelectedDate.getTimeInMillis() == 0) {
mFirstDateOfPanel.setTimeInMillis(System.currentTimeMillis());
mFirstDateOfPanel.setFirstDayOfWeek(firstDayOfWeek);
} else {
mFirstDateOfPanel.setTimeInMillis(mSelectedDate.getTimeInMillis());
mFirstDateOfPanel.setFirstDayOfWeek(firstDayOfWeek);
}
updateStartDateForPanel();
return mFirstDateOfPanel;
}
/**
* 得到当前日历表中的第一天
*
* @return Calendar
*/
public Calendar getStartDate() {
int iDay = 0;
Calendar cal_Now = Calendar.getInstance();
cal_Now.set(Calendar.DAY_OF_MONTH, 1);
cal_Now.set(Calendar.HOUR_OF_DAY, 0);
cal_Now.set(Calendar.MINUTE, 0);
cal_Now.set(Calendar.SECOND, 0);
cal_Now.setFirstDayOfWeek(Calendar.SUNDAY);
iDay = cal_Now.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY;
if (iDay < 0) {
iDay = 6;
}
cal_Now.add(Calendar.DAY_OF_WEEK, -iDay);
return cal_Now;
}
public Calendar getTodayDate() {
Calendar cal_Today = Calendar.getInstance();
cal_Today.set(Calendar.HOUR_OF_DAY, 0);
cal_Today.set(Calendar.MINUTE, 0);
cal_Today.set(Calendar.SECOND, 0);
cal_Today.setFirstDayOfWeek(Calendar.MONDAY);
return cal_Today;
}
/**
* 更新日历标题上显示的年月
*/
private void updateCurrentMonthDisplay() {
String date = mFirstDateOfPanel.get(Calendar.YEAR) + "年" + (mFirstDateOfPanel.get(Calendar.MONTH) + 1) + "月";
currentYAndM.setText(date);
}
/**
* 点击上月按钮,触发事件
* @author Win7
*/
// 生成布局LinearLayout
private LinearLayout createLayout(int iOrientation) {
LinearLayout lay = new LinearLayout(this);
lay.setLayoutParams(new LayoutParams(android.view.ViewGroup.LayoutParams.FILL_PARENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT));
lay.setOrientation(iOrientation);
return lay;
}
class OnClickPreMonthListener implements OnClickListener {
@Override
public void onClick(View v) {
contentText.setText("aaaa");
mSelectedDate.setTimeInMillis(0);
currentMonth--;
if (currentMonth == -1) {
currentMonth = 11;
currentYear--;
}
mFirstDateOfPanel.set(Calendar.DAY_OF_MONTH, 1);
mFirstDateOfPanel.set(Calendar.MONTH, currentMonth);
mFirstDateOfPanel.set(Calendar.YEAR, currentYear);
mFirstDateOfPanel.set(Calendar.HOUR_OF_DAY, 0);
mFirstDateOfPanel.set(Calendar.MINUTE, 0);
mFirstDateOfPanel.set(Calendar.SECOND, 0);
mFirstDateOfPanel.set(Calendar.MILLISECOND, 0);
updateStartDateForPanel();
startDate = (Calendar) mFirstDateOfPanel.clone();
// 新建线程
new Thread() {
@Override
public void run() {
int day = getIndexFromDates(mTodayDate, startDate);
//day是算出当前显示的月份面版第一天与当天的天数
Log.i("sys", "点击上月时 day = "+day);
}
}.start();
refreshCalendar();
}
}
/**
* 点击下月按钮,触发事件
* @author Win7
*/
class OnClickNextMonthListener implements OnClickListener {
@Override
public void onClick(View v) {
contentText.setText("");
mSelectedDate.setTimeInMillis(0);
currentMonth++;
if (currentMonth == 12) {
currentMonth = 0;
currentYear++;
}
mFirstDateOfPanel.set(Calendar.DAY_OF_MONTH, 1);
mFirstDateOfPanel.set(Calendar.MONTH, currentMonth);
mFirstDateOfPanel.set(Calendar.YEAR, currentYear);
updateStartDateForPanel();
startDate = (Calendar) mFirstDateOfPanel.clone();
// 新建线程
new Thread() {
@Override
public void run() {
int day = 5;
Log.i("sys", "点击下月时 day = "+day);
}
}.start();
refreshCalendar();
}
}
// 点击日历,触发事件
private DateWidgetDayView.OnDateItemClickListener mOnDayCellClick = new DateWidgetDayView.OnDateItemClickListener() {
public void OnClick(DateWidgetDayView item) {
mSelectedDate.setTimeInMillis(item.getDate().getTimeInMillis());
int day = getIndexFromDates(mSelectedDate, startDate);
contentText.setText(getDateShortString(mSelectedDate));
contentText.setText("无数据");
Log.i("sys", "mFirstDateOfPanel=" + mFirstDateOfPanel.get(Calendar.DATE) + " calCalendar=" + mViewDate.get(Calendar.DATE) + " mTodayDate=" + mTodayDate.get(Calendar.DATE)
+ " mSelectedDate=" + mSelectedDate.get(Calendar.DATE) +" day = "+day);
item.setSelected(true);
refreshCalendar();
}
};
@Deprecated
public Calendar getEndDate(Calendar startDate) {
// Calendar end = GetStartDate(enddate);
Calendar endDate = Calendar.getInstance();
endDate = (Calendar) startDate.clone();
endDate.add(Calendar.DAY_OF_MONTH, 41);
return endDate;
}
}
星期View:
public class DateWidgetWeekView extends View {
// 字体大小
private final static int fTextSize = 22;
private Paint pt = new Paint();
private RectF rect = new RectF();
private int iWeekDay = -1;
m.nvzi91.cn
public DateWidgetWeekView(Context context, int iWidth, int iHeight) {
super(context);
setLayoutParams(new LayoutParams(iWidth, iHeight));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 设置矩形大小
rect.set(0, 0, this.getWidth(), this.getHeight());
rect.inset(1, 1);
// 绘制日历头部
drawDayHeader(canvas);
}
private void drawDayHeader(Canvas canvas) {
// 画矩形,并设置矩形画笔的颜色
pt.setColor(CalenderActivity.Calendar_WeekBgColor);
canvas.drawRect(rect, pt);
// 写入日历头部,设置画笔参数
pt.setTypeface(null);
pt.setTextSize(fTextSize);
pt.setAntiAlias(true);
pt.setFakeBoldText(true);
pt.setColor(CalenderActivity.Calendar_WeekFontColor);
// draw day name
final String sDayName = CalenderUtil.getWeekDayName(iWeekDay);
final int iPosX = (int) rect.left + ((int) rect.width() >> 1)
- ((int) pt.measureText(sDayName) >> 1);
final int iPosY = (int) (this.getHeight()
- (this.getHeight() - getTextHeight()) / 2 - pt
.getFontMetrics().bottom);
canvas.drawText(sDayName, iPosX, iPosY, pt);
}
// 得到字体高度
private int getTextHeight() {
return (int) (-pt.ascent() + pt.descent());
}
// 得到一星期的第几天的文本标记
public void setData(int iWeekDay) {
this.iWeekDay = iWeekDay;
}
}
日期View:
/**
* 日历控件单元格绘制类
* @Description: 日历控件单元格绘制类
* @FileName: DateWidgetDayView.java
*/
public class DateWidgetDayView extends View {
// 字体大小
private static final int fTextSize = 28;
// 基本元素
private OnDateItemClickListener itemClick = null;
private Paint mPaint = new Paint();
private RectF rect = new RectF();
private String sDate = "";
// 当前日期
private int iDateYear = 0;
private int iDateMonth = 0;
private int iDateDay = 0;
// 布尔变量
private boolean hasSelected = false;
private boolean isActiveMonth = false;
private boolean isToday = false;
private boolean isTouchedDown = false;
private boolean isHoliday = false;
private boolean hasMSG = false;
public static int ANIM_ALPHA_DURATION = 100;
public interface OnDateItemClickListener {
public void OnClick(DateWidgetDayView item);
}
// 构造函数
public DateWidgetDayView(Context context, int iWidth, int iHeight) {
super(context);
setFocusable(true);
setLayoutParams(new LayoutParams(iWidth, iHeight));
}
// 取变量值
public Calendar getDate() {
Calendar calDate = Calendar.getInstance();
calDate.clear();
calDate.set(Calendar.YEAR, iDateYear);
calDate.set(Calendar.MONTH, iDateMonth);
calDate.set(Calendar.DAY_OF_MONTH, iDateDay);
return calDate;
}
// 是否有消息
public boolean hasMSG() {
return this.hasMSG;
}
// 是否假期
public boolean isHoliday() {
return this.isHoliday;
}
// 设置变量值
public void setData(int iYear, int iMonth, int iDay, Boolean bToday,
Boolean bHoliday, int iActiveMonth, boolean hasRecord) {
iDateYear = iYear;
iDateMonth = iMonth;
iDateDay = iDay;
this.sDate = Integer.toString(iDateDay);
this.isActiveMonth = (iDateMonth == iActiveMonth);
this.isToday = bToday;
this.isHoliday = bHoliday;
this.hasMSG = hasRecord;
}
// 重载绘制方法
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
rect.set(0, 0, this.getWidth(), this.getHeight());
rect.inset(1, 1);
final boolean bFocused = IsViewFocused();
drawDayView(canvas, bFocused);
drawDayNumber(canvas);
}
public boolean IsViewFocused() {
return (this.isFocused() || isTouchedDown);
}
// 绘制日历方格
private void drawDayView(Canvas canvas, boolean bFocused) {
if (hasSelected || bFocused) {
LinearGradient lGradBkg = null;
if (bFocused) {
lGradBkg = new LinearGradient(rect.left, 0, rect.right, 0,
0xffaa5500, 0xffffddbb, Shader.TileMode.CLAMP);
}
if (hasSelected) {
lGradBkg = new LinearGradient(rect.left, 0, rect.right, 0,
0xff225599, 0xffbbddff, Shader.TileMode.CLAMP);
}
if (lGradBkg != null) {
mPaint.setShader(lGradBkg);
canvas.drawRect(rect, mPaint);
}
mPaint.setShader(null);
} else {
mPaint.setColor(getColorBkg(isHoliday, isToday));
canvas.drawRect(rect, mPaint);
}
if(isHoliday){
mPaint.setColor(CalenderActivity.IsHoliday_BgColor);
canvas.drawRect(rect, mPaint);
}
if (hasMSG) {
markHasMSGReminder(canvas, CalenderActivity.Special_Reminder);
}
// else if (!hasRecord && !bToday && !bSelected) {
// CreateReminder(canvas, Calendar_TestActivity.Calendar_DayBgColor);
// }
}
// 绘制日历中的数字
public void drawDayNumber(Canvas canvas) {
// draw day number
mPaint.setTypeface(null);
mPaint.setAntiAlias(true);
mPaint.setShader(null);
mPaint.setFakeBoldText(true);
mPaint.setTextSize(fTextSize);
mPaint.setColor(CalenderActivity.IsPresentMonth_FontColor);
mPaint.setUnderlineText(false);
if (!isActiveMonth)
mPaint.setColor(CalenderActivity.UnPresentMonth_FontColor);
if (isToday)
mPaint.setUnderlineText(true);
final int iPosX = (int) rect.left + ((int) rect.width() >> 1) - ((int) mPaint.measureText(sDate) >> 1);
final int iPosY = (int) (this.getHeight() - (this.getHeight() - getTextHeight()) / 2 - mPaint .getFontMetrics().bottom);
canvas.drawText(sDate, iPosX, iPosY, mPaint);
mPaint.setUnderlineText(false);
}
// 得到字体高度
private int getTextHeight() {
return (int) (-mPaint.ascent() + mPaint.descent());
}
// 根据条件返回不同颜色值
public static int getColorBkg(boolean bHoliday, boolean bToday) {
if (bToday)
return CalenderActivity.IsToday_BgColor;
// if (bHoliday) //如需周末有特殊背景色,可去掉注释
// return Calendar_TestActivity.isHoliday_BgColor;
return CalenderActivity.Calendar_DayBgColor;
}
// 设置是否被选中
@Override
public void setSelected(boolean bEnable) {
if (this.hasSelected != bEnable) {
this.hasSelected = bEnable;
this.invalidate();
}
}
public void setItemClick(OnDateItemClickListener itemClick) {
this.itemClick = itemClick;
}
public void doItemClick() {
if (itemClick != null)
itemClick.OnClick(this);
}
// 点击事件
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean bHandled = false;
if (event.getAction() == MotionEvent.ACTION_DOWN) {
bHandled = true;
isTouchedDown = true;
invalidate();
startAlphaAnimIn(DateWidgetDayView.this);
}
if (event.getAction() == MotionEvent.ACTION_CANCEL) {
bHandled = true;
isTouchedDown = false;
invalidate();
}
if (event.getAction() == MotionEvent.ACTION_UP) {
bHandled = true;
isTouchedDown = false;
invalidate();
doItemClick();
}
return bHandled;
}
// 点击事件
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
boolean bResult = super.onKeyDown(keyCode, event);
if ((keyCode == KeyEvent.KEYCODE_DPAD_CENTER)
|| (keyCode == KeyEvent.KEYCODE_ENTER)) {
doItemClick();
}
return bResult;
}
// 不透明度渐变
public static void startAlphaAnimIn(View view) {
AlphaAnimation anim = new AlphaAnimation(0.5F, 1);
anim.setDuration(ANIM_ALPHA_DURATION);
anim.startNow();
view.startAnimation(anim);
}
//右上角画倒三角
public void markHasMSGReminder(Canvas canvas, int Color) {
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setColor(Color);
Path path = new Path();
path.moveTo(rect.right - rect.width() / 4, rect.top);
path.lineTo(rect.right, rect.top);
path.lineTo(rect.right, rect.top + rect.width() / 4);
path.lineTo(rect.right - rect.width() / 4, rect.top);
path.close();
canvas.drawPath(path, mPaint);
}
}
工具类:
public class CalenderUtil {
private final static String[] vecStrWeekDayNames = getWeekDayNames();
private static String[] getWeekDayNames() {
String[] vec = new String[10];
vec[Calendar.SUNDAY] = "星期日";
vec[Calendar.MONDAY] = "星期一";
vec[Calendar.TUESDAY] = "星期二";
vec[Calendar.WEDNESDAY] = "星期三";
vec[Calendar.THURSDAY] = "星期四";
vec[Calendar.FRIDAY] = "星期五";
vec[Calendar.SATURDAY] = "星期六";
return vec;
}
public static String getWeekDayName(int iDay) {
return vecStrWeekDayNames[iDay];
}
public static int getWeekDay(int index, int iFirstDayOfWeek) {
int iWeekDay = -1;
if (iFirstDayOfWeek == Calendar.MONDAY) {
iWeekDay = index + Calendar.MONDAY;
if (iWeekDay > Calendar.SATURDAY)
iWeekDay = Calendar.SUNDAY;
}
if (iFirstDayOfWeek == Calendar.SUNDAY) {
iWeekDay = index + Calendar.SUNDAY;
}
return iWeekDay;
}
/**
* Calculate the days with milliseconds
* @param intervalMs
* @return
*/
public static int millisecondsToDays(long intervalMs) {
return Math.round((intervalMs / (1000 * 86400)));
}
/**
* Return the milliseconds from 1970 to just
* @param calendar
*/
public static void setTimeToMidnight(Calendar calendar) {
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
}
}
calendar_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_horizontal"
android:orientation="vertical" >
<RelativeLayout
android:id="@+id/relativeLayout1"
android:layout_width="fill_parent"
android:layout_height="60dip"
android:background="#EDE8DD" >
<TextView
android:id="@+id/Top_Date"
android:layout_width="150dip"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center_horizontal|center"
android:textColor="#424139"
android:textSize="19sp"
android:textStyle="bold" />
<Button
android:id="@+id/btn_pre_month"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="30dp"
android:background="@drawable/previous_month"
android:text="" />
<Button
android:id="@+id/btn_next_month"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="30dp"
android:background="@drawable/next_month"
android:text="" />
</RelativeLayout>
<LinearLayout
android:id="@+id/date_calender_framelayout"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
></LinearLayout>
</LinearLayout>
Activity:
/**
* Android实现日历控件
* 注:Calendar时间与现在实的时间在月份上需要+1,因为月份是0-11
*/
public class CalenderActivity extends Activity {
http://m.nvzi91.cn/gongjingmilan/29426.html
private ArrayList<DateWidgetDayView> days = new ArrayList<DateWidgetDayView>();
//颜色代码常量
public static int Calendar_WeekBgColor = 0;
public static int Calendar_DayBgColor = 0;
public static int IsHoliday_BgColor = 0;
public static int UnPresentMonth_FontColor = 0;
public static int IsPresentMonth_FontColor = 0;
public static int IsToday_BgColor = 0;
public static int Special_Reminder = 0;
public static int Common_Reminder = 0;
public static int Calendar_WeekFontColor = 0;
/**
* 表格中的第一天,一般上月的某一天
*/
public static Calendar mFirstDateOfPanel = Calendar.getInstance();
private Calendar mTodayDate = Calendar.getInstance();// 初始日期,即当天
private Calendar mSelectedDate = Calendar.getInstance();//选中的日期,如果未选中则为1970-1-1
private Calendar mViewDate = Calendar.getInstance();
// 当前操作日期
private int firstDayOfWeek = Calendar.SUNDAY;// 是星期日
private int currentMonth = 0;
private int currentYear = 0;
private int displayWidth = 0;// 屏幕总宽度
private int cell_Width = 0; // 日期单元格宽度
private int cell_Height = 35; // 日期单元格高度
// 页面控件
TextView currentYAndM = null;
Button preMonthButton = null;
Button nextMonthButton = null;
LinearLayout mainLayout = null;
LinearLayout calendarLayout = null;
LinearLayout contentLayout = null;
TextView contentText = null;
// 数据源
Boolean[] msgs = null;
Calendar startDate = null;//表格的第一天的日期
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.calendar_main);
this.viewModel = new BlogViewModel(this);
// 获得屏幕宽和高,并計算出屏幕寬度分七等份的大小
WindowManager windowManager = getWindowManager();
Display display = windowManager.getDefaultDisplay();
displayWidth = display.getWidth();
cell_Width = displayWidth / 7 + 1;
// 制定布局文件,并设置属性
mainLayout = (LinearLayout) this.findViewById(R.id.date_calender_framelayout);
currentYAndM = (TextView) findViewById(R.id.Top_Date);
preMonthButton = (Button) findViewById(R.id.btn_pre_month);
nextMonthButton = (Button) findViewById(R.id.btn_next_month);
preMonthButton.setOnClickListener(new OnClickPreMonthListener());
nextMonthButton.setOnClickListener(new OnClickNextMonthListener());
// 计算本月日历中的第一天(一般是上月的某天),并更新日历
mFirstDateOfPanel = getCalendarStartDate();
this.mTodayDate = getTodayDate();
this.startDate = getStartDate();
/*
* 初始化日期视图
* Calendar部分
*/
View calendarView = generateCalendarView();
this.mainLayout.addView(calendarView);
//刷新日期视图
this.refreshCalendar();
/*
* Description 部分
*/
ScrollView view = new ScrollView(this);
contentLayout = createLayout(LinearLayout.VERTICAL);
contentLayout.setPadding(5, 2, 0, 0);
contentText = new TextView(this);
contentText.setTextColor(Color.BLACK);
contentText.setTextSize(18);
contentLayout.addView(contentText);
LinearLayout.LayoutParams Param1 = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
view.addView(contentLayout, Param1);
mainLayout.setBackgroundColor(Color.WHITE);
mainLayout.addView(view);
/* 新建线程
new Thread() {
@Override
public void run() {
int day = getIndexFromDates(mTodayDate, startDate);
Log.i("sys", "初始时 day = "+day);
}
}.start();*/
Calendar_WeekBgColor = this.getResources().getColor(R.color.Calendar_WeekBgColor);
Calendar_DayBgColor = this.getResources().getColor(R.color.Calendar_DayBgColor);
IsHoliday_BgColor = this.getResources().getColor(R.color.isHoliday_BgColor);
UnPresentMonth_FontColor = this.getResources().getColor(R.color.unPresentMonth_FontColor);
IsPresentMonth_FontColor = this.getResources().getColor(R.color.isPresentMonth_FontColor);
IsToday_BgColor = this.getResources().getColor(R.color.isToday_BgColor);
Special_Reminder = this.getResources().getColor(R.color.specialReminder);
Common_Reminder = this.getResources().getColor(R.color.commonReminder);
Calendar_WeekFontColor = this.getResources().getColor(R.color.Calendar_WeekFontColor);
}
protected String getDateShortString(Calendar date) {
String returnString = date.get(Calendar.YEAR) + "-";
returnString += date.get(Calendar.MONTH) + 1 + "-";
returnString += date.get(Calendar.DAY_OF_MONTH);
return returnString;
}
/**
* Return the Date's index of {@LINK returnDate} from {@link datesList};
* First is Today's index
*
* @param now
* today
* @param returnDate
* click date
* @return
*/http://m.nvzi91.cn/gongjingfeida/29428.html
private int getIndexFromDates(Calendar now, Calendar returnDate) {
Calendar cNow = (Calendar) now.clone();
Calendar cReturnDate = (Calendar) returnDate.clone();
CalenderUtil.setTimeToMidnight(cNow);
CalenderUtil.setTimeToMidnight(cReturnDate);
long todayMs = cNow.getTimeInMillis();
long returnMs = cReturnDate.getTimeInMillis();
long intervalMs = todayMs - returnMs;
int index = CalenderUtil.millisecondsToDays(intervalMs);
Log.i("sys", "Index = " + index);
return index;
}
/**
* 生成日期视图 即初始化calendarLayout
*
* @return
*/
private View generateCalendarView() {
calendarLayout = createLayout(LinearLayout.VERTICAL);
// layContent.setPadding(1, 0, 1, 0);
calendarLayout.setBackgroundColor(Color.argb(255, 105, 105, 103));
calendarLayout.addView(generateCalendarWeekRows());
days.clear();
for (int iRow = 0; iRow < 6; iRow++) {
calendarLayout.addView(generateCalendarDayRows());
}
return calendarLayout;
}
/**
* 生成星期View
*
* @return View
*/
private View generateCalendarWeekRows() {
LinearLayout weekLayoutRow = createLayout(LinearLayout.HORIZONTAL);
weekLayoutRow.setBackgroundColor(Color.argb(255, 207, 207, 205));
for (int iDay = 0; iDay < 7; iDay++) {
DateWidgetWeekView dayView = new DateWidgetWeekView(this, cell_Width, cell_Height);
final int iWeekDay = CalenderUtil.getWeekDay(iDay, firstDayOfWeek);
dayView.setData(iWeekDay);
weekLayoutRow.addView(dayView);
}
return weekLayoutRow;
}
/**
* 生成日期行View
*
* @return View
*/
private View generateCalendarDayRows() {
LinearLayout layRow = createLayout(LinearLayout.HORIZONTAL);
//TODO 日期数据消息给添加属性
for (int iDay = 0; iDay < 7; iDay++) {
DateWidgetDayView dateDayView = new DateWidgetDayView(this, cell_Width, cell_Width);
dateDayView.setItemClick(mOnDayCellClick);
days.add(dateDayView);
layRow.addView(dateDayView);
}
return layRow;
}
/**
* 由于本日历上的日期都是从周一开始的,此方法可推算出上月在本月日历中显示的天数 计算出本月第一行1号前的空格数
*/
private void updateStartDateForPanel() {
currentMonth = mFirstDateOfPanel.get(Calendar.MONTH);
currentYear = mFirstDateOfPanel.get(Calendar.YEAR);
mFirstDateOfPanel.set(Calendar.DAY_OF_MONTH, 1);
mFirstDateOfPanel.set(Calendar.HOUR_OF_DAY, 0);
mFirstDateOfPanel.set(Calendar.MINUTE, 0);
mFirstDateOfPanel.set(Calendar.SECOND, 0);
// 显示当前是的年月在Header
updateCurrentMonthDisplay();
int iDay = 0;// 前面的空格数
int iStartDay = firstDayOfWeek;// 当天的星期角标
if (iStartDay == Calendar.MONDAY) {
iDay = mFirstDateOfPanel.get(Calendar.DAY_OF_WEEK) - Calendar.MONDAY;
if (iDay < 0)
iDay = 6;
}
if (iStartDay == Calendar.SUNDAY) {
iDay = mFirstDateOfPanel.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY;
if (iDay < 0)
iDay = 6;
}
mFirstDateOfPanel.add(Calendar.DAY_OF_WEEK, -iDay);// 得出-2,即前面从上月30号开始
}
/**
* 更新日历数据并设置日期
* 给days中的DateWidgetDayView元素添加Text
*/
private void refreshCalendar() {
DateWidgetDayView dayView = null;
boolean isSelected = false;
final boolean bIsSelection = (mSelectedDate.getTimeInMillis() != 0);
final int iSelectedYear = mSelectedDate.get(Calendar.YEAR);
final int iSelectedMonth = mSelectedDate.get(Calendar.MONTH);
final int iSelectedDay = mSelectedDate.get(Calendar.DAY_OF_MONTH);
//取得表格中的第一天(一般为上月)
mViewDate.setTimeInMillis(mFirstDateOfPanel.getTimeInMillis());
for (int i = 0; i < days.size(); i++) {
final int iYear = mViewDate.get(Calendar.YEAR);
final int iMonth = mViewDate.get(Calendar.MONTH);
final int iDay = mViewDate.get(Calendar.DAY_OF_MONTH);
final int iDayOfWeek = mViewDate.get(Calendar.DAY_OF_WEEK);
dayView = days.get(i);
// Check isToday
boolean isToday = false;
if (mTodayDate.get(Calendar.YEAR) == iYear && mTodayDate.get(Calendar.MONTH) == iMonth && mTodayDate.get(Calendar.DAY_OF_MONTH) == iDay) {
isToday = true;
}
// Check isHoliday
boolean isHoliday = false;
if ((iDayOfWeek == Calendar.SATURDAY) || (iDayOfWeek == Calendar.SUNDAY))
isHoliday = true;
/*if ((iMonth == Calendar.JANUARY) && (iDay == 1))
isHoliday = true;*///在格里高利历和罗马儒略历中一年中的第一个月是 JANUARY,它为 0;最后一个月取决于一年中的月份数。
// Check isSelected
isSelected = false;
if (bIsSelection)
if ((iSelectedDay == iDay) && (iSelectedMonth == iMonth) && (iSelectedYear == iYear)) {
isSelected = true;
}
dayView.setSelected(isSelected);
// Check hasMSG
boolean hasMSG = false;
if (msgs != null && msgs[i] == true ){
//TODO
}
if (isSelected){
dayView.setFocusable(true);
}
dayView.setData(iYear, iMonth, iDay, isToday, isHoliday, currentMonth, hasMSG);
mViewDate.add(Calendar.DAY_OF_MONTH, 1);
Log.i("sys", "mViewDate : "+iYear+"-"+iMonth+"-"+iDay);
Log.i("sys", "mFirstDateOfPanel : "+mFirstDateOfPanel.get(Calendar.YEAR)+"-"+mFirstDateOfPanel.get(Calendar.MONTH)+"-"+mFirstDateOfPanel.get(Calendar.DAY_OF_MONTH));
}
Log.i("sys", "mSelectedDate : "+iSelectedYear+"-"+iSelectedMonth+"-"+iSelectedDay);
Log.i("sys", "startDate : "+startDate.get(Calendar.YEAR)+"-"+startDate.get(Calendar.MONTH)+"-"+startDate.get(Calendar.DAY_OF_MONTH));
calendarLayout.invalidate();
}
/**
* 设置当天日期和第并计算出前面第一个星期天的日期{@link mFirstDateOfPanel}
* @return
*/
private Calendar getCalendarStartDate() {
mTodayDate.setTimeInMillis(System.currentTimeMillis());
mTodayDate.setFirstDayOfWeek(firstDayOfWeek);
http://m.nvzi91.cn/gongjingmilan/29429.html
// 如果没有选中日期,则设置当前日期为 ?
if (mSelectedDate.getTimeInMillis() == 0) {
mFirstDateOfPanel.setTimeInMillis(System.currentTimeMillis());
mFirstDateOfPanel.setFirstDayOfWeek(firstDayOfWeek);
} else {
mFirstDateOfPanel.setTimeInMillis(mSelectedDate.getTimeInMillis());
mFirstDateOfPanel.setFirstDayOfWeek(firstDayOfWeek);
}
updateStartDateForPanel();
return mFirstDateOfPanel;
}
/**
* 得到当前日历表中的第一天
*
* @return Calendar
*/
public Calendar getStartDate() {
int iDay = 0;
Calendar cal_Now = Calendar.getInstance();
cal_Now.set(Calendar.DAY_OF_MONTH, 1);
cal_Now.set(Calendar.HOUR_OF_DAY, 0);
cal_Now.set(Calendar.MINUTE, 0);
cal_Now.set(Calendar.SECOND, 0);
cal_Now.setFirstDayOfWeek(Calendar.SUNDAY);
iDay = cal_Now.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY;
if (iDay < 0) {
iDay = 6;
}
cal_Now.add(Calendar.DAY_OF_WEEK, -iDay);
return cal_Now;
}
public Calendar getTodayDate() {
Calendar cal_Today = Calendar.getInstance();
cal_Today.set(Calendar.HOUR_OF_DAY, 0);
cal_Today.set(Calendar.MINUTE, 0);
cal_Today.set(Calendar.SECOND, 0);
cal_Today.setFirstDayOfWeek(Calendar.MONDAY);
return cal_Today;
}
/**
* 更新日历标题上显示的年月
*/
private void updateCurrentMonthDisplay() {
String date = mFirstDateOfPanel.get(Calendar.YEAR) + "年" + (mFirstDateOfPanel.get(Calendar.MONTH) + 1) + "月";
currentYAndM.setText(date);
}
/**
* 点击上月按钮,触发事件
* @author Win7
*/
// 生成布局LinearLayout
private LinearLayout createLayout(int iOrientation) {
LinearLayout lay = new LinearLayout(this);
lay.setLayoutParams(new LayoutParams(android.view.ViewGroup.LayoutParams.FILL_PARENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT));
lay.setOrientation(iOrientation);
return lay;
}
class OnClickPreMonthListener implements OnClickListener {
@Override
public void onClick(View v) {
contentText.setText("aaaa");
mSelectedDate.setTimeInMillis(0);
currentMonth--;
if (currentMonth == -1) {
currentMonth = 11;
currentYear--;
}
mFirstDateOfPanel.set(Calendar.DAY_OF_MONTH, 1);
mFirstDateOfPanel.set(Calendar.MONTH, currentMonth);
mFirstDateOfPanel.set(Calendar.YEAR, currentYear);
mFirstDateOfPanel.set(Calendar.HOUR_OF_DAY, 0);
mFirstDateOfPanel.set(Calendar.MINUTE, 0);
mFirstDateOfPanel.set(Calendar.SECOND, 0);
mFirstDateOfPanel.set(Calendar.MILLISECOND, 0);
updateStartDateForPanel();
startDate = (Calendar) mFirstDateOfPanel.clone();
// 新建线程
new Thread() {
@Override
public void run() {
int day = getIndexFromDates(mTodayDate, startDate);
//day是算出当前显示的月份面版第一天与当天的天数
Log.i("sys", "点击上月时 day = "+day);
}
}.start();
refreshCalendar();
}
}
/**
* 点击下月按钮,触发事件
* @author Win7
*/
class OnClickNextMonthListener implements OnClickListener {
@Override
public void onClick(View v) {
contentText.setText("");
mSelectedDate.setTimeInMillis(0);
currentMonth++;
if (currentMonth == 12) {
currentMonth = 0;
currentYear++;
}
mFirstDateOfPanel.set(Calendar.DAY_OF_MONTH, 1);
mFirstDateOfPanel.set(Calendar.MONTH, currentMonth);
mFirstDateOfPanel.set(Calendar.YEAR, currentYear);
updateStartDateForPanel();
startDate = (Calendar) mFirstDateOfPanel.clone();
// 新建线程
new Thread() {
@Override
public void run() {
int day = 5;
Log.i("sys", "点击下月时 day = "+day);
}
}.start();
refreshCalendar();
}
}
// 点击日历,触发事件
private DateWidgetDayView.OnDateItemClickListener mOnDayCellClick = new DateWidgetDayView.OnDateItemClickListener() {
public void OnClick(DateWidgetDayView item) {
mSelectedDate.setTimeInMillis(item.getDate().getTimeInMillis());
int day = getIndexFromDates(mSelectedDate, startDate);
contentText.setText(getDateShortString(mSelectedDate));
contentText.setText("无数据");
Log.i("sys", "mFirstDateOfPanel=" + mFirstDateOfPanel.get(Calendar.DATE) + " calCalendar=" + mViewDate.get(Calendar.DATE) + " mTodayDate=" + mTodayDate.get(Calendar.DATE)
+ " mSelectedDate=" + mSelectedDate.get(Calendar.DATE) +" day = "+day);
item.setSelected(true);
refreshCalendar();
}
};
@Deprecated
public Calendar getEndDate(Calendar startDate) {
// Calendar end = GetStartDate(enddate);
Calendar endDate = Calendar.getInstance();
endDate = (Calendar) startDate.clone();
endDate.add(Calendar.DAY_OF_MONTH, 41);
return endDate;
}
}
星期View:
public class DateWidgetWeekView extends View {
// 字体大小
private final static int fTextSize = 22;
private Paint pt = new Paint();
private RectF rect = new RectF();
private int iWeekDay = -1;
m.nvzi91.cn
public DateWidgetWeekView(Context context, int iWidth, int iHeight) {
super(context);
setLayoutParams(new LayoutParams(iWidth, iHeight));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 设置矩形大小
rect.set(0, 0, this.getWidth(), this.getHeight());
rect.inset(1, 1);
// 绘制日历头部
drawDayHeader(canvas);
}
private void drawDayHeader(Canvas canvas) {
// 画矩形,并设置矩形画笔的颜色
pt.setColor(CalenderActivity.Calendar_WeekBgColor);
canvas.drawRect(rect, pt);
// 写入日历头部,设置画笔参数
pt.setTypeface(null);
pt.setTextSize(fTextSize);
pt.setAntiAlias(true);
pt.setFakeBoldText(true);
pt.setColor(CalenderActivity.Calendar_WeekFontColor);
// draw day name
final String sDayName = CalenderUtil.getWeekDayName(iWeekDay);
final int iPosX = (int) rect.left + ((int) rect.width() >> 1)
- ((int) pt.measureText(sDayName) >> 1);
final int iPosY = (int) (this.getHeight()
- (this.getHeight() - getTextHeight()) / 2 - pt
.getFontMetrics().bottom);
canvas.drawText(sDayName, iPosX, iPosY, pt);
}
// 得到字体高度
private int getTextHeight() {
return (int) (-pt.ascent() + pt.descent());
}
// 得到一星期的第几天的文本标记
public void setData(int iWeekDay) {
this.iWeekDay = iWeekDay;
}
}
日期View:
/**
* 日历控件单元格绘制类
* @Description: 日历控件单元格绘制类
* @FileName: DateWidgetDayView.java
*/
public class DateWidgetDayView extends View {
// 字体大小
private static final int fTextSize = 28;
// 基本元素
private OnDateItemClickListener itemClick = null;
private Paint mPaint = new Paint();
private RectF rect = new RectF();
private String sDate = "";
// 当前日期
private int iDateYear = 0;
private int iDateMonth = 0;
private int iDateDay = 0;
// 布尔变量
private boolean hasSelected = false;
private boolean isActiveMonth = false;
private boolean isToday = false;
private boolean isTouchedDown = false;
private boolean isHoliday = false;
private boolean hasMSG = false;
public static int ANIM_ALPHA_DURATION = 100;
public interface OnDateItemClickListener {
public void OnClick(DateWidgetDayView item);
}
// 构造函数
public DateWidgetDayView(Context context, int iWidth, int iHeight) {
super(context);
setFocusable(true);
setLayoutParams(new LayoutParams(iWidth, iHeight));
}
// 取变量值
public Calendar getDate() {
Calendar calDate = Calendar.getInstance();
calDate.clear();
calDate.set(Calendar.YEAR, iDateYear);
calDate.set(Calendar.MONTH, iDateMonth);
calDate.set(Calendar.DAY_OF_MONTH, iDateDay);
return calDate;
}
// 是否有消息
public boolean hasMSG() {
return this.hasMSG;
}
// 是否假期
public boolean isHoliday() {
return this.isHoliday;
}
// 设置变量值
public void setData(int iYear, int iMonth, int iDay, Boolean bToday,
Boolean bHoliday, int iActiveMonth, boolean hasRecord) {
iDateYear = iYear;
iDateMonth = iMonth;
iDateDay = iDay;
this.sDate = Integer.toString(iDateDay);
this.isActiveMonth = (iDateMonth == iActiveMonth);
this.isToday = bToday;
this.isHoliday = bHoliday;
this.hasMSG = hasRecord;
}
// 重载绘制方法
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
rect.set(0, 0, this.getWidth(), this.getHeight());
rect.inset(1, 1);
final boolean bFocused = IsViewFocused();
drawDayView(canvas, bFocused);
drawDayNumber(canvas);
}
public boolean IsViewFocused() {
return (this.isFocused() || isTouchedDown);
}
// 绘制日历方格
private void drawDayView(Canvas canvas, boolean bFocused) {
if (hasSelected || bFocused) {
LinearGradient lGradBkg = null;
if (bFocused) {
lGradBkg = new LinearGradient(rect.left, 0, rect.right, 0,
0xffaa5500, 0xffffddbb, Shader.TileMode.CLAMP);
}
if (hasSelected) {
lGradBkg = new LinearGradient(rect.left, 0, rect.right, 0,
0xff225599, 0xffbbddff, Shader.TileMode.CLAMP);
}
if (lGradBkg != null) {
mPaint.setShader(lGradBkg);
canvas.drawRect(rect, mPaint);
}
mPaint.setShader(null);
} else {
mPaint.setColor(getColorBkg(isHoliday, isToday));
canvas.drawRect(rect, mPaint);
}
if(isHoliday){
mPaint.setColor(CalenderActivity.IsHoliday_BgColor);
canvas.drawRect(rect, mPaint);
}
if (hasMSG) {
markHasMSGReminder(canvas, CalenderActivity.Special_Reminder);
}
// else if (!hasRecord && !bToday && !bSelected) {
// CreateReminder(canvas, Calendar_TestActivity.Calendar_DayBgColor);
// }
}
// 绘制日历中的数字
public void drawDayNumber(Canvas canvas) {
// draw day number
mPaint.setTypeface(null);
mPaint.setAntiAlias(true);
mPaint.setShader(null);
mPaint.setFakeBoldText(true);
mPaint.setTextSize(fTextSize);
mPaint.setColor(CalenderActivity.IsPresentMonth_FontColor);
mPaint.setUnderlineText(false);
if (!isActiveMonth)
mPaint.setColor(CalenderActivity.UnPresentMonth_FontColor);
if (isToday)
mPaint.setUnderlineText(true);
final int iPosX = (int) rect.left + ((int) rect.width() >> 1) - ((int) mPaint.measureText(sDate) >> 1);
final int iPosY = (int) (this.getHeight() - (this.getHeight() - getTextHeight()) / 2 - mPaint .getFontMetrics().bottom);
canvas.drawText(sDate, iPosX, iPosY, mPaint);
mPaint.setUnderlineText(false);
}
// 得到字体高度
private int getTextHeight() {
return (int) (-mPaint.ascent() + mPaint.descent());
}
// 根据条件返回不同颜色值
public static int getColorBkg(boolean bHoliday, boolean bToday) {
if (bToday)
return CalenderActivity.IsToday_BgColor;
// if (bHoliday) //如需周末有特殊背景色,可去掉注释
// return Calendar_TestActivity.isHoliday_BgColor;
return CalenderActivity.Calendar_DayBgColor;
}
// 设置是否被选中
@Override
public void setSelected(boolean bEnable) {
if (this.hasSelected != bEnable) {
this.hasSelected = bEnable;
this.invalidate();
}
}
public void setItemClick(OnDateItemClickListener itemClick) {
this.itemClick = itemClick;
}
public void doItemClick() {
if (itemClick != null)
itemClick.OnClick(this);
}
// 点击事件
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean bHandled = false;
if (event.getAction() == MotionEvent.ACTION_DOWN) {
bHandled = true;
isTouchedDown = true;
invalidate();
startAlphaAnimIn(DateWidgetDayView.this);
}
if (event.getAction() == MotionEvent.ACTION_CANCEL) {
bHandled = true;
isTouchedDown = false;
invalidate();
}
if (event.getAction() == MotionEvent.ACTION_UP) {
bHandled = true;
isTouchedDown = false;
invalidate();
doItemClick();
}
return bHandled;
}
// 点击事件
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
boolean bResult = super.onKeyDown(keyCode, event);
if ((keyCode == KeyEvent.KEYCODE_DPAD_CENTER)
|| (keyCode == KeyEvent.KEYCODE_ENTER)) {
doItemClick();
}
return bResult;
}
// 不透明度渐变
public static void startAlphaAnimIn(View view) {
AlphaAnimation anim = new AlphaAnimation(0.5F, 1);
anim.setDuration(ANIM_ALPHA_DURATION);
anim.startNow();
view.startAnimation(anim);
}
//右上角画倒三角
public void markHasMSGReminder(Canvas canvas, int Color) {
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setColor(Color);
Path path = new Path();
path.moveTo(rect.right - rect.width() / 4, rect.top);
path.lineTo(rect.right, rect.top);
path.lineTo(rect.right, rect.top + rect.width() / 4);
path.lineTo(rect.right - rect.width() / 4, rect.top);
path.close();
canvas.drawPath(path, mPaint);
}
}
工具类:
public class CalenderUtil {
private final static String[] vecStrWeekDayNames = getWeekDayNames();
private static String[] getWeekDayNames() {
String[] vec = new String[10];
vec[Calendar.SUNDAY] = "星期日";
vec[Calendar.MONDAY] = "星期一";
vec[Calendar.TUESDAY] = "星期二";
vec[Calendar.WEDNESDAY] = "星期三";
vec[Calendar.THURSDAY] = "星期四";
vec[Calendar.FRIDAY] = "星期五";
vec[Calendar.SATURDAY] = "星期六";
return vec;
}
public static String getWeekDayName(int iDay) {
return vecStrWeekDayNames[iDay];
}
public static int getWeekDay(int index, int iFirstDayOfWeek) {
int iWeekDay = -1;
if (iFirstDayOfWeek == Calendar.MONDAY) {
iWeekDay = index + Calendar.MONDAY;
if (iWeekDay > Calendar.SATURDAY)
iWeekDay = Calendar.SUNDAY;
}
if (iFirstDayOfWeek == Calendar.SUNDAY) {
iWeekDay = index + Calendar.SUNDAY;
}
return iWeekDay;
}
/**
* Calculate the days with milliseconds
* @param intervalMs
* @return
*/
public static int millisecondsToDays(long intervalMs) {
return Math.round((intervalMs / (1000 * 86400)));
}
/**
* Return the milliseconds from 1970 to just
* @param calendar
*/
public static void setTimeToMidnight(Calendar calendar) {
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
}
}
calendar_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_horizontal"
android:orientation="vertical" >
<RelativeLayout
android:id="@+id/relativeLayout1"
android:layout_width="fill_parent"
android:layout_height="60dip"
android:background="#EDE8DD" >
<TextView
android:id="@+id/Top_Date"
android:layout_width="150dip"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center_horizontal|center"
android:textColor="#424139"
android:textSize="19sp"
android:textStyle="bold" />
<Button
android:id="@+id/btn_pre_month"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="30dp"
android:background="@drawable/previous_month"
android:text="" />
<Button
android:id="@+id/btn_next_month"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="30dp"
android:background="@drawable/next_month"
android:text="" />
</RelativeLayout>
<LinearLayout
android:id="@+id/date_calender_framelayout"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
></LinearLayout>
</LinearLayout>
相关文章推荐
- Android AutoLayout全新的适配方式 堪称适配终结者
- [Android教程] android获得json数据并处理
- 学习使用Android Chronometer计时器
- 关于MPAndroidChart柱状图左右滑动
- MVP模式在Android中的应用实例
- Android应用开发之所有动画使用详解
- OpenCV学习笔记(五)—— OpenCV for Android剔除OpenCV Manager依赖
- Android 图片裁切框架 uCrop 的用法
- Gradle sync failed: Gradle DSL method not found: 'android()'
- android studio 初步的dex分包应用
- Android RecyclerView布局就这么简单
- Android 使用DatePicker以及TimePicker显示当前日期和时间
- android开发中常见颜色值
- android中Button和TextView的关系
- Android Design Support Library使用详解
- Android日期显示和选择库
- Android布局控件之RelativeLayout
- no lable views point to this text field with an android:lablFor=”@+id/@+id
- android警告——Buttons in button bars should be border
- ScrollView中软键盘弹出依然遮住控件