我使用自定义日历显示月份和日期。一切正常,但要求是,我不应该在当前日历中显示过去的日期。 例如:如果12月1日星期五开始,则不应显示31,30。
这是我完成的代码。所以在xml中,使用“CalendarPickerView”并在对话框中显示。
参考:Github
CalendarPickerView
public class CalendarPickerView extends FrameLayout {
private CalendarNumbersView calendar;
private TextView tvCalendarCaption;
private ImageView ivPrevMonth;
private ImageView ivNextMonth;
public CalendarPickerView(Context context) {
super(context);
init();
}
public CalendarPickerView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CalendarPickerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
LayoutInflater.from(getContext()).inflate(R.layout.view_date_time_picker, this);
tvCalendarCaption = (TextView) findViewById(R.id.tvCalendarCaption);
calendar = (CalendarNumbersView) findViewById(R.id.calendar);
ivPrevMonth = (ImageView) findViewById(R.id.ivPrevMonth);
ivNextMonth = (ImageView) findViewById(R.id.ivNextMonth);
ivPrevMonth.setOnClickListener(onPrevMonthClickListener);
ivNextMonth.setOnClickListener(onNextMonthClickListener);
updateCaption();
}
public void setListener(CalendarNumbersView.DateSelectionListener listener) {
calendar.setListener(listener);
}
public CalendarNumbersView.DateSelectionListener getListener() {
return calendar.getListener();
}
private void updateCaption() {
SimpleDateFormat format = new SimpleDateFormat("MMMM yyyy", Locale.getDefault());
tvCalendarCaption.setText(format.format(calendar.getShownMonth().getTime()).toUpperCase());
}
public CalendarNumbersView getCalendar() {
return calendar;
}
private OnClickListener onPrevMonthClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
Calendar prevMonth = calendar.getShownMonth();
prevMonth.add(Calendar.MONTH, -1);
calendar.setShownMonth(prevMonth);
updateCaption();
}
};
private OnClickListener onNextMonthClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
Calendar nextMonth = calendar.getShownMonth();
nextMonth.add(Calendar.MONTH, 1);
calendar.setShownMonth(nextMonth);
updateCaption();
}
};
}
CalendarNumbersView
public class CalendarNumbersView extends View {
public static final int MAX_WEEKS_IN_MONTH = 6;
private float MAX_SELECTION_FINGER_SHIFT_DIST = 5.0f;
private TextPaint paint;
private int cellPadding;
private int textColor;
private int inactiveTextColor;
private int selectionTextColor;
private int cellBackgroundColor;
private int cellSelectionBackgroundColor;
private int dayNamesTextColor;
private int dayNamesBackgroundColor;
private boolean showDayNames = true;
private Locale locale = Locale.getDefault();
private Calendar selectedDate;
private Calendar shownMonth;
private DateSelectionListener listener = null;
//temporary and cache values
private int _cachedCellSideWidth = 0;
private int _cachedCellSideHeight = 0;
private Calendar _calendar = Calendar.getInstance();
private Rect _rect = new Rect();
private float _textHeight = 0;
private float _x;
private float _y;
private Typeface _boldTypeface;
private Typeface _defaultTypeface;
public interface DateSelectionListener {
void onDateSelected(Calendar selectedDate);
}
public static class CalendarDayCellCoord {
public int col;
public int row;
public CalendarDayCellCoord(int col, int row) {
this.col = col;
this.row = row;
}
}
public CalendarNumbersView(Context context) {
super(context);
init(null);
}
public CalendarNumbersView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public CalendarNumbersView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
private void init(AttributeSet attrs) {
paint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG);
paint.setTextSize(getResources().getDimensionPixelSize(R.dimen.calendar_default_text_size));
textColor = getResources().getColor(R.color.calendar_default_text_color);
inactiveTextColor = getResources().getColor(R.color.calendar_default_inactive_text_color);
selectionTextColor = getResources().getColor(R.color.calendar_default_selection_text_color);
cellPadding = getResources().getDimensionPixelSize(R.dimen.calendar_default_cell_padding);
cellBackgroundColor = getResources().getColor(R.color.calendar_default_cell_background_color);
//cellSelectionBackgroundColor = getResources().getColor(R.color.calendar_default_cell_selection_background_color);
dayNamesTextColor = getResources().getColor(R.color.calendar_default_day_names_cell_text_color);
dayNamesBackgroundColor = getResources().getColor(R.color.calendar_default_day_names_cell_background_color);
TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.CalendarNumbersView);
if (ta != null) {
paint.setTextSize(ta.getDimensionPixelSize(R.styleable.CalendarNumbersView_fontSize, (int) paint.getTextSize()));
textColor = ta.getColor(R.styleable.CalendarNumbersView_textColor, textColor);
inactiveTextColor = ta.getColor(R.styleable.CalendarNumbersView_inactiveTextColor, inactiveTextColor);
selectionTextColor = ta.getColor(R.styleable.CalendarNumbersView_selectionTextColor, selectionTextColor);
cellPadding = ta.getDimensionPixelSize(R.styleable.CalendarNumbersView_cellPadding, cellPadding);
cellBackgroundColor = ta.getColor(R.styleable.CalendarNumbersView_cellBackgroundColor, cellBackgroundColor);
cellSelectionBackgroundColor = ta.getColor(R.styleable.CalendarNumbersView_cellSelectionBackgroundColor, cellSelectionBackgroundColor);
dayNamesTextColor = ta.getColor(R.styleable.CalendarNumbersView_cellDayNamesCellTextColor, dayNamesTextColor);
dayNamesBackgroundColor = ta.getColor(R.styleable.CalendarNumbersView_cellDayNamesCellBackgroundColor, dayNamesBackgroundColor);
}
selectedDate = Calendar.getInstance();
shownMonth = (Calendar) selectedDate.clone();
}
public int calculateQuadCellSideWidth() {
Rect bounds = new Rect();
String str = "WW";//widest possible cell string
paint.getTextBounds(str, 0, str.length(), bounds);
int maxWidth = bounds.width();
int maxHeight = bounds.height();
_textHeight = bounds.height();
return Math.max(maxWidth, maxHeight) + cellPadding * 2;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int quadCellSideWidth = calculateQuadCellSideWidth();
int calculatedWidth = quadCellSideWidth * shownMonth.getActualMaximum(Calendar.DAY_OF_WEEK) + getPaddingLeft() + getPaddingRight();
int calculatedHeight = quadCellSideWidth * MAX_WEEKS_IN_MONTH + getPaddingTop() + getPaddingBottom();
if (showDayNames) {
calculatedHeight += quadCellSideWidth;
}
int minimumWidth = Math.max(getSuggestedMinimumWidth(), calculatedWidth);
int minimumHeight = Math.max(getSuggestedMinimumHeight(), calculatedHeight);
int width = chooseSize(minimumWidth, widthMeasureSpec);
int height = chooseSize(minimumHeight, heightMeasureSpec);
setMeasuredDimension(width, height);
}
public int chooseSize(int size, int measureSpec) {
int result = size;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
case MeasureSpec.AT_MOST:
result = size;
break;
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
_cachedCellSideWidth = (w - getPaddingRight() - getPaddingLeft()) / shownMonth.getActualMaximum(Calendar.DAY_OF_WEEK);
_cachedCellSideHeight = (h - getPaddingTop() - getPaddingBottom()) / MAX_WEEKS_IN_MONTH;
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (showDayNames) {
setCalendarToFirstVisibleDay(_calendar);
DateFormatSymbols symbols = new DateFormatSymbols(locale);
for (int col = 0; col < _calendar.getActualMaximum(Calendar.DAY_OF_WEEK); col++) {
String str = _calendar.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.SHORT, locale);
String name = str.substring(0, str.length() - 1);
drawCell(canvas, -1, col, dayNamesTextColor, dayNamesBackgroundColor, name, true);
_calendar.add(Calendar.DAY_OF_MONTH, 1);
}
}
setCalendarToFirstVisibleDay(_calendar);
for (int row = 0; row < MAX_WEEKS_IN_MONTH; row++) {
for (int col = 0; col < _calendar.getActualMaximum(Calendar.DAY_OF_WEEK); col++) {
int textColor;
int backgroundColor;
if (_calendar.get(Calendar.DAY_OF_YEAR) == selectedDate.get(Calendar.DAY_OF_YEAR) &&
_calendar.get(Calendar.YEAR) == selectedDate.get(Calendar.YEAR)) {
textColor = selectionTextColor;
backgroundColor = cellSelectionBackgroundColor;
} else {
if (_calendar.get(Calendar.MONTH) == shownMonth.get(Calendar.MONTH)) {
textColor = this.textColor;
} else {
textColor = inactiveTextColor;
}
backgroundColor = cellBackgroundColor;
}
int day = _calendar.get(Calendar.DAY_OF_MONTH);
String str = Integer.toString(day);
drawCell(canvas, row, col, textColor, backgroundColor, str, false);
_calendar.add(Calendar.DAY_OF_MONTH, 1);
}
}
}
private void drawCell(Canvas canvas, int row, int col, int textColor, int backgroundColor, String str, boolean bold) {
getRectForCell(col, row, _rect);
paint.setColor(backgroundColor);
_rect.inset(cellPadding, cellPadding);
canvas.drawRect(_rect, paint);
_rect.inset(-cellPadding, -cellPadding);
paint.setColor(textColor);
if (bold) {
if (_boldTypeface == null) {
_boldTypeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD);
}
paint.setTypeface(_boldTypeface);
} else {
if (_defaultTypeface == null) {
_defaultTypeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL);
}
paint.setTypeface(_defaultTypeface);
}
paint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(str,
_rect.left + _cachedCellSideWidth / 2f,
_rect.top + _cachedCellSideHeight / 2f + _textHeight / 2f - paint.getFontMetrics().descent / 2,
paint);
}
private void setCalendarToFirstVisibleDay(Calendar calendar) {
calendar.setTime(shownMonth.getTime());
calendar.set(Calendar.DAY_OF_MONTH, 1);
int firstDayInWeek = calendar.getFirstDayOfWeek();
int firstDayOfWeekOfCurrentMonth = calendar.get(Calendar.DAY_OF_WEEK);
int shift;
if (firstDayInWeek > firstDayOfWeekOfCurrentMonth) {
shift = -(firstDayOfWeekOfCurrentMonth + calendar.getActualMaximum(Calendar.DAY_OF_WEEK) - firstDayInWeek);
} else {
shift = -(firstDayOfWeekOfCurrentMonth - firstDayInWeek);
}
calendar.add(Calendar.DAY_OF_MONTH, shift);
}
private void getRectForCell(int col, int row, Rect outRect) {
if (showDayNames) {
row++;
}
outRect.set(getPaddingLeft() + col * _cachedCellSideWidth,
getPaddingTop() + row * _cachedCellSideHeight,
getPaddingLeft() + col * _cachedCellSideWidth + _cachedCellSideWidth,
getPaddingTop() + row * _cachedCellSideHeight + _cachedCellSideHeight);
}
private CalendarDayCellCoord getCellForCoords(float x, float y) {
if (x < getPaddingLeft() ||
x >= getWidth() - getPaddingRight() ||
y < getPaddingTop() ||
y >= getHeight() - getPaddingBottom()) {
return null;
}
CalendarDayCellCoord coord = new CalendarDayCellCoord(
(int) (x - getPaddingLeft()) / _cachedCellSideWidth,
(int) (y - getPaddingTop()) / _cachedCellSideHeight
);
if (showDayNames) {
coord.row--;
if (coord.row < 0) {
return null;
}
}
return coord;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
_x = event.getX();
_y = event.getY();
return true;
case MotionEvent.ACTION_UP:
float x = event.getX();
float y = event.getY();
if (Math.sqrt(Math.pow(x - _x, 2) + Math.pow(y - _y, 2)) <= MAX_SELECTION_FINGER_SHIFT_DIST) {
selectDayAt(x, y);
}
return true;
default:
return super.onTouchEvent(event);
}
}
private void selectDayAt(float x, float y) {
CalendarDayCellCoord cellCoords = getCellForCoords(x, y);
if (cellCoords == null) {
return;
}
setCalendarToFirstVisibleDay(_calendar);
_calendar.add(Calendar.DAY_OF_YEAR, cellCoords.col);
_calendar.add(Calendar.WEEK_OF_MONTH, cellCoords.row);
selectedDate.setTime(_calendar.getTime());
if (listener != null) {
listener.onDateSelected(selectedDate);
}
invalidate();
}
public int getCellBackgroundColor() {
return cellBackgroundColor;
}
public void setCellBackgroundColor(int cellBackgroundColor) {
this.cellBackgroundColor = cellBackgroundColor;
invalidate();
}
public int getCellPadding() {
return cellPadding;
}
public void setCellPadding(int cellPadding) {
this.cellPadding = cellPadding;
invalidate();
}
public int getCellSelectionBackgroundColor() {
return cellSelectionBackgroundColor;
}
public void setCellSelectionBackgroundColor(int cellSelectionBackgroundColor) {
this.cellSelectionBackgroundColor = cellSelectionBackgroundColor;
invalidate();
}
public int getInactiveTextColor() {
return inactiveTextColor;
}
public void setInactiveTextColor(int inactiveTextColor) {
this.inactiveTextColor = inactiveTextColor;
invalidate();
}
public DateSelectionListener getListener() {
return listener;
}
public void setListener(DateSelectionListener listener) {
this.listener = listener;
}
public Calendar getSelectedDate() {
return selectedDate;
}
public void setSelectedDate(Calendar selectedDate) {
this.selectedDate = selectedDate;
invalidate();
}
public int getSelectionTextColor() {
return selectionTextColor;
}
public void setSelectionTextColor(int selectionTextColor) {
this.selectionTextColor = selectionTextColor;
invalidate();
}
public int getTextColor() {
return textColor;
}
public void setTextColor(int textColor) {
this.textColor = textColor;
invalidate();
}
public Calendar getShownMonth() {
return shownMonth;
}
public void setShownMonth(Calendar shownMonth) {
this.shownMonth = shownMonth;
invalidate();
}
public boolean isShowDayNames() {
return showDayNames;
}
public void setShowDayNames(boolean showDayNames) {
this.showDayNames = showDayNames;
invalidate();
}
public Locale getLocale() {
return locale;
}
public void setLocale(Locale locale) {
this.locale = locale;
invalidate();
}
public int getDayNamesBackgroundColor() {
return dayNamesBackgroundColor;
}
public void setDayNamesBackgroundColor(int dayNamesBackgroundColor) {
this.dayNamesBackgroundColor = dayNamesBackgroundColor;
invalidate();
}
public int getDayNamesTextColor() {
return dayNamesTextColor;
}
public void setDayNamesTextColor(int dayNamesTextColor) {
this.dayNamesTextColor = dayNamesTextColor;
invalidate();
}
}
我的输出:
必填项: (您可以看到隐藏7月日期的位置)
答案 0 :(得分:1)
您可以通过更改onDraw
的{{1}}来实现此目的:
1:只需将CalendarNumbersView
文字颜色改为透明,如
inactiveTextColor
到
textColor = inactiveTextColor;
OR
2:在获得日期值之前,在textColor = Color.parseColor("#FFFFFFFF");
方法中添加条件,如下所示。
onDraw