如何通过不在今天的月份自定义日历中显示以前的日期来禁用?

时间:2017-12-19 08:29:20

标签: java android android-calendar android-datepicker android-date

我使用自定义日历显示月份和日期。一切正常,但要求是,我不应该在当前日历中显示过去的日期。 例如:如果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();
    }
} 

我的输出:

enter image description here

必填项: (您可以看到隐藏7月日期的位置)

enter image description here

1 个答案:

答案 0 :(得分:1)

您可以通过更改onDraw的{​​{1}}来实现此目的:

1:只需将CalendarNumbersView文字颜色改为透明,如

inactiveTextColor

textColor = inactiveTextColor;

OR

2:在获得日期值之前,在textColor = Color.parseColor("#FFFFFFFF");方法中添加条件,如下所示。

onDraw