List<List<MonthCellDescriptor>> getMonthCells(MonthDescriptor month, Calendar startCal) { Calendar cal = Calendar.getInstance(locale); cal.setTime(startCal.getTime()); List<List<MonthCellDescriptor>> cells = new ArrayList<List<MonthCellDescriptor>>(); cal.set(DAY_OF_MONTH, 1); int firstDayOfWeek = cal.get(DAY_OF_WEEK); int offset = cal.getFirstDayOfWeek() - firstDayOfWeek; if (offset > 0) { offset -= 7; } cal.add(Calendar.DATE, offset); Calendar minSelectedCal = minDate(selectedCals); Calendar maxSelectedCal = maxDate(selectedCals); while ((cal.get(MONTH) < month.getMonth() + 1 || cal.get(YEAR) < month.getYear()) // && cal.get(YEAR) <= month.getYear()) { Logr.d("Building week row starting at %s", cal.getTime()); List<MonthCellDescriptor> weekCells = new ArrayList<MonthCellDescriptor>(); cells.add(weekCells); for (int c = 0; c < 7; c++) { Date date = cal.getTime(); boolean isCurrentMonth = cal.get(MONTH) == month.getMonth(); boolean isSelected = isCurrentMonth && containsDate(selectedCals, cal); boolean isSelectable = isCurrentMonth && betweenDates(cal, minCal, maxCal) && isDateSelectable(date); boolean isToday = sameDate(cal, today); boolean isHighlighted = containsDate(highlightedCals, cal); int value = cal.get(DAY_OF_MONTH); MonthCellDescriptor.RangeState rangeState = MonthCellDescriptor.RangeState.NONE; if (selectedCals.size() > 1) { if (sameDate(minSelectedCal, cal)) { rangeState = MonthCellDescriptor.RangeState.FIRST; } else if (sameDate(maxDate(selectedCals), cal)) { rangeState = MonthCellDescriptor.RangeState.LAST; } else if (betweenDates(cal, minSelectedCal, maxSelectedCal)) { rangeState = MonthCellDescriptor.RangeState.MIDDLE; } } weekCells.add( new MonthCellDescriptor( date, isCurrentMonth, isSelectable, isSelected, isToday, isHighlighted, value, rangeState)); cal.add(DATE, 1); } } return cells; }
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { Logr.d( "Grid.onMeasure w=%s h=%s", MeasureSpec.toString(widthMeasureSpec), MeasureSpec.toString(heightMeasureSpec)); int widthMeasureSize = MeasureSpec.getSize(widthMeasureSpec); if (oldWidthMeasureSize == widthMeasureSize) { Logr.d("SKIP Grid.onMeasure"); setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight()); return; } long start = System.currentTimeMillis(); oldWidthMeasureSize = widthMeasureSize; int cellSize = widthMeasureSize / 7; // Remove any extra pixels since /7 is unlikely to give whole nums. widthMeasureSize = cellSize * 7; int totalHeight = 0; final int rowWidthSpec = makeMeasureSpec(widthMeasureSize, EXACTLY); final int rowHeightSpec = makeMeasureSpec(cellSize, EXACTLY); for (int c = 0, numChildren = getChildCount(); c < numChildren; c++) { final View child = getChildAt(c); if (child.getVisibility() == View.VISIBLE) { if (c == 0) { // It's the header: height should be wrap_content. measureChild(child, rowWidthSpec, makeMeasureSpec(cellSize, AT_MOST)); } else { measureChild(child, rowWidthSpec, rowHeightSpec); } totalHeight += child.getMeasuredHeight(); } } final int measuredWidth = widthMeasureSize + 2; // Fudge factor to make the borders show up. setMeasuredDimension(measuredWidth, totalHeight); Logr.d("Grid.onMeasure %d ms", System.currentTimeMillis() - start); }
/** * This method should only be called if the calendar is contained in a dialog, and it should only * be called when the screen has been rotated and the dialog should be re-measured. */ public void unfixDialogDimens() { Logr.d("Reset the fixed dimensions to allow for re-measurement"); // Fix the layout height/width after the dialog has been shown. getLayoutParams().height = LayoutParams.MATCH_PARENT; getLayoutParams().width = LayoutParams.MATCH_PARENT; requestLayout(); }
@Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { long start = System.currentTimeMillis(); int cellHeight = bottom - top; for (int c = 0, numChildren = getChildCount(); c < numChildren; c++) { final View child = getChildAt(c); child.layout(c * cellSize, 0, (c + 1) * cellSize, cellHeight); } Logr.d("Row.onLayout %d ms", System.currentTimeMillis() - start); }
@Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { long start = System.currentTimeMillis(); top = 0; for (int c = 0, numChildren = getChildCount(); c < numChildren; c++) { final View child = getChildAt(c); final int rowHeight = child.getMeasuredHeight(); child.layout(left, top, right, top + rowHeight); top += rowHeight; } Logr.d("Grid.onLayout %d ms", System.currentTimeMillis() - start); }
/** * This method should only be called if the calendar is contained in a dialog, and it should only * be called once, right after the dialog is shown (using {@link * android.content.DialogInterface.OnShowListener} or {@link * android.app.DialogFragment#onStart()}). */ public void fixDialogDimens() { Logr.d("Fixing dimensions to h = %d / w = %d", getMeasuredHeight(), getMeasuredWidth()); // Fix the layout height/width after the dialog has been shown. getLayoutParams().height = getMeasuredHeight(); getLayoutParams().width = getMeasuredWidth(); // Post this runnable so it runs _after_ the dimen changes have been // applied/re-measured. post( new Runnable() { @Override public void run() { Logr.d("Dimens are fixed: now scroll to the selected date"); scrollToSelectedDates(); } }); }
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { long start = System.currentTimeMillis(); final int totalWidth = MeasureSpec.getSize(widthMeasureSpec); cellSize = totalWidth / 7; int cellWidthSpec = makeMeasureSpec(cellSize, EXACTLY); int cellHeightSpec = isHeaderRow ? makeMeasureSpec(cellSize, AT_MOST) : cellWidthSpec; int rowHeight = 0; for (int c = 0, numChildren = getChildCount(); c < numChildren; c++) { final View child = getChildAt(c); child.measure(cellWidthSpec, cellHeightSpec); // The row height is the height of the tallest cell. if (child.getMeasuredHeight() > rowHeight) { rowHeight = child.getMeasuredHeight(); } } final int widthWithPadding = totalWidth + getPaddingLeft() + getPaddingRight(); final int heightWithPadding = rowHeight + getPaddingTop() + getPaddingBottom(); setMeasuredDimension(widthWithPadding, heightWithPadding); Logr.d("Row.onMeasure %d ms", System.currentTimeMillis() - start); }