android 自定义日历控件
日历控件View:
- /**
- * 日历控件 功能:获得点选的日期区间
- *
- */
- public class CalendarView extends View implements View.OnTouchListener {
- private final static String TAG = "anCalendar";
- private Date selectedStartDate;
- private Date selectedEndDate;
- private Date curDate; // 当前日历显示的月
- private Date today; // 今天的日期文字显示红色
- private Date downDate; // 手指按下状态时临时日期
- private Date showFirstDate, showLastDate; // 日历显示的第一个日期和最后一个日期
- private int downIndex; // 按下的格子索引
- private Calendar calendar;
- private Surface surface;
- private int[] date = new int[42]; // 日历显示数字
- private int curStartIndex, curEndIndex; // 当前显示的日历起始的索引
- //private boolean completed = false; // 为false表示只选择了开始日期,true表示结束日期也选择了
- //给控件设置监听事件
- private OnItemClickListener onItemClickListener;
- public CalendarView(Context context) {
- super(context);
- init();
- }
- public CalendarView(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*2/5);
- // if (View.MeasureSpec.getMode(widthMeasureSpec) == View.MeasureSpec.EXACTLY) {
- // surface.width = View.MeasureSpec.getSize(widthMeasureSpec);
- // }
- // if (View.MeasureSpec.getMode(heightMeasureSpec) == View.MeasureSpec.EXACTLY) {
- // surface.height = View.MeasureSpec.getSize(heightMeasureSpec);
- // }
- widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(surface.width,
- View.MeasureSpec.EXACTLY);
- heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(surface.height,
- View.MeasureSpec.EXACTLY);
- setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
- @Override
- protected void onLayout(boolean changed, int left, int top, int right,
- int bottom) {
- Log.d(TAG, "[onLayout] changed:"
- + (changed ? "new size" : "not change") + " left:" + left
- + " top:" + top + " right:" + right + " bottom:" + bottom);
- if (changed) {
- surface.init();
- }
- super.onLayout(changed, left, top, right, bottom);
- }
- @Override
- protected void onDraw(Canvas canvas) {
- Log.d(TAG, "onDraw");
- // 画框
- canvas.drawPath(surface.boxPath, surface.borderPaint);
- // 年月
- //String monthText = getYearAndmonth();
- //float textWidth = surface.monthPaint.measureText(monthText);
- //canvas.drawText(monthText, (surface.width - textWidth) / 2f,
- // surface.monthHeight * 3 / 4f, surface.monthPaint);
- // 上一月/下一月
- //canvas.drawPath(surface.preMonthBtnPath, surface.monthChangeBtnPaint);
- //canvas.drawPath(surface.nextMonthBtnPath, surface.monthChangeBtnPaint);
- // 星期
- float weekTextY = surface.monthHeight + surface.weekHeight * 3 / 4f;
- // 星期背景
- // surface.cellBgPaint.setColor(surface.textColor);
- // canvas.drawRect(surface.weekHeight, surface.width, surface.weekHeight, surface.width, surface.cellBgPaint);
- 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);
- // write date number
- // today index
- 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;
- }
- for (int i = 0; i < 42; i++) {
- int color = surface.textColor;
- if (isLastMonth(i)) {
- color = surface.borderColor;
- } else if (isNextMonth(i)) {
- color = surface.borderColor;
- }
- if (todayIndex != -1 && i == todayIndex) {
- color = surface.todayNumberColor;
- }
- drawCellText(canvas, i, date[i] + "", color);
- }
- super.onDraw(canvas);
- }
- private void calculateDate() {
- calendar.setTime(curDate);
- calendar.set(Calendar.DAY_OF_MONTH, 1);
- int dayInWeek = calendar.get(Calendar.DAY_OF_WEEK);
- Log.d(TAG, "day in week:" + dayInWeek);
- 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);
- float cellY = surface.monthHeight + surface.weekHeight + (y - 1)
- * surface.cellHeight + surface.cellHeight * 3 / 4f;
- 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 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;
- float top = surface.monthHeight + surface.weekHeight + (y - 1)
- * surface.cellHeight + surface.borderWidth;
- canvas.drawRect(left, top, left + surface.cellWidth
- - surface.borderWidth, top + surface.cellHeight
- - surface.borderWidth, surface.cellBgPaint);
- }
- private void drawDownOrSelectedBg(Canvas canvas) {
- // down and not up
- if (downDate != null) {
- drawCellBg(canvas, downIndex, surface.cellDownColor);
- }
- // selected bg color
- 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();
- // Log.d(TAG, "temp:" + temp.toLocaleString());
- 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;
- }
- 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
- }
- // 获得当前应该显示的年月
- public String getYearAndmonth() {
- calendar.setTime(curDate);
- int year = calendar.get(Calendar.YEAR);
- int month = calendar.get(Calendar.MONTH);
- return year + "-" + surface.monthText[month];
- }
- //上一月
- 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();
- }
- private void setSelectedDateByCoor(float x, float y) {
- // change month
- // if (y < surface.monthHeight) {
- // // pre month
- // if (x < surface.monthChangeWidth) {
- // calendar.setTime(curDate);
- // calendar.add(Calendar.MONTH, -1);
- // curDate = calendar.getTime();
- // }
- // // next month
- // else if (x > surface.width - surface.monthChangeWidth) {
- // calendar.setTime(curDate);
- // calendar.add(Calendar.MONTH, 1);
- // curDate = calendar.getTime();
- // }
- // }
- // cell click down
- 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;
- Log.d(TAG, "downIndex:" + downIndex);
- 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) {
- // if (!completed) {
- // if (downDate.before(selectedStartDate)) {
- // selectedEndDate = selectedStartDate;
- // selectedStartDate = downDate;
- // } else {
- // selectedEndDate = downDate;
- // }
- // completed = true;
- // } else {
- // selectedStartDate = selectedEndDate = downDate;
- // completed = false;
- // }
- selectedStartDate = selectedEndDate = downDate;
- //响应监听事件
- onItemClickListener.OnItemClick(selectedStartDate);
- // Log.d(TAG, "downdate:" + downDate.toLocaleString());
- //Log.d(TAG, "start:" + selectedStartDate.toLocaleString());
- //Log.d(TAG, "end:" + selectedEndDate.toLocaleString());
- downDate = null;
- invalidate();
- }
- break;
- }
- return true;
- }
- //给控件设置监听事件
- public void setOnItemClickListener(OnItemClickListener onItemClickListener){
- this.onItemClickListener = onItemClickListener;
- }
- //监听接口
- 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 monthChangeWidth; // 上一月、下一月按钮宽度
- 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 textColorUnimportant = Color.parseColor("#666666");
- private int btnColor = Color.parseColor("#666666");
- private int borderColor = Color.parseColor("#CCCCCC");
- public int todayNumberColor = Color.RED;
- public int cellDownColor = Color.parseColor("#CCFFFF");
- public int cellSelectedColor = Color.parseColor("#99CCFF");
- public Paint borderPaint;
- public Paint monthPaint;
- public Paint weekPaint;
- public Paint datePaint;
- public Paint monthChangeBtnPaint;
- public Paint cellBgPaint;
- public Path boxPath; // 边框路径
- //public Path preMonthBtnPath; // 上一月按钮三角形
- //public Path nextMonthBtnPath; // 下一月按钮三角形
- public String[] weekText = { "Sun","Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
- public String[] monthText = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
- public void init() {
- float temp = height / 7f;
- monthHeight = 0;//(float) ((temp + temp * 0.3f) * 0.6);
- //monthChangeWidth = monthHeight * 1.5f;
- 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);
- // Log.d(TAG, "borderwidth:" + borderWidth);
- borderWidth = borderWidth < 1 ? 1 : borderWidth;
- borderPaint.setStrokeWidth(borderWidth);
- monthPaint = new Paint();
- monthPaint.setColor(textColor);
- monthPaint.setAntiAlias(true);
- float textSize = cellHeight * 0.4f;
- Log.d(TAG, "text size:" + textSize);
- monthPaint.setTextSize(textSize);
- monthPaint.setTypeface(Typeface.DEFAULT_BOLD);
- weekPaint = new Paint();
- weekPaint.setColor(textColor);
- weekPaint.setAntiAlias(true);
- float weekTextSize = weekHeight * 0.6f;
- weekPaint.setTextSize(weekTextSize);
- weekPaint.setTypeface(Typeface.DEFAULT_BOLD);
- datePaint = new Paint();
- datePaint.setColor(textColor);
- datePaint.setAntiAlias(true);
- float cellTextSize = cellHeight * 0.5f;
- datePaint.setTextSize(cellTextSize);
- datePaint.setTypeface(Typeface.DEFAULT_BOLD);
- boxPath = new Path();
- //boxPath.addRect(0, 0, width, height, Direction.CW);
- //boxPath.moveTo(0, monthHeight);
- boxPath.rLineTo(width, 0);
- boxPath.moveTo(0, monthHeight + weekHeight);
- boxPath.rLineTo(width, 0);
- for (int i = 1; i < 6; i++) {
- boxPath.moveTo(0, monthHeight + weekHeight + i * cellHeight);
- boxPath.rLineTo(width, 0);
- boxPath.moveTo(i * cellWidth, monthHeight);
- boxPath.rLineTo(0, height - monthHeight);
- }
- boxPath.moveTo(6 * cellWidth, monthHeight);
- boxPath.rLineTo(0, height - monthHeight);
- //preMonthBtnPath = new Path();
- //int btnHeight = (int) (monthHeight * 0.6f);
- //preMonthBtnPath.moveTo(monthChangeWidth / 2f, monthHeight / 2f);
- //preMonthBtnPath.rLineTo(btnHeight / 2f, -btnHeight / 2f);
- //preMonthBtnPath.rLineTo(0, btnHeight);
- //preMonthBtnPath.close();
- //nextMonthBtnPath = new Path();
- //nextMonthBtnPath.moveTo(width - monthChangeWidth / 2f,
- // monthHeight / 2f);
- //nextMonthBtnPath.rLineTo(-btnHeight / 2f, -btnHeight / 2f);
- //nextMonthBtnPath.rLineTo(0, btnHeight);
- //nextMonthBtnPath.close();
- monthChangeBtnPaint = new Paint();
- monthChangeBtnPaint.setAntiAlias(true);
- monthChangeBtnPaint.setStyle(Paint.Style.FILL_AND_STROKE);
- monthChangeBtnPaint.setColor(btnColor);
- cellBgPaint = new Paint();
- cellBgPaint.setAntiAlias(true);
- cellBgPaint.setStyle(Paint.Style.FILL);
- cellBgPaint.setColor(cellSelectedColor);
- }
- }
- }
/**
* 日历控件 功能:获得点选的日期区间
*
*/
public class CalendarView extends View implements View.OnTouchListener {
private final static String TAG = "anCalendar";
private Date selectedStartDate;
private Date selectedEndDate;
private Date curDate; // 当前日历显示的月
private Date today; // 今天的日期文字显示红色
private Date downDate; // 手指按下状态时临时日期
private Date showFirstDate, showLastDate; // 日历显示的第一个日期和最后一个日期
private int downIndex; // 按下的格子索引
private Calendar calendar;
private Surface surface;
private int[] date = new int[42]; // 日历显示数字
private int curStartIndex, curEndIndex; // 当前显示的日历起始的索引
//private boolean completed = false; // 为false表示只选择了开始日期,true表示结束日期也选择了
//给控件设置监听事件
private OnItemClickListener onItemClickListener; public CalendarView(Context context) {
super(context);
init();
} public CalendarView(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*2/5);
// if (View.MeasureSpec.getMode(widthMeasureSpec) == View.MeasureSpec.EXACTLY) {
// surface.width = View.MeasureSpec.getSize(widthMeasureSpec);
// }
// if (View.MeasureSpec.getMode(heightMeasureSpec) == View.MeasureSpec.EXACTLY) {
// surface.height = View.MeasureSpec.getSize(heightMeasureSpec);
// }
widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(surface.width,
View.MeasureSpec.EXACTLY);
heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(surface.height,
View.MeasureSpec.EXACTLY);
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} @Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
Log.d(TAG, "[onLayout] changed:"
+ (changed ? "new size" : "not change") + " left:" + left
+ " top:" + top + " right:" + right + " bottom:" + bottom);
if (changed) {
surface.init();
}
super.onLayout(changed, left, top, right, bottom);
} @Override
protected void onDraw(Canvas canvas) {
Log.d(TAG, "onDraw");
// 画框
canvas.drawPath(surface.boxPath, surface.borderPaint);
// 年月
//String monthText = getYearAndmonth();
//float textWidth = surface.monthPaint.measureText(monthText);
//canvas.drawText(monthText, (surface.width - textWidth) / 2f,
// surface.monthHeight * 3 / 4f, surface.monthPaint);
// 上一月/下一月
//canvas.drawPath(surface.preMonthBtnPath, surface.monthChangeBtnPaint);
//canvas.drawPath(surface.nextMonthBtnPath, surface.monthChangeBtnPaint);
// 星期
float weekTextY = surface.monthHeight + surface.weekHeight * 3 / 4f;
// 星期背景
// surface.cellBgPaint.setColor(surface.textColor);
// canvas.drawRect(surface.weekHeight, surface.width, surface.weekHeight, surface.width, surface.cellBgPaint);
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);
// write date number
// today index
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;
}
for (int i = 0; i < 42; i++) {
int color = surface.textColor;
if (isLastMonth(i)) {
color = surface.borderColor;
} else if (isNextMonth(i)) {
color = surface.borderColor;
}
if (todayIndex != -1 && i == todayIndex) {
color = surface.todayNumberColor;
}
drawCellText(canvas, i, date[i] + "", color);
}
super.onDraw(canvas);
} private void calculateDate() {
calendar.setTime(curDate);
calendar.set(Calendar.DAY_OF_MONTH, 1);
int dayInWeek = calendar.get(Calendar.DAY_OF_WEEK);
Log.d(TAG, "day in week:" + dayInWeek);
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);
float cellY = surface.monthHeight + surface.weekHeight + (y - 1)
* surface.cellHeight + surface.cellHeight * 3 / 4f;
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 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;
float top = surface.monthHeight + surface.weekHeight + (y - 1)
* surface.cellHeight + surface.borderWidth;
canvas.drawRect(left, top, left + surface.cellWidth
- surface.borderWidth, top + surface.cellHeight
- surface.borderWidth, surface.cellBgPaint);
} private void drawDownOrSelectedBg(Canvas canvas) {
// down and not up
if (downDate != null) {
drawCellBg(canvas, downIndex, surface.cellDownColor);
}
// selected bg color
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();
// Log.d(TAG, "temp:" + temp.toLocaleString());
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;
} 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
} // 获得当前应该显示的年月
public String getYearAndmonth() {
calendar.setTime(curDate);
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
return year + "-" + surface.monthText[month];
} //上一月
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();
} private void setSelectedDateByCoor(float x, float y) {
// change month
// if (y < surface.monthHeight) {
// // pre month
// if (x < surface.monthChangeWidth) {
// calendar.setTime(curDate);
// calendar.add(Calendar.MONTH, -1);
// curDate = calendar.getTime();
// }
// // next month
// else if (x > surface.width - surface.monthChangeWidth) {
// calendar.setTime(curDate);
// calendar.add(Calendar.MONTH, 1);
// curDate = calendar.getTime();
// }
// }
// cell click down
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;
Log.d(TAG, "downIndex:" + downIndex);
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) {
// if (!completed) {
// if (downDate.before(selectedStartDate)) {
// selectedEndDate = selectedStartDate;
// selectedStartDate = downDate;
// } else {
// selectedEndDate = downDate;
// }
// completed = true;
// } else {
// selectedStartDate = selectedEndDate = downDate;
// completed = false;
// }
selectedStartDate = selectedEndDate = downDate;
//响应监听事件
onItemClickListener.OnItemClick(selectedStartDate);
// Log.d(TAG, "downdate:" + downDate.toLocaleString());
//Log.d(TAG, "start:" + selectedStartDate.toLocaleString());
//Log.d(TAG, "end:" + selectedEndDate.toLocaleString());
downDate = null;
invalidate();
}
break;
}
return true;
} //给控件设置监听事件
public void setOnItemClickListener(OnItemClickListener onItemClickListener){
this.onItemClickListener = onItemClickListener;
}
//监听接口
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 monthChangeWidth; // 上一月、下一月按钮宽度
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 textColorUnimportant = Color.parseColor("#666666");
private int btnColor = Color.parseColor("#666666");
private int borderColor = Color.parseColor("#CCCCCC");
public int todayNumberColor = Color.RED;
public int cellDownColor = Color.parseColor("#CCFFFF");
public int cellSelectedColor = Color.parseColor("#99CCFF");
public Paint borderPaint;
public Paint monthPaint;
public Paint weekPaint;
public Paint datePaint;
public Paint monthChangeBtnPaint;
public Paint cellBgPaint;
public Path boxPath; // 边框路径
//public Path preMonthBtnPath; // 上一月按钮三角形
//public Path nextMonthBtnPath; // 下一月按钮三角形
public String[] weekText = { "Sun","Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
public String[] monthText = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; public void init() {
float temp = height / 7f;
monthHeight = 0;//(float) ((temp + temp * 0.3f) * 0.6);
//monthChangeWidth = monthHeight * 1.5f;
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);
// Log.d(TAG, "borderwidth:" + borderWidth);
borderWidth = borderWidth < 1 ? 1 : borderWidth;
borderPaint.setStrokeWidth(borderWidth);
monthPaint = new Paint();
monthPaint.setColor(textColor);
monthPaint.setAntiAlias(true);
float textSize = cellHeight * 0.4f;
Log.d(TAG, "text size:" + textSize);
monthPaint.setTextSize(textSize);
monthPaint.setTypeface(Typeface.DEFAULT_BOLD);
weekPaint = new Paint();
weekPaint.setColor(textColor);
weekPaint.setAntiAlias(true);
float weekTextSize = weekHeight * 0.6f;
weekPaint.setTextSize(weekTextSize);
weekPaint.setTypeface(Typeface.DEFAULT_BOLD);
datePaint = new Paint();
datePaint.setColor(textColor);
datePaint.setAntiAlias(true);
float cellTextSize = cellHeight * 0.5f;
datePaint.setTextSize(cellTextSize);
datePaint.setTypeface(Typeface.DEFAULT_BOLD);
boxPath = new Path();
//boxPath.addRect(0, 0, width, height, Direction.CW);
//boxPath.moveTo(0, monthHeight);
boxPath.rLineTo(width, 0);
boxPath.moveTo(0, monthHeight + weekHeight);
boxPath.rLineTo(width, 0);
for (int i = 1; i < 6; i++) {
boxPath.moveTo(0, monthHeight + weekHeight + i * cellHeight);
boxPath.rLineTo(width, 0);
boxPath.moveTo(i * cellWidth, monthHeight);
boxPath.rLineTo(0, height - monthHeight);
}
boxPath.moveTo(6 * cellWidth, monthHeight);
boxPath.rLineTo(0, height - monthHeight);
//preMonthBtnPath = new Path();
//int btnHeight = (int) (monthHeight * 0.6f);
//preMonthBtnPath.moveTo(monthChangeWidth / 2f, monthHeight / 2f);
//preMonthBtnPath.rLineTo(btnHeight / 2f, -btnHeight / 2f);
//preMonthBtnPath.rLineTo(0, btnHeight);
//preMonthBtnPath.close();
//nextMonthBtnPath = new Path();
//nextMonthBtnPath.moveTo(width - monthChangeWidth / 2f,
// monthHeight / 2f);
//nextMonthBtnPath.rLineTo(-btnHeight / 2f, -btnHeight / 2f);
//nextMonthBtnPath.rLineTo(0, btnHeight);
//nextMonthBtnPath.close();
monthChangeBtnPaint = new Paint();
monthChangeBtnPaint.setAntiAlias(true);
monthChangeBtnPaint.setStyle(Paint.Style.FILL_AND_STROKE);
monthChangeBtnPaint.setColor(btnColor);
cellBgPaint = new Paint();
cellBgPaint.setAntiAlias(true);
cellBgPaint.setStyle(Paint.Style.FILL);
cellBgPaint.setColor(cellSelectedColor);
}
}
}
实现日历控件:
- <RelativeLayout
- android:id="@+id/layout_calendar"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:visibility="visible" >
- <TextView
- android:id="@+id/calendarCenter"
- style="@style/main_bar_text_style"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
- android:layout_margin="8dp" />
- <ImageButton
- android:id="@+id/calendarLeft"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:padding="8dp"
- android:contentDescription="@null"
- android:src="@drawable/calendar_month_left"
- android:background="@null"/>
- <ImageButton
- android:id="@+id/calendarRight"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:padding="8dp"
- android:contentDescription="@null"
- android:src="@drawable/calendar_month_right"
- android:background="@null"/>
- <com.techrare.view.CalendarView
- android:id="@+id/calendar"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_below="@+id/calendarCenter" />
- </RelativeLayout>
<RelativeLayout
android:id="@+id/layout_calendar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="visible" > <TextView
android:id="@+id/calendarCenter"
style="@style/main_bar_text_style"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_margin="8dp" /> <ImageButton
android:id="@+id/calendarLeft"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:padding="8dp"
android:contentDescription="@null"
android:src="@drawable/calendar_month_left"
android:background="@null"/> <ImageButton
android:id="@+id/calendarRight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:padding="8dp"
android:contentDescription="@null"
android:src="@drawable/calendar_month_right"
android:background="@null"/> <com.techrare.view.CalendarView
android:id="@+id/calendar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/calendarCenter" />
</RelativeLayout>
- <style name="main_bar_text_style">
- <item name="android:textColor">@color/white</item>
- <item name="android:textStyle">bold</item>
- <item name="android:textSize">18sp</item>
- </style>
<style name="main_bar_text_style">
<item name="android:textColor">@color/white</item>
<item name="android:textStyle">bold</item>
<item name="android:textSize">18sp</item>
</style>
上一月图片:
- 调用 calendar.clickLeftMonth();
调用 calendar.clickLeftMonth();
下一月:
- 调用 calendar.clickRightMonth();
调用 calendar.clickRightMonth();
日历控件中的一些功能(可以自己加):
- //获取日历控件对象
- calendar = (CalendarView)findViewById(R.id.calendar);
- //获取日历中年月 ya[0]为年,ya[1]为月(格式大家可以自行在日历控件中改)
- String[] ya = calendar.getYearAndmonth().split("-");
- //点击上一月 同样返回年月
- String leftYearAndmonth = calendar.clickLeftMonth();
- String[] lya = leftYearAndmonth.split("-");
- //点击下一月
- String rightYearAndmonth = calendar.clickRightMonth();
- String[] rya = rightYearAndmonth.split("-");
- //设置控件监听,可以监听到点击的每一天(大家也可以在控件中自行设定)
- calendar.setOnItemClickListener(new calendarItemClickListener());
- class calendarItemClickListener implements OnItemClickListener{
- @Override
- public void OnItemClick(Date date) {
- Toast.makeText(getApplicationContext(), date+"", Toast.LENGTH_SHORT).show();
- }
- }
android 自定义日历控件的更多相关文章
- Android自定义日历控件(继承系统控件实现)
Android自定义日历控件(继承系统控件实现) 主要步骤 编写布局 继承LinearLayout设置子控件 设置数据 继承TextView实现有圆圈背景的TextView 添加Attribute 添 ...
- Android 一个日历控件的实现代码
转载 2017-05-19 作者:Othershe 我要评论 本篇文章主要介绍了Android 一个日历控件的实现代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看 ...
- javascript实例学习之六—自定义日历控件
基于之前上篇博客轻量级jquery,tool.js和base.js.自定义开发的base_datePicker插件,效果类似于jquery_ui的datePicker插件 //基于Base.js以及t ...
- 撸一个Android高性能日历控件,高仿魅族
Android原生的CalendarView根本无法满足我们日常开发的需要,在开发吾记APP的过程中,我觉得需要来一款高性能且美观简洁的日历控件,觉得魅族的日历风格十分适合,于是打算撸一款. gith ...
- IOS自定义日历控件的简单实现(附思想及过程)
因为程序要求要插入一个日历控件,该空间的要求是从当天开始及以后的六个月内的日历,上网查资料基本上都说只要获取两个条件(当月第一天周几和本月一共有多少天)就可以实现一个简单的日历,剩下的靠自己的简单逻辑 ...
- android自定义倒计时控件示例
这篇文章主要介绍了Android秒杀倒计时自定义TextView示例,大家参考使用吧 自定义TextView控件TimeTextView代码: 复制代码 代码如下: import android.co ...
- Android自定义组合控件详细示例 (附完整源码)
在我们平时的Android开发中,有时候原生的控件无法满足我们的需求,或者经常用到几个控件组合在一起来使用.这个时候,我们就可以根据自己的需求创建自定义的控件了,一般通过继承View或其子类来实现. ...
- 014 Android 自定义组合控件
1.需求介绍 将已经编写好的布局文件,抽取到一个类中去做管理,下次还需要使用类似布局时,直接使用该组合控件的对象. 优点:可复用. 例如要重复利用以下布局: <RelativeLayout an ...
- Android自定义用户控件简单范例(二)
对于完全由后台定制的控件,并不是很方便其他人的使用,因为我们常常需要看到控件放到xml界面上的效果,并根据效果进行布局的调整,这就需要一个更加标准的控件制作流程: 我们的自定义控件和其他的控件一样,应 ...
随机推荐
- UVALive 3942 Remember the Word(字典树+DP)
题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...
- 如何防止鼠标移出移入子元素触发mouseout和mouseover事件
js代码: function isMouseLeaveOrEnter(e, handler) { var reltg=e.relatedTarget?e.relatedTarget:e.type==' ...
- php socket获取数据类
<?php define("CONNECTED", true); define("DISCONNECTED", false); /** * Socket ...
- C2第三次作业解题报告
看过题解后如果觉得还算有用,请帮忙加点我所在团队博客访问量 http://www.cnblogs.com/newbe/ http://www.cnblogs.com/newbe/p/4069834.h ...
- 揭秘Sql2014新特性-tempdb性能提升
一直以来,在高负载,复杂的生产环境中,tempdb的压力是成为整个实例瓶颈的重要因素之一.微软的工程师们也在各个版本中不断优化它的使用.到了Sql Server2014又有了新的特性使其性能得temp ...
- PC-PC-单片机(Arduino)通信实例
请仔细理解相关参数,如端口设置.IP设置.COM口设置......等等.....不要盲目COPY.....这涉及2台电脑和一个单片机,其中一台电脑作为服务器并与单片机相连,负责通过网络与客户端通信(s ...
- jQuery Mobile + HTML5
最近项目需要,需要构建一个适合手持设备访问的站点,作者从网上查阅了一些资料,本文就是基于此而来. 首先下载jQuery Mobile http://jquerymobile.com/,选择稳定版即可. ...
- mysql悲观锁总结和实践
使用场景举例:以MySQL InnoDB为例商品t_goods表中有一个字段status,status为1代表商品未被下单,status为2代表商品已经被下单,那么我们对某个商品下单时必须确保该商品s ...
- Atitit.dwr3 不能显示错误详细信息的解决方案,控件显示错误详细信息的解决方案 java .net php
Atitit.dwr3 不能显示错误详细信息的解决方案,控件显示错误详细信息的解决方案 java .net php 1. Keyword/subtitle 1 2. 使用dwr3的异常convert处 ...
- iOS-网络请求-AFN升级至AFN3.0
AFNetworking是一款在OS X和iOS下都令人喜爱的网络库.为了迎合iOS新版本的升级, AFNetworking在3.0版本中删除了基于 NSURLConnection API的所有支持. ...