FileDocCategorySizeDatePackage
SimpleMonthView.javaAPI DocAndroid 5.1 API24989Thu Mar 12 22:22:10 GMT 2015android.widget

SimpleMonthView

public class SimpleMonthView extends android.view.View
A calendar-like view displaying a specified month and the appropriate selectable day numbers within the specified month.

Fields Summary
private static final int
DEFAULT_HEIGHT
private static final int
MIN_HEIGHT
private static final int
DEFAULT_SELECTED_DAY
private static final int
DEFAULT_WEEK_START
private static final int
DEFAULT_NUM_DAYS
private static final int
DEFAULT_NUM_ROWS
private static final int
MAX_NUM_ROWS
private static final int
SELECTED_CIRCLE_ALPHA
private static final int
DAY_SEPARATOR_WIDTH
private final Formatter
mFormatter
private final StringBuilder
mStringBuilder
private final int
mMiniDayNumberTextSize
private final int
mMonthLabelTextSize
private final int
mMonthDayLabelTextSize
private final int
mMonthHeaderSize
private final int
mDaySelectedCircleSize
private SimpleDateFormat
mDayFormatter
Single-letter (when available) formatter for the day of week label.
private int
mPadding
private String
mDayOfWeekTypeface
private String
mMonthTitleTypeface
private android.graphics.Paint
mDayNumberPaint
private android.graphics.Paint
mDayNumberDisabledPaint
private android.graphics.Paint
mDayNumberSelectedPaint
private android.graphics.Paint
mMonthTitlePaint
private android.graphics.Paint
mMonthDayLabelPaint
private int
mMonth
private int
mYear
private int
mWidth
private int
mRowHeight
private boolean
mHasToday
private int
mSelectedDay
private int
mToday
private int
mWeekStart
private int
mNumDays
private int
mNumCells
private int
mDayOfWeekStart
private int
mEnabledDayStart
private int
mEnabledDayEnd
private final Calendar
mCalendar
private final Calendar
mDayLabelCalendar
private final MonthViewTouchHelper
mTouchHelper
private int
mNumRows
private OnDayClickListener
mOnDayClickListener
private boolean
mLockAccessibilityDelegate
private int
mNormalTextColor
private int
mDisabledTextColor
private int
mSelectedDayColor
Constructors Summary
public SimpleMonthView(android.content.Context context)


       
        this(context, null);
    
public SimpleMonthView(android.content.Context context, android.util.AttributeSet attrs)

        this(context, attrs, R.attr.datePickerStyle);
    
public SimpleMonthView(android.content.Context context, android.util.AttributeSet attrs, int defStyleAttr)

        this(context, attrs, defStyleAttr, 0);
    
public SimpleMonthView(android.content.Context context, android.util.AttributeSet attrs, int defStyleAttr, int defStyleRes)

        super(context, attrs, defStyleAttr, defStyleRes);

        final Resources res = context.getResources();
        mDayOfWeekTypeface = res.getString(R.string.day_of_week_label_typeface);
        mMonthTitleTypeface = res.getString(R.string.sans_serif);

        mStringBuilder = new StringBuilder(50);
        mFormatter = new Formatter(mStringBuilder, Locale.getDefault());

        mMiniDayNumberTextSize = res.getDimensionPixelSize(R.dimen.datepicker_day_number_size);
        mMonthLabelTextSize = res.getDimensionPixelSize(R.dimen.datepicker_month_label_size);
        mMonthDayLabelTextSize = res.getDimensionPixelSize(
                R.dimen.datepicker_month_day_label_text_size);
        mMonthHeaderSize = res.getDimensionPixelOffset(
                R.dimen.datepicker_month_list_item_header_height);
        mDaySelectedCircleSize = res.getDimensionPixelSize(
                R.dimen.datepicker_day_number_select_circle_radius);

        mRowHeight = (res.getDimensionPixelOffset(R.dimen.datepicker_view_animator_height)
                - mMonthHeaderSize) / MAX_NUM_ROWS;

        // Set up accessibility components.
        mTouchHelper = new MonthViewTouchHelper(this);
        setAccessibilityDelegate(mTouchHelper);
        setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
        mLockAccessibilityDelegate = true;

        // Sets up any standard paints that will be used
        initView();
    
Methods Summary
private intcalculateNumRows()

        int offset = findDayOffset();
        int dividend = (offset + mNumCells) / mNumDays;
        int remainder = (offset + mNumCells) % mNumDays;
        return (dividend + (remainder > 0 ? 1 : 0));
    
public voidclearAccessibilityFocus()
Clears accessibility focus within the view. No-op if the view does not contain accessibility focus.

        mTouchHelper.clearFocusedVirtualView();
    
public booleandispatchHoverEvent(android.view.MotionEvent event)

        // First right-of-refusal goes the touch exploration helper.
        if (mTouchHelper.dispatchHoverEvent(event)) {
            return true;
        }
        return super.dispatchHoverEvent(event);
    
private voiddrawDays(android.graphics.Canvas canvas)
Draws the month days.

        int y = (((mRowHeight + mMiniDayNumberTextSize) / 2) - DAY_SEPARATOR_WIDTH)
                + mMonthHeaderSize;
        int dayWidthHalf = (mWidth - mPadding * 2) / (mNumDays * 2);
        int j = findDayOffset();
        for (int day = 1; day <= mNumCells; day++) {
            int x = (2 * j + 1) * dayWidthHalf + mPadding;
            if (mSelectedDay == day) {
                canvas.drawCircle(x, y - (mMiniDayNumberTextSize / 3), mDaySelectedCircleSize,
                        mDayNumberSelectedPaint);
            }

            if (mHasToday && mToday == day) {
                mDayNumberPaint.setColor(mSelectedDayColor);
            } else {
                mDayNumberPaint.setColor(mNormalTextColor);
            }
            final Paint paint = (day < mEnabledDayStart || day > mEnabledDayEnd) ?
                    mDayNumberDisabledPaint : mDayNumberPaint;
            canvas.drawText(String.format("%d", day), x, y, paint);
            j++;
            if (j == mNumDays) {
                j = 0;
                y += mRowHeight;
            }
        }
    
private voiddrawMonthTitle(android.graphics.Canvas canvas)

        final float x = (mWidth + 2 * mPadding) / 2f;
        final float y = (mMonthHeaderSize - mMonthDayLabelTextSize) / 2f;
        canvas.drawText(getMonthAndYearString(), x, y, mMonthTitlePaint);
    
private voiddrawWeekDayLabels(android.graphics.Canvas canvas)

        final int y = mMonthHeaderSize - (mMonthDayLabelTextSize / 2);
        final int dayWidthHalf = (mWidth - mPadding * 2) / (mNumDays * 2);

        for (int i = 0; i < mNumDays; i++) {
            final int calendarDay = (i + mWeekStart) % mNumDays;
            mDayLabelCalendar.set(Calendar.DAY_OF_WEEK, calendarDay);

            final String dayLabel = mDayFormatter.format(mDayLabelCalendar.getTime());
            final int x = (2 * i + 1) * dayWidthHalf + mPadding;
            canvas.drawText(dayLabel, x, y, mMonthDayLabelPaint);
        }
    
private intfindDayOffset()

        return (mDayOfWeekStart < mWeekStart ? (mDayOfWeekStart + mNumDays) : mDayOfWeekStart)
                - mWeekStart;
    
java.util.CalendargetAccessibilityFocus()

return
The date that has accessibility focus, or {@code null} if no date has focus

        final int day = mTouchHelper.getFocusedVirtualView();
        Calendar date = null;
        if (day >= 0) {
            date = Calendar.getInstance();
            date.set(mYear, mMonth, day);
        }
        return date;
    
private intgetDayFromLocation(float x, float y)
Calculates the day that the given x position is in, accounting for week number. Returns the day or -1 if the position wasn't in a day.

param
x The x position of the touch event
return
The day number, or -1 if the position wasn't in a day

        int dayStart = mPadding;
        if (x < dayStart || x > mWidth - mPadding) {
            return -1;
        }
        // Selection is (x - start) / (pixels/day) == (x -s) * day / pixels
        int row = (int) (y - mMonthHeaderSize) / mRowHeight;
        int column = (int) ((x - dayStart) * mNumDays / (mWidth - dayStart - mPadding));

        int day = column - findDayOffset() + 1;
        day += row * mNumDays;
        if (day < 1 || day > mNumCells) {
            return -1;
        }
        return day;
    
private static intgetDaysInMonth(int month, int year)

        switch (month) {
            case Calendar.JANUARY:
            case Calendar.MARCH:
            case Calendar.MAY:
            case Calendar.JULY:
            case Calendar.AUGUST:
            case Calendar.OCTOBER:
            case Calendar.DECEMBER:
                return 31;
            case Calendar.APRIL:
            case Calendar.JUNE:
            case Calendar.SEPTEMBER:
            case Calendar.NOVEMBER:
                return 30;
            case Calendar.FEBRUARY:
                return (year % 4 == 0) ? 29 : 28;
            default:
                throw new IllegalArgumentException("Invalid Month");
        }
    
private java.lang.StringgetMonthAndYearString()

        int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR
                | DateUtils.FORMAT_NO_MONTH_DAY;
        mStringBuilder.setLength(0);
        long millis = mCalendar.getTimeInMillis();
        return DateUtils.formatDateRange(getContext(), mFormatter, millis, millis, flags,
                Time.getCurrentTimezone()).toString();
    
private voidinitView()
Sets up the text and style properties for painting.

        mMonthTitlePaint = new Paint();
        mMonthTitlePaint.setAntiAlias(true);
        mMonthTitlePaint.setColor(mNormalTextColor);
        mMonthTitlePaint.setTextSize(mMonthLabelTextSize);
        mMonthTitlePaint.setTypeface(Typeface.create(mMonthTitleTypeface, Typeface.BOLD));
        mMonthTitlePaint.setTextAlign(Align.CENTER);
        mMonthTitlePaint.setStyle(Style.FILL);
        mMonthTitlePaint.setFakeBoldText(true);

        mMonthDayLabelPaint = new Paint();
        mMonthDayLabelPaint.setAntiAlias(true);
        mMonthDayLabelPaint.setColor(mNormalTextColor);
        mMonthDayLabelPaint.setTextSize(mMonthDayLabelTextSize);
        mMonthDayLabelPaint.setTypeface(Typeface.create(mDayOfWeekTypeface, Typeface.NORMAL));
        mMonthDayLabelPaint.setTextAlign(Align.CENTER);
        mMonthDayLabelPaint.setStyle(Style.FILL);
        mMonthDayLabelPaint.setFakeBoldText(true);

        mDayNumberSelectedPaint = new Paint();
        mDayNumberSelectedPaint.setAntiAlias(true);
        mDayNumberSelectedPaint.setColor(mSelectedDayColor);
        mDayNumberSelectedPaint.setAlpha(SELECTED_CIRCLE_ALPHA);
        mDayNumberSelectedPaint.setTextAlign(Align.CENTER);
        mDayNumberSelectedPaint.setStyle(Style.FILL);
        mDayNumberSelectedPaint.setFakeBoldText(true);

        mDayNumberPaint = new Paint();
        mDayNumberPaint.setAntiAlias(true);
        mDayNumberPaint.setTextSize(mMiniDayNumberTextSize);
        mDayNumberPaint.setTextAlign(Align.CENTER);
        mDayNumberPaint.setStyle(Style.FILL);
        mDayNumberPaint.setFakeBoldText(false);

        mDayNumberDisabledPaint = new Paint();
        mDayNumberDisabledPaint.setAntiAlias(true);
        mDayNumberDisabledPaint.setColor(mDisabledTextColor);
        mDayNumberDisabledPaint.setTextSize(mMiniDayNumberTextSize);
        mDayNumberDisabledPaint.setTextAlign(Align.CENTER);
        mDayNumberDisabledPaint.setStyle(Style.FILL);
        mDayNumberDisabledPaint.setFakeBoldText(false);
    
private static booleanisValidDayOfWeek(int day)

        return day >= Calendar.SUNDAY && day <= Calendar.SATURDAY;
    
private static booleanisValidMonth(int month)

        return month >= Calendar.JANUARY && month <= Calendar.DECEMBER;
    
protected voidonConfigurationChanged(android.content.res.Configuration newConfig)

        super.onConfigurationChanged(newConfig);

        mDayFormatter = new SimpleDateFormat("EEEEE", newConfig.locale);
    
private voidonDayClick(int day)
Called when the user clicks on a day. Handles callbacks to the {@link OnDayClickListener} if one is set.

param
day The day that was clicked

        if (mOnDayClickListener != null) {
            Calendar date = Calendar.getInstance();
            date.set(mYear, mMonth, day);
            mOnDayClickListener.onDayClick(this, date);
        }

        // This is a no-op if accessibility is turned off.
        mTouchHelper.sendEventForVirtualView(day, AccessibilityEvent.TYPE_VIEW_CLICKED);
    
protected voidonDraw(android.graphics.Canvas canvas)

        drawMonthTitle(canvas);
        drawWeekDayLabels(canvas);
        drawDays(canvas);
    
protected voidonMeasure(int widthMeasureSpec, int heightMeasureSpec)

        setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), mRowHeight * mNumRows
                + mMonthHeaderSize);
    
protected voidonSizeChanged(int w, int h, int oldw, int oldh)

        mWidth = w;

        // Invalidate cached accessibility information.
        mTouchHelper.invalidateRoot();
    
public booleanonTouchEvent(android.view.MotionEvent event)

        switch (event.getAction()) {
            case MotionEvent.ACTION_UP:
                final int day = getDayFromLocation(event.getX(), event.getY());
                if (day >= 0) {
                    onDayClick(day);
                }
                break;
        }
        return true;
    
booleanrestoreAccessibilityFocus(java.util.Calendar day)
Attempts to restore accessibility focus to the specified date.

param
day The date which should receive focus
return
{@code false} if the date is not valid for this month view, or {@code true} if the date received focus

        if ((day.get(Calendar.YEAR) != mYear) || (day.get(Calendar.MONTH) != mMonth) ||
                (day.get(Calendar.DAY_OF_MONTH) > mNumCells)) {
            return false;
        }
        mTouchHelper.setFocusedVirtualView(day.get(Calendar.DAY_OF_MONTH));
        return true;
    
public voidreuse()

        mNumRows = DEFAULT_NUM_ROWS;
        requestLayout();
    
private booleansameDay(int day, android.text.format.Time today)

        return mYear == today.year &&
                mMonth == today.month &&
                day == today.monthDay;
    
public voidsetAccessibilityDelegate(AccessibilityDelegate delegate)

        // Workaround for a JB MR1 issue where accessibility delegates on
        // top-level ListView items are overwritten.
        if (!mLockAccessibilityDelegate) {
            super.setAccessibilityDelegate(delegate);
        }
    
voidsetMonthParams(int selectedDay, int month, int year, int weekStart, int enabledDayStart, int enabledDayEnd)
Sets all the parameters for displaying this week. Parameters have a default value and will only update if a new value is included, except for focus month, which will always default to no focus month if no value is passed in. The only required parameter is the week start.

param
selectedDay the selected day of the month, or -1 for no selection.
param
month the month.
param
year the year.
param
weekStart which day the week should start on. {@link Calendar#SUNDAY} through {@link Calendar#SATURDAY}.
param
enabledDayStart the first enabled day.
param
enabledDayEnd the last enabled day.

        if (mRowHeight < MIN_HEIGHT) {
            mRowHeight = MIN_HEIGHT;
        }

        mSelectedDay = selectedDay;

        if (isValidMonth(month)) {
            mMonth = month;
        }
        mYear = year;

        // Figure out what day today is
        final Time today = new Time(Time.getCurrentTimezone());
        today.setToNow();
        mHasToday = false;
        mToday = -1;

        mCalendar.set(Calendar.MONTH, mMonth);
        mCalendar.set(Calendar.YEAR, mYear);
        mCalendar.set(Calendar.DAY_OF_MONTH, 1);
        mDayOfWeekStart = mCalendar.get(Calendar.DAY_OF_WEEK);

        if (isValidDayOfWeek(weekStart)) {
            mWeekStart = weekStart;
        } else {
            mWeekStart = mCalendar.getFirstDayOfWeek();
        }

        if (enabledDayStart > 0 && enabledDayEnd < 32) {
            mEnabledDayStart = enabledDayStart;
        }
        if (enabledDayEnd > 0 && enabledDayEnd < 32 && enabledDayEnd >= enabledDayStart) {
            mEnabledDayEnd = enabledDayEnd;
        }

        mNumCells = getDaysInMonth(mMonth, mYear);
        for (int i = 0; i < mNumCells; i++) {
            final int day = i + 1;
            if (sameDay(day, today)) {
                mHasToday = true;
                mToday = day;
            }
        }
        mNumRows = calculateNumRows();

        // Invalidate cached accessibility information.
        mTouchHelper.invalidateRoot();
    
public voidsetOnDayClickListener(android.widget.SimpleMonthView$OnDayClickListener listener)

        mOnDayClickListener = listener;
    
voidsetTextColor(android.content.res.ColorStateList colors)

        final Resources res = getContext().getResources();

        mNormalTextColor = colors.getColorForState(ENABLED_STATE_SET,
                res.getColor(R.color.datepicker_default_normal_text_color_holo_light));
        mMonthTitlePaint.setColor(mNormalTextColor);
        mMonthDayLabelPaint.setColor(mNormalTextColor);

        mDisabledTextColor = colors.getColorForState(EMPTY_STATE_SET,
                res.getColor(R.color.datepicker_default_disabled_text_color_holo_light));
        mDayNumberDisabledPaint.setColor(mDisabledTextColor);

        mSelectedDayColor = colors.getColorForState(ENABLED_SELECTED_STATE_SET,
                res.getColor(R.color.holo_blue_light));
        mDayNumberSelectedPaint.setColor(mSelectedDayColor);
        mDayNumberSelectedPaint.setAlpha(SELECTED_CIRCLE_ALPHA);