DayPickerView.java revision 816aa142023c75cf427401c21831193998bdf233
1bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio/* 2bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * Copyright (C) 2014 The Android Open Source Project 3bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * 4bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * Licensed under the Apache License, Version 2.0 (the "License"); 5bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * you may not use this file except in compliance with the License. 6bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * You may obtain a copy of the License at 7bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * 8bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * http://www.apache.org/licenses/LICENSE-2.0 9bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * 10bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * Unless required by applicable law or agreed to in writing, software 11bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * distributed under the License is distributed on an "AS IS" BASIS, 12bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * See the License for the specific language governing permissions and 14bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * limitations under the License. 15bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio */ 16bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 17bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Megliopackage android.widget; 18bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 190ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport com.android.internal.widget.ViewPager; 200ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport com.android.internal.R; 210ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 22bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.Context; 23bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport android.content.res.ColorStateList; 240ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.content.res.TypedArray; 25816aa142023c75cf427401c21831193998bdf233Alan Viveretteimport android.graphics.drawable.Drawable; 260ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport android.util.AttributeSet; 2750eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viveretteimport android.util.MathUtils; 28816aa142023c75cf427401c21831193998bdf233Alan Viveretteimport android.view.View; 29bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 30816aa142023c75cf427401c21831193998bdf233Alan Viveretteimport java.util.ArrayList; 31bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport java.util.Calendar; 32bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglioimport java.util.Locale; 33bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 340ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteimport libcore.icu.LocaleData; 350ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 36bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio/** 37bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * This displays a list of months in a calendar format with selectable days. 38bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio */ 390ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viveretteclass DayPickerView extends ViewPager { 400ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private static final int DEFAULT_START_YEAR = 1900; 410ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private static final int DEFAULT_END_YEAR = 2100; 42bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 430ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private final Calendar mSelectedDay = Calendar.getInstance(); 440ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private final Calendar mMinDate = Calendar.getInstance(); 450ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private final Calendar mMaxDate = Calendar.getInstance(); 46bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 47816aa142023c75cf427401c21831193998bdf233Alan Viverette private final ArrayList<View> mMatchParentChildren = new ArrayList<>(1); 48816aa142023c75cf427401c21831193998bdf233Alan Viverette 490ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private final DayPickerAdapter mAdapter; 50bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 510ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette /** Temporary calendar used for date calculations. */ 520ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private Calendar mTempCalendar; 53bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 540ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private OnDaySelectedListener mOnDaySelectedListener; 55e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette 560ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette public DayPickerView(Context context) { 570ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette this(context, null); 580ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 59bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 600ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette public DayPickerView(Context context, AttributeSet attrs) { 610ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette this(context, attrs, R.attr.calendarViewStyle); 620ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 63bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 640ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette public DayPickerView(Context context, AttributeSet attrs, int defStyleAttr) { 650ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette this(context, attrs, defStyleAttr, 0); 660ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 6750eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette 680ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette public DayPickerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 690ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette super(context, attrs, defStyleAttr, defStyleRes); 704612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 710ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final TypedArray a = context.obtainStyledAttributes(attrs, 720ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette R.styleable.CalendarView, defStyleAttr, defStyleRes); 73bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 740ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int firstDayOfWeek = a.getInt(R.styleable.CalendarView_firstDayOfWeek, 750ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette LocaleData.get(Locale.getDefault()).firstDayOfWeek); 76bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 770ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final String minDate = a.getString(R.styleable.CalendarView_minDate); 780ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final String maxDate = a.getString(R.styleable.CalendarView_maxDate); 79bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 800ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int monthTextAppearanceResId = a.getResourceId( 810ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette R.styleable.CalendarView_monthTextAppearance, 820ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette R.style.TextAppearance_Material_Widget_Calendar_Month); 830ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int dayOfWeekTextAppearanceResId = a.getResourceId( 840ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette R.styleable.CalendarView_weekDayTextAppearance, 850ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette R.style.TextAppearance_Material_Widget_Calendar_DayOfWeek); 860ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int dayTextAppearanceResId = a.getResourceId( 870ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette R.styleable.CalendarView_dateTextAppearance, 880ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette R.style.TextAppearance_Material_Widget_Calendar_Day); 890ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 900ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final ColorStateList daySelectorColor = a.getColorStateList( 910ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette R.styleable.CalendarView_daySelectorColor); 920ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 930ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette a.recycle(); 940ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 950ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Set up adapter. 9660b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette mAdapter = new DayPickerAdapter(context, 9760b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette R.layout.date_picker_month_item_material, R.id.month_view); 980ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mAdapter.setMonthTextAppearance(monthTextAppearanceResId); 990ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mAdapter.setDayOfWeekTextAppearance(dayOfWeekTextAppearanceResId); 1000ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mAdapter.setDayTextAppearance(dayTextAppearanceResId); 1010ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mAdapter.setDaySelectorColor(daySelectorColor); 10250eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette 103bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio setAdapter(mAdapter); 104e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette 1050ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Set up min and max dates. 1060ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final Calendar tempDate = Calendar.getInstance(); 1070ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (!CalendarView.parseDate(minDate, tempDate)) { 1080ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette tempDate.set(DEFAULT_START_YEAR, Calendar.JANUARY, 1); 1090ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 1100ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final long minDateMillis = tempDate.getTimeInMillis(); 1110ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 1120ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (!CalendarView.parseDate(maxDate, tempDate)) { 1130ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette tempDate.set(DEFAULT_END_YEAR, Calendar.DECEMBER, 31); 1140ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 1150ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final long maxDateMillis = tempDate.getTimeInMillis(); 1160ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 1170ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (maxDateMillis < minDateMillis) { 1180ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette throw new IllegalArgumentException("maxDate must be >= minDate"); 1190ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 1200ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 1210ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final long setDateMillis = MathUtils.constrain( 1220ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette System.currentTimeMillis(), minDateMillis, maxDateMillis); 123e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette 1240ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette setFirstDayOfWeek(firstDayOfWeek); 1250ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette setMinDate(minDateMillis); 1260ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette setMaxDate(maxDateMillis); 1270ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette setDate(setDateMillis, false); 1280ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 1290ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette // Proxy selection callbacks to our own listener. 1300ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mAdapter.setOnDaySelectedListener(new DayPickerAdapter.OnDaySelectedListener() { 1310ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette @Override 1320ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette public void onDaySelected(DayPickerAdapter adapter, Calendar day) { 1330ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (mOnDaySelectedListener != null) { 1340ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mOnDaySelectedListener.onDaySelected(DayPickerView.this, day); 1350ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 1360ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 13760b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette 13860b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette @Override 13960b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette public void onNavigationClick(DayPickerAdapter view, int direction, boolean animate) { 14060b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette // ViewPager clamps input values, so we don't need to worry 14160b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette // about passing invalid indices. 14260b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette final int nextItem = getCurrentItem() + direction; 14360b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette setCurrentItem(nextItem, animate); 14460b674e07bf7346a673abd4a5f40bddeca16e7ffAlan Viverette } 1450ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette }); 1460ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 1470ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 148816aa142023c75cf427401c21831193998bdf233Alan Viverette @Override 149816aa142023c75cf427401c21831193998bdf233Alan Viverette protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 150816aa142023c75cf427401c21831193998bdf233Alan Viverette populate(); 151816aa142023c75cf427401c21831193998bdf233Alan Viverette 152816aa142023c75cf427401c21831193998bdf233Alan Viverette // Everything below is mostly copied from FrameLayout. 153816aa142023c75cf427401c21831193998bdf233Alan Viverette int count = getChildCount(); 154816aa142023c75cf427401c21831193998bdf233Alan Viverette 155816aa142023c75cf427401c21831193998bdf233Alan Viverette final boolean measureMatchParentChildren = 156816aa142023c75cf427401c21831193998bdf233Alan Viverette MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY || 157816aa142023c75cf427401c21831193998bdf233Alan Viverette MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY; 158816aa142023c75cf427401c21831193998bdf233Alan Viverette 159816aa142023c75cf427401c21831193998bdf233Alan Viverette int maxHeight = 0; 160816aa142023c75cf427401c21831193998bdf233Alan Viverette int maxWidth = 0; 161816aa142023c75cf427401c21831193998bdf233Alan Viverette int childState = 0; 162816aa142023c75cf427401c21831193998bdf233Alan Viverette 163816aa142023c75cf427401c21831193998bdf233Alan Viverette for (int i = 0; i < count; i++) { 164816aa142023c75cf427401c21831193998bdf233Alan Viverette final View child = getChildAt(i); 165816aa142023c75cf427401c21831193998bdf233Alan Viverette if (child.getVisibility() != GONE) { 166816aa142023c75cf427401c21831193998bdf233Alan Viverette measureChild(child, widthMeasureSpec, heightMeasureSpec); 167816aa142023c75cf427401c21831193998bdf233Alan Viverette final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 168816aa142023c75cf427401c21831193998bdf233Alan Viverette maxWidth = Math.max(maxWidth, child.getMeasuredWidth()); 169816aa142023c75cf427401c21831193998bdf233Alan Viverette maxHeight = Math.max(maxHeight, child.getMeasuredHeight()); 170816aa142023c75cf427401c21831193998bdf233Alan Viverette childState = combineMeasuredStates(childState, child.getMeasuredState()); 171816aa142023c75cf427401c21831193998bdf233Alan Viverette if (measureMatchParentChildren) { 172816aa142023c75cf427401c21831193998bdf233Alan Viverette if (lp.width == LayoutParams.MATCH_PARENT || 173816aa142023c75cf427401c21831193998bdf233Alan Viverette lp.height == LayoutParams.MATCH_PARENT) { 174816aa142023c75cf427401c21831193998bdf233Alan Viverette mMatchParentChildren.add(child); 175816aa142023c75cf427401c21831193998bdf233Alan Viverette } 176816aa142023c75cf427401c21831193998bdf233Alan Viverette } 177816aa142023c75cf427401c21831193998bdf233Alan Viverette } 178816aa142023c75cf427401c21831193998bdf233Alan Viverette } 179816aa142023c75cf427401c21831193998bdf233Alan Viverette 180816aa142023c75cf427401c21831193998bdf233Alan Viverette // Account for padding too 181816aa142023c75cf427401c21831193998bdf233Alan Viverette maxWidth += getPaddingLeft() + getPaddingRight(); 182816aa142023c75cf427401c21831193998bdf233Alan Viverette maxHeight += getPaddingTop() + getPaddingBottom(); 183816aa142023c75cf427401c21831193998bdf233Alan Viverette 184816aa142023c75cf427401c21831193998bdf233Alan Viverette // Check against our minimum height and width 185816aa142023c75cf427401c21831193998bdf233Alan Viverette maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight()); 186816aa142023c75cf427401c21831193998bdf233Alan Viverette maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth()); 187816aa142023c75cf427401c21831193998bdf233Alan Viverette 188816aa142023c75cf427401c21831193998bdf233Alan Viverette // Check against our foreground's minimum height and width 189816aa142023c75cf427401c21831193998bdf233Alan Viverette final Drawable drawable = getForeground(); 190816aa142023c75cf427401c21831193998bdf233Alan Viverette if (drawable != null) { 191816aa142023c75cf427401c21831193998bdf233Alan Viverette maxHeight = Math.max(maxHeight, drawable.getMinimumHeight()); 192816aa142023c75cf427401c21831193998bdf233Alan Viverette maxWidth = Math.max(maxWidth, drawable.getMinimumWidth()); 193816aa142023c75cf427401c21831193998bdf233Alan Viverette } 194816aa142023c75cf427401c21831193998bdf233Alan Viverette 195816aa142023c75cf427401c21831193998bdf233Alan Viverette setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState), 196816aa142023c75cf427401c21831193998bdf233Alan Viverette resolveSizeAndState(maxHeight, heightMeasureSpec, 197816aa142023c75cf427401c21831193998bdf233Alan Viverette childState << MEASURED_HEIGHT_STATE_SHIFT)); 198816aa142023c75cf427401c21831193998bdf233Alan Viverette 199816aa142023c75cf427401c21831193998bdf233Alan Viverette count = mMatchParentChildren.size(); 200816aa142023c75cf427401c21831193998bdf233Alan Viverette if (count > 1) { 201816aa142023c75cf427401c21831193998bdf233Alan Viverette for (int i = 0; i < count; i++) { 202816aa142023c75cf427401c21831193998bdf233Alan Viverette final View child = mMatchParentChildren.get(i); 203816aa142023c75cf427401c21831193998bdf233Alan Viverette 204816aa142023c75cf427401c21831193998bdf233Alan Viverette final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 205816aa142023c75cf427401c21831193998bdf233Alan Viverette final int childWidthMeasureSpec; 206816aa142023c75cf427401c21831193998bdf233Alan Viverette final int childHeightMeasureSpec; 207816aa142023c75cf427401c21831193998bdf233Alan Viverette 208816aa142023c75cf427401c21831193998bdf233Alan Viverette if (lp.width == LayoutParams.MATCH_PARENT) { 209816aa142023c75cf427401c21831193998bdf233Alan Viverette childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( 210816aa142023c75cf427401c21831193998bdf233Alan Viverette getMeasuredWidth() - getPaddingLeft() - getPaddingRight(), 211816aa142023c75cf427401c21831193998bdf233Alan Viverette MeasureSpec.EXACTLY); 212816aa142023c75cf427401c21831193998bdf233Alan Viverette } else { 213816aa142023c75cf427401c21831193998bdf233Alan Viverette childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, 214816aa142023c75cf427401c21831193998bdf233Alan Viverette getPaddingLeft() + getPaddingRight(), 215816aa142023c75cf427401c21831193998bdf233Alan Viverette lp.width); 216816aa142023c75cf427401c21831193998bdf233Alan Viverette } 217816aa142023c75cf427401c21831193998bdf233Alan Viverette 218816aa142023c75cf427401c21831193998bdf233Alan Viverette if (lp.height == LayoutParams.MATCH_PARENT) { 219816aa142023c75cf427401c21831193998bdf233Alan Viverette childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( 220816aa142023c75cf427401c21831193998bdf233Alan Viverette getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), 221816aa142023c75cf427401c21831193998bdf233Alan Viverette MeasureSpec.EXACTLY); 222816aa142023c75cf427401c21831193998bdf233Alan Viverette } else { 223816aa142023c75cf427401c21831193998bdf233Alan Viverette childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, 224816aa142023c75cf427401c21831193998bdf233Alan Viverette getPaddingTop() + getPaddingBottom(), 225816aa142023c75cf427401c21831193998bdf233Alan Viverette lp.height); 226816aa142023c75cf427401c21831193998bdf233Alan Viverette } 227816aa142023c75cf427401c21831193998bdf233Alan Viverette 228816aa142023c75cf427401c21831193998bdf233Alan Viverette child.measure(childWidthMeasureSpec, childHeightMeasureSpec); 229816aa142023c75cf427401c21831193998bdf233Alan Viverette } 230816aa142023c75cf427401c21831193998bdf233Alan Viverette } 231816aa142023c75cf427401c21831193998bdf233Alan Viverette 232816aa142023c75cf427401c21831193998bdf233Alan Viverette mMatchParentChildren.clear(); 233816aa142023c75cf427401c21831193998bdf233Alan Viverette } 234816aa142023c75cf427401c21831193998bdf233Alan Viverette 2350ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette public void setDayOfWeekTextAppearance(int resId) { 2360ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mAdapter.setDayOfWeekTextAppearance(resId); 2370ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 2380ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 2390ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette public int getDayOfWeekTextAppearance() { 2400ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette return mAdapter.getDayOfWeekTextAppearance(); 2410ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 2420ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 2430ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette public void setDayTextAppearance(int resId) { 2440ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mAdapter.setDayTextAppearance(resId); 2450ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 2460ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 2470ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette public int getDayTextAppearance() { 2480ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette return mAdapter.getDayTextAppearance(); 249e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette } 250e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette 2514612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 2524612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Sets the currently selected date to the specified timestamp. Jumps 2534612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * immediately to the new date. To animate to the new date, use 2540ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * {@link #setDate(long, boolean)}. 2554612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 2560ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * @param timeInMillis the target day in milliseconds 2574612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 2584612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setDate(long timeInMillis) { 2590ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette setDate(timeInMillis, false); 2604612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 2614612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 2620ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette /** 2630ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * Sets the currently selected date to the specified timestamp. Jumps 2640ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * immediately to the new date, optionally animating the transition. 2650ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * 2660ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * @param timeInMillis the target day in milliseconds 2670ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * @param animate whether to smooth scroll to the new position 2680ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette */ 2690ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette public void setDate(long timeInMillis, boolean animate) { 2700ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette setDate(timeInMillis, animate, true); 2710ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 2720ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 2730ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette /** 2740ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * Moves to the month containing the specified day, optionally setting the 2750ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * day as selected. 2760ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * 2770ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * @param timeInMillis the target day in milliseconds 2780ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * @param animate whether to smooth scroll to the new position 2790ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette * @param setSelected whether to set the specified day as selected 2800ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette */ 2810ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette private void setDate(long timeInMillis, boolean animate, boolean setSelected) { 2820ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (setSelected) { 2830ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette mSelectedDay.setTimeInMillis(timeInMillis); 2840ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 2850ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette 2860ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette final int position = getPositionFromDay(timeInMillis); 2870ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette if (position != getCurrentItem()) { 2880ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette setCurrentItem(position, animate); 2890ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette } 290f63757b7a6d06138860640f8e95326dc1ff47646Alan Viverette 291f63757b7a6d06138860640f8e95326dc1ff47646Alan Viverette mTempCalendar.setTimeInMillis(timeInMillis); 292f63757b7a6d06138860640f8e95326dc1ff47646Alan Viverette mAdapter.setSelectedDay(mTempCalendar); 2934612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 2944612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 2954612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public long getDate() { 2964612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mSelectedDay.getTimeInMillis(); 297e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette } 298e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette 299e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette public void setFirstDayOfWeek(int firstDayOfWeek) { 300e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette mAdapter.setFirstDayOfWeek(firstDayOfWeek); 301bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 302bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 3034612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public int getFirstDayOfWeek() { 3044612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mAdapter.getFirstDayOfWeek(); 3054612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3064612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 3074612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setMinDate(long timeInMillis) { 3084612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mMinDate.setTimeInMillis(timeInMillis); 3094612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette onRangeChanged(); 3104612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3114612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 3124612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public long getMinDate() { 3134612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mMinDate.getTimeInMillis(); 3144612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3154612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 3164612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setMaxDate(long timeInMillis) { 3174612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mMaxDate.setTimeInMillis(timeInMillis); 3184612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette onRangeChanged(); 3194612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 32050eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette 3214612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public long getMaxDate() { 3224612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mMaxDate.getTimeInMillis(); 3234612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3244612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 3254612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 3264612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Handles changes to date range. 3274612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 3284612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void onRangeChanged() { 32950eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette mAdapter.setRange(mMinDate, mMaxDate); 33050eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette 3315ecbfeb38b6bdcfe8f3561f8cdcb4af9ba30c886Alan Viverette // Changing the min/max date changes the selection position since we 3324612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // don't really have stable IDs. Jumps immediately to the new position. 3330ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette setDate(mSelectedDay.getTimeInMillis(), false, false); 33450eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette } 33550eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette 33650eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette /** 337e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette * Sets the listener to call when the user selects a day. 33850eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette * 339e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette * @param listener The listener to call. 340bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio */ 341e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette public void setOnDaySelectedListener(OnDaySelectedListener listener) { 342e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette mOnDaySelectedListener = listener; 343bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 344bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 34550eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette private int getDiffMonths(Calendar start, Calendar end) { 346bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio final int diffYears = end.get(Calendar.YEAR) - start.get(Calendar.YEAR); 3470ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette return end.get(Calendar.MONTH) - start.get(Calendar.MONTH) + 12 * diffYears; 348bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 349bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 3504612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int getPositionFromDay(long timeInMillis) { 35150eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette final int diffMonthMax = getDiffMonths(mMinDate, mMaxDate); 3524612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette final int diffMonth = getDiffMonths(mMinDate, getTempCalendarForTime(timeInMillis)); 35350eb025c2fea7e364e0be951ce8ba6ca605f901aAlan Viverette return MathUtils.constrain(diffMonth, 0, diffMonthMax); 354bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 355bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio 3564612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private Calendar getTempCalendarForTime(long timeInMillis) { 3574612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mTempCalendar == null) { 3584612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempCalendar = Calendar.getInstance(); 3594612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3604612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempCalendar.setTimeInMillis(timeInMillis); 3614612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mTempCalendar; 3624612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3634612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 364bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio /** 365bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio * Gets the position of the view that is most prominently displayed within the list view. 366bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio */ 367bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio public int getMostVisiblePosition() { 3680ef59ac0e57e9b99d174d4a53f7d9639357743acAlan Viverette return getCurrentItem(); 369bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio } 370e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette 371e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette public interface OnDaySelectedListener { 372e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette public void onDaySelected(DayPickerView view, Calendar day); 373e763c9bd6ed0ca46daafc21fc4313ebcad4bcafaAlan Viverette } 374bd9152f6ee156ee473f05f6f05f238605996fca4Fabrice Di Meglio} 375