14612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette/* 24612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Copyright (C) 2014 The Android Open Source Project 34612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 44612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Licensed under the Apache License, Version 2.0 (the "License"); 54612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * you may not use this file except in compliance with the License. 64612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * You may obtain a copy of the License at 74612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 84612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * http://www.apache.org/licenses/LICENSE-2.0 94612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 104612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Unless required by applicable law or agreed to in writing, software 114612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * distributed under the License is distributed on an "AS IS" BASIS, 124612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * See the License for the specific language governing permissions and 144612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * limitations under the License. 154612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 164612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 174612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverettepackage android.widget; 184612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 194612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport com.android.internal.R; 204612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 214612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport android.app.Service; 224612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport android.content.Context; 234612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport android.content.res.Configuration; 244612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport android.content.res.TypedArray; 254612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport android.database.DataSetObserver; 264612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport android.graphics.Canvas; 274612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport android.graphics.Paint; 284612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport android.graphics.Rect; 294612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport android.graphics.drawable.Drawable; 304612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport android.text.TextUtils; 314612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport android.text.format.DateUtils; 324612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport android.util.AttributeSet; 334612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport android.util.DisplayMetrics; 344612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport android.util.TypedValue; 354612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport android.view.GestureDetector; 364612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport android.view.LayoutInflater; 374612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport android.view.MotionEvent; 384612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport android.view.View; 394612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport android.view.ViewGroup; 404612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 414612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport java.util.Calendar; 424612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport java.util.Locale; 434612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 444612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteimport libcore.icu.LocaleData; 454612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 464612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette/** 474612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * A delegate implementing the legacy CalendarView 484612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 494612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viveretteclass CalendarViewLegacyDelegate extends CalendarView.AbstractCalendarViewDelegate { 504612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 514612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Default value whether to show week number. 524612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 534612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private static final boolean DEFAULT_SHOW_WEEK_NUMBER = true; 544612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 554612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 564612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * The number of milliseconds in a day.e 574612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 584612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private static final long MILLIS_IN_DAY = 86400000L; 594612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 604612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 614612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * The number of day in a week. 624612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 634612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private static final int DAYS_PER_WEEK = 7; 644612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 654612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 664612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * The number of milliseconds in a week. 674612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 684612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private static final long MILLIS_IN_WEEK = DAYS_PER_WEEK * MILLIS_IN_DAY; 694612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 704612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 714612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Affects when the month selection will change while scrolling upe 724612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 734612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private static final int SCROLL_HYST_WEEKS = 2; 744612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 754612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 764612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * How long the GoTo fling animation should last. 774612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 784612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private static final int GOTO_SCROLL_DURATION = 1000; 794612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 804612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 814612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * The duration of the adjustment upon a user scroll in milliseconds. 824612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 834612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private static final int ADJUSTMENT_SCROLL_DURATION = 500; 844612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 854612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 864612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * How long to wait after receiving an onScrollStateChanged notification 874612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * before acting on it. 884612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 894612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private static final int SCROLL_CHANGE_DELAY = 40; 904612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 914612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private static final int DEFAULT_SHOWN_WEEK_COUNT = 6; 924612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 934612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private static final int DEFAULT_DATE_TEXT_SIZE = 14; 944612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 954612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private static final int UNSCALED_SELECTED_DATE_VERTICAL_BAR_WIDTH = 6; 964612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 974612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private static final int UNSCALED_WEEK_MIN_VISIBLE_HEIGHT = 12; 984612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 994612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private static final int UNSCALED_LIST_SCROLL_TOP_OFFSET = 2; 1004612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1014612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private static final int UNSCALED_BOTTOM_BUFFER = 20; 1024612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1034612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private static final int UNSCALED_WEEK_SEPARATOR_LINE_WIDTH = 1; 1044612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1054612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private static final int DEFAULT_WEEK_DAY_TEXT_APPEARANCE_RES_ID = -1; 1064612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1074612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private final int mWeekSeperatorLineWidth; 1084612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1094612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mDateTextSize; 1104612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1114612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private Drawable mSelectedDateVerticalBar; 1124612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1134612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private final int mSelectedDateVerticalBarWidth; 1144612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1154612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mSelectedWeekBackgroundColor; 1164612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1174612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mFocusedMonthDateColor; 1184612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1194612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mUnfocusedMonthDateColor; 1204612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1214612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mWeekSeparatorLineColor; 1224612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1234612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mWeekNumberColor; 1244612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1254612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mWeekDayTextAppearanceResId; 1264612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1274612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mDateTextAppearanceResId; 1284612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1294612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 1304612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * The top offset of the weeks list. 1314612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 1324612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mListScrollTopOffset = 2; 1334612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1344612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 1354612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * The visible height of a week view. 1364612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 1374612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mWeekMinVisibleHeight = 12; 1384612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1394612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 1404612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * The visible height of a week view. 1414612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 1424612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mBottomBuffer = 20; 1434612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1444612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 1454612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * The number of shown weeks. 1464612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 1474612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mShownWeekCount; 1484612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1494612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 1504612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Flag whether to show the week number. 1514612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 1524612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private boolean mShowWeekNumber; 1534612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1544612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 1554612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * The number of day per week to be shown. 1564612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 1574612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mDaysPerWeek = 7; 1584612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1594612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 1604612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * The friction of the week list while flinging. 1614612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 1624612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private float mFriction = .05f; 1634612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1644612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 1654612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Scale for adjusting velocity of the week list while flinging. 1664612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 1674612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private float mVelocityScale = 0.333f; 1684612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1694612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 1704612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * The adapter for the weeks list. 1714612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 1724612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private WeeksAdapter mAdapter; 1734612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1744612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 1754612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * The weeks list. 1764612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 1774612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private ListView mListView; 1784612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1794612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 1804612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * The name of the month to display. 1814612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 1824612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private TextView mMonthName; 1834612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1844612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 1854612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * The header with week day names. 1864612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 1874612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private ViewGroup mDayNamesHeader; 1884612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1894612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 1904612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Cached abbreviations for day of week names. 1914612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 1924612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private String[] mDayNamesShort; 1934612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1944612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 1954612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Cached full-length day of week names. 1964612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 1974612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private String[] mDayNamesLong; 1984612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 1994612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 2004612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * The first day of the week. 2014612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 2024612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mFirstDayOfWeek; 2034612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 2044612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 2054612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Which month should be displayed/highlighted [0-11]. 2064612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 2074612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mCurrentMonthDisplayed = -1; 2084612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 2094612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 2104612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Used for tracking during a scroll. 2114612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 2124612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private long mPreviousScrollPosition; 2134612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 2144612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 2154612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Used for tracking which direction the view is scrolling. 2164612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 2174612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private boolean mIsScrollingUp = false; 2184612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 2194612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 2204612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * The previous scroll state of the weeks ListView. 2214612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 2224612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mPreviousScrollState = AbsListView.OnScrollListener.SCROLL_STATE_IDLE; 2234612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 2244612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 2254612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * The current scroll state of the weeks ListView. 2264612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 2274612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mCurrentScrollState = AbsListView.OnScrollListener.SCROLL_STATE_IDLE; 2284612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 2294612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 2304612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Listener for changes in the selected day. 2314612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 2324612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private CalendarView.OnDateChangeListener mOnDateChangeListener; 2334612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 2344612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 2354612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Command for adjusting the position after a scroll/fling. 2364612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 2374612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private ScrollStateRunnable mScrollStateChangedRunnable = new ScrollStateRunnable(); 2384612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 2394612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 2404612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Temporary instance to avoid multiple instantiations. 2414612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 2424612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private Calendar mTempDate; 2434612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 2444612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 2454612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * The first day of the focused month. 2464612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 2474612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private Calendar mFirstDayOfMonth; 2484612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 2494612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 2504612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * The start date of the range supported by this picker. 2514612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 2524612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private Calendar mMinDate; 2534612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 2544612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 2554612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * The end date of the range supported by this picker. 2564612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 2574612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private Calendar mMaxDate; 2584612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 2594612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette CalendarViewLegacyDelegate(CalendarView delegator, Context context, AttributeSet attrs, 2604612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int defStyleAttr, int defStyleRes) { 2614612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette super(delegator, context); 2624612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 2634612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette final TypedArray a = context.obtainStyledAttributes(attrs, 2644612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette R.styleable.CalendarView, defStyleAttr, defStyleRes); 2654612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mShowWeekNumber = a.getBoolean(R.styleable.CalendarView_showWeekNumber, 2664612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette DEFAULT_SHOW_WEEK_NUMBER); 2674612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mFirstDayOfWeek = a.getInt(R.styleable.CalendarView_firstDayOfWeek, 2684612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette LocaleData.get(Locale.getDefault()).firstDayOfWeek); 2694612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette final String minDate = a.getString(R.styleable.CalendarView_minDate); 2704612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (TextUtils.isEmpty(minDate) || !parseDate(minDate, mMinDate)) { 2714612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette parseDate(DEFAULT_MIN_DATE, mMinDate); 2724612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 2734612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette final String maxDate = a.getString(R.styleable.CalendarView_maxDate); 2744612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (TextUtils.isEmpty(maxDate) || !parseDate(maxDate, mMaxDate)) { 2754612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette parseDate(DEFAULT_MAX_DATE, mMaxDate); 2764612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 2774612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mMaxDate.before(mMinDate)) { 2784612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette throw new IllegalArgumentException("Max date cannot be before min date."); 2794612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 2804612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mShownWeekCount = a.getInt(R.styleable.CalendarView_shownWeekCount, 2814612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette DEFAULT_SHOWN_WEEK_COUNT); 2824612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mSelectedWeekBackgroundColor = a.getColor( 2834612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette R.styleable.CalendarView_selectedWeekBackgroundColor, 0); 2844612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mFocusedMonthDateColor = a.getColor( 2854612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette R.styleable.CalendarView_focusedMonthDateColor, 0); 2864612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mUnfocusedMonthDateColor = a.getColor( 2874612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette R.styleable.CalendarView_unfocusedMonthDateColor, 0); 2884612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mWeekSeparatorLineColor = a.getColor( 2894612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette R.styleable.CalendarView_weekSeparatorLineColor, 0); 2904612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mWeekNumberColor = a.getColor(R.styleable.CalendarView_weekNumberColor, 0); 2914612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mSelectedDateVerticalBar = a.getDrawable( 2924612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette R.styleable.CalendarView_selectedDateVerticalBar); 2934612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 2944612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDateTextAppearanceResId = a.getResourceId( 2954612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette R.styleable.CalendarView_dateTextAppearance, R.style.TextAppearance_Small); 2964612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette updateDateTextSize(); 2974612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 2984612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mWeekDayTextAppearanceResId = a.getResourceId( 2994612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette R.styleable.CalendarView_weekDayTextAppearance, 3004612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette DEFAULT_WEEK_DAY_TEXT_APPEARANCE_RES_ID); 3014612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette a.recycle(); 3024612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 3034612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette DisplayMetrics displayMetrics = mDelegator.getResources().getDisplayMetrics(); 3044612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mWeekMinVisibleHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3054612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette UNSCALED_WEEK_MIN_VISIBLE_HEIGHT, displayMetrics); 3064612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mListScrollTopOffset = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3074612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette UNSCALED_LIST_SCROLL_TOP_OFFSET, displayMetrics); 3084612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mBottomBuffer = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3094612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette UNSCALED_BOTTOM_BUFFER, displayMetrics); 3104612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mSelectedDateVerticalBarWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3114612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette UNSCALED_SELECTED_DATE_VERTICAL_BAR_WIDTH, displayMetrics); 3124612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mWeekSeperatorLineWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3134612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette UNSCALED_WEEK_SEPARATOR_LINE_WIDTH, displayMetrics); 3144612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 3154612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette LayoutInflater layoutInflater = (LayoutInflater) mContext 3164612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette .getSystemService(Service.LAYOUT_INFLATER_SERVICE); 3174612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette View content = layoutInflater.inflate(R.layout.calendar_view, null, false); 3184612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDelegator.addView(content); 3194612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 3204612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mListView = (ListView) mDelegator.findViewById(R.id.list); 3214612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDayNamesHeader = (ViewGroup) content.findViewById(R.id.day_names); 3224612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mMonthName = (TextView) content.findViewById(R.id.month_name); 3234612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 3244612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette setUpHeader(); 3254612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette setUpListView(); 3264612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette setUpAdapter(); 3274612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 3284612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // go to today or whichever is close to today min or max date 3294612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempDate.setTimeInMillis(System.currentTimeMillis()); 3304612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mTempDate.before(mMinDate)) { 3314612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette goTo(mMinDate, false, true, true); 3324612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else if (mMaxDate.before(mTempDate)) { 3334612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette goTo(mMaxDate, false, true, true); 3344612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 3354612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette goTo(mTempDate, false, true, true); 3364612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3374612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 3384612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDelegator.invalidate(); 3394612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3404612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 3414612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 3424612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setShownWeekCount(int count) { 3434612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mShownWeekCount != count) { 3444612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mShownWeekCount = count; 3454612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDelegator.invalidate(); 3464612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3474612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3484612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 3494612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 3504612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public int getShownWeekCount() { 3514612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mShownWeekCount; 3524612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3534612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 3544612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 3554612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setSelectedWeekBackgroundColor(int color) { 3564612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mSelectedWeekBackgroundColor != color) { 3574612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mSelectedWeekBackgroundColor = color; 3584612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette final int childCount = mListView.getChildCount(); 3594612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette for (int i = 0; i < childCount; i++) { 3604612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette WeekView weekView = (WeekView) mListView.getChildAt(i); 3614612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (weekView.mHasSelectedDay) { 3624612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette weekView.invalidate(); 3634612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3644612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3654612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3664612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3674612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 3684612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 3694612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public int getSelectedWeekBackgroundColor() { 3704612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mSelectedWeekBackgroundColor; 3714612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3724612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 3734612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 3744612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setFocusedMonthDateColor(int color) { 3754612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mFocusedMonthDateColor != color) { 3764612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mFocusedMonthDateColor = color; 3774612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette final int childCount = mListView.getChildCount(); 3784612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette for (int i = 0; i < childCount; i++) { 3794612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette WeekView weekView = (WeekView) mListView.getChildAt(i); 3804612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (weekView.mHasFocusedDay) { 3814612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette weekView.invalidate(); 3824612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3834612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3844612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3854612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3864612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 3874612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 3884612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public int getFocusedMonthDateColor() { 3894612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mFocusedMonthDateColor; 3904612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 3914612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 3924612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 3934612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setUnfocusedMonthDateColor(int color) { 3944612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mUnfocusedMonthDateColor != color) { 3954612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mUnfocusedMonthDateColor = color; 3964612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette final int childCount = mListView.getChildCount(); 3974612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette for (int i = 0; i < childCount; i++) { 3984612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette WeekView weekView = (WeekView) mListView.getChildAt(i); 3994612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (weekView.mHasUnfocusedDay) { 4004612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette weekView.invalidate(); 4014612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4024612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4034612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4044612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4054612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 4064612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 4074612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public int getUnfocusedMonthDateColor() { 4084612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mFocusedMonthDateColor; 4094612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4104612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 4114612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 4124612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setWeekNumberColor(int color) { 4134612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mWeekNumberColor != color) { 4144612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mWeekNumberColor = color; 4154612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mShowWeekNumber) { 4164612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette invalidateAllWeekViews(); 4174612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4184612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4194612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4204612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 4214612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 4224612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public int getWeekNumberColor() { 4234612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mWeekNumberColor; 4244612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4254612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 4264612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 4274612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setWeekSeparatorLineColor(int color) { 4284612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mWeekSeparatorLineColor != color) { 4294612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mWeekSeparatorLineColor = color; 4304612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette invalidateAllWeekViews(); 4314612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4324612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4334612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 4344612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 4354612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public int getWeekSeparatorLineColor() { 4364612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mWeekSeparatorLineColor; 4374612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4384612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 4394612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 4404612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setSelectedDateVerticalBar(int resourceId) { 4414612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette Drawable drawable = mDelegator.getContext().getDrawable(resourceId); 4424612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette setSelectedDateVerticalBar(drawable); 4434612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4444612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 4454612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 4464612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setSelectedDateVerticalBar(Drawable drawable) { 4474612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mSelectedDateVerticalBar != drawable) { 4484612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mSelectedDateVerticalBar = drawable; 4494612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette final int childCount = mListView.getChildCount(); 4504612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette for (int i = 0; i < childCount; i++) { 4514612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette WeekView weekView = (WeekView) mListView.getChildAt(i); 4524612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (weekView.mHasSelectedDay) { 4534612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette weekView.invalidate(); 4544612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4554612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4564612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4574612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4584612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 4594612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 4604612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public Drawable getSelectedDateVerticalBar() { 4614612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mSelectedDateVerticalBar; 4624612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4634612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 4644612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 4654612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setWeekDayTextAppearance(int resourceId) { 4664612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mWeekDayTextAppearanceResId != resourceId) { 4674612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mWeekDayTextAppearanceResId = resourceId; 4684612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette setUpHeader(); 4694612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4704612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4714612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 4724612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 4734612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public int getWeekDayTextAppearance() { 4744612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mWeekDayTextAppearanceResId; 4754612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4764612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 4774612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 4784612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setDateTextAppearance(int resourceId) { 4794612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mDateTextAppearanceResId != resourceId) { 4804612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDateTextAppearanceResId = resourceId; 4814612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette updateDateTextSize(); 4824612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette invalidateAllWeekViews(); 4834612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4844612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4854612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 4864612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 4874612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public int getDateTextAppearance() { 4884612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mDateTextAppearanceResId; 4894612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4904612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 4914612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 4924612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setMinDate(long minDate) { 4934612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempDate.setTimeInMillis(minDate); 4944612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (isSameDate(mTempDate, mMinDate)) { 4954612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return; 4964612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 4974612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mMinDate.setTimeInMillis(minDate); 4984612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // make sure the current date is not earlier than 4994612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // the new min date since the latter is used for 5004612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // calculating the indices in the adapter thus 5014612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // avoiding out of bounds error 5024612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette Calendar date = mAdapter.mSelectedDate; 5034612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (date.before(mMinDate)) { 5044612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mAdapter.setSelectedDay(mMinDate); 5054612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 5064612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // reinitialize the adapter since its range depends on min date 5074612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mAdapter.init(); 5084612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (date.before(mMinDate)) { 5094612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette setDate(mTempDate.getTimeInMillis()); 5104612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 5114612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // we go to the current date to force the ListView to query its 5124612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // adapter for the shown views since we have changed the adapter 5134612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // range and the base from which the later calculates item indices 5144612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // note that calling setDate will not work since the date is the same 5154612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette goTo(date, false, true, false); 5164612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 5174612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 5184612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 5194612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 5204612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public long getMinDate() { 5214612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mMinDate.getTimeInMillis(); 5224612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 5234612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 5244612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 5254612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setMaxDate(long maxDate) { 5264612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempDate.setTimeInMillis(maxDate); 5274612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (isSameDate(mTempDate, mMaxDate)) { 5284612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return; 5294612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 5304612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mMaxDate.setTimeInMillis(maxDate); 5314612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // reinitialize the adapter since its range depends on max date 5324612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mAdapter.init(); 5334612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette Calendar date = mAdapter.mSelectedDate; 5344612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (date.after(mMaxDate)) { 5354612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette setDate(mMaxDate.getTimeInMillis()); 5364612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 5374612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // we go to the current date to force the ListView to query its 5384612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // adapter for the shown views since we have changed the adapter 5394612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // range and the base from which the later calculates item indices 5404612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // note that calling setDate will not work since the date is the same 5414612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette goTo(date, false, true, false); 5424612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 5434612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 5444612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 5454612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 5464612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public long getMaxDate() { 5474612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mMaxDate.getTimeInMillis(); 5484612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 5494612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 5504612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 5514612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setShowWeekNumber(boolean showWeekNumber) { 5524612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mShowWeekNumber == showWeekNumber) { 5534612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return; 5544612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 5554612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mShowWeekNumber = showWeekNumber; 5564612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mAdapter.notifyDataSetChanged(); 5574612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette setUpHeader(); 5584612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 5594612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 5604612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 5614612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public boolean getShowWeekNumber() { 5624612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mShowWeekNumber; 5634612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 5644612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 5654612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 5664612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setFirstDayOfWeek(int firstDayOfWeek) { 5674612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mFirstDayOfWeek == firstDayOfWeek) { 5684612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return; 5694612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 5704612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mFirstDayOfWeek = firstDayOfWeek; 5714612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mAdapter.init(); 5724612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mAdapter.notifyDataSetChanged(); 5734612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette setUpHeader(); 5744612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 5754612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 5764612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 5774612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public int getFirstDayOfWeek() { 5784612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mFirstDayOfWeek; 5794612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 5804612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 5814612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 5824612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setDate(long date) { 5834612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette setDate(date, false, false); 5844612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 5854612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 5864612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 5874612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setDate(long date, boolean animate, boolean center) { 5884612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempDate.setTimeInMillis(date); 5894612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (isSameDate(mTempDate, mAdapter.mSelectedDate)) { 5904612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return; 5914612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 5924612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette goTo(mTempDate, animate, true, center); 5934612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 5944612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 5954612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 5964612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public long getDate() { 5974612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mAdapter.mSelectedDate.getTimeInMillis(); 5984612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 5994612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 6004612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 6014612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setOnDateChangeListener(CalendarView.OnDateChangeListener listener) { 6024612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mOnDateChangeListener = listener; 6034612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 6044612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 6054612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 6064612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void onConfigurationChanged(Configuration newConfig) { 6074612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette setCurrentLocale(newConfig.locale); 6084612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 6094612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 6104612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 6114612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Sets the current locale. 6124612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 6134612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param locale The current locale. 6144612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 6154612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 6164612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette protected void setCurrentLocale(Locale locale) { 6174612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette super.setCurrentLocale(locale); 6184612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 6194612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempDate = getCalendarForLocale(mTempDate, locale); 6204612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mFirstDayOfMonth = getCalendarForLocale(mFirstDayOfMonth, locale); 6214612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mMinDate = getCalendarForLocale(mMinDate, locale); 6224612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mMaxDate = getCalendarForLocale(mMaxDate, locale); 6234612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 6244612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private void updateDateTextSize() { 6254612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette TypedArray dateTextAppearance = mDelegator.getContext().obtainStyledAttributes( 6264612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDateTextAppearanceResId, R.styleable.TextAppearance); 6274612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDateTextSize = dateTextAppearance.getDimensionPixelSize( 6284612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette R.styleable.TextAppearance_textSize, DEFAULT_DATE_TEXT_SIZE); 6294612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette dateTextAppearance.recycle(); 6304612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 6314612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 6324612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 6334612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Invalidates all week views. 6344612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 6354612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private void invalidateAllWeekViews() { 6364612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette final int childCount = mListView.getChildCount(); 6374612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette for (int i = 0; i < childCount; i++) { 6384612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette View view = mListView.getChildAt(i); 6394612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette view.invalidate(); 6404612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 6414612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 6424612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 6434612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 6444612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Gets a calendar for locale bootstrapped with the value of a given calendar. 6454612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 6464612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param oldCalendar The old calendar. 6474612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param locale The locale. 6484612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 6494612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private static Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) { 6504612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (oldCalendar == null) { 6514612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return Calendar.getInstance(locale); 6524612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 6534612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette final long currentTimeMillis = oldCalendar.getTimeInMillis(); 6544612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette Calendar newCalendar = Calendar.getInstance(locale); 6554612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette newCalendar.setTimeInMillis(currentTimeMillis); 6564612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return newCalendar; 6574612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 6584612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 6594612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 6604612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 6614612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @return True if the <code>firstDate</code> is the same as the <code> 6624612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * secondDate</code>. 6634612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 6644612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private static boolean isSameDate(Calendar firstDate, Calendar secondDate) { 6654612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return (firstDate.get(Calendar.DAY_OF_YEAR) == secondDate.get(Calendar.DAY_OF_YEAR) 6664612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette && firstDate.get(Calendar.YEAR) == secondDate.get(Calendar.YEAR)); 6674612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 6684612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 6694612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 6704612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Creates a new adapter if necessary and sets up its parameters. 6714612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 6724612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private void setUpAdapter() { 6734612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mAdapter == null) { 6744612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mAdapter = new WeeksAdapter(mContext); 6754612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mAdapter.registerDataSetObserver(new DataSetObserver() { 6764612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 6774612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void onChanged() { 6784612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mOnDateChangeListener != null) { 6794612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette Calendar selectedDay = mAdapter.getSelectedDay(); 6804612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mOnDateChangeListener.onSelectedDayChange(mDelegator, 6814612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette selectedDay.get(Calendar.YEAR), 6824612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette selectedDay.get(Calendar.MONTH), 6834612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette selectedDay.get(Calendar.DAY_OF_MONTH)); 6844612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 6854612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 6864612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette }); 6874612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mListView.setAdapter(mAdapter); 6884612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 6894612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 6904612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // refresh the view with the new parameters 6914612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mAdapter.notifyDataSetChanged(); 6924612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 6934612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 6944612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 6954612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Sets up the strings to be used by the header. 6964612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 6974612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private void setUpHeader() { 6984612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDayNamesShort = new String[mDaysPerWeek]; 6994612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDayNamesLong = new String[mDaysPerWeek]; 7004612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette for (int i = mFirstDayOfWeek, count = mFirstDayOfWeek + mDaysPerWeek; i < count; i++) { 7014612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int calendarDay = (i > Calendar.SATURDAY) ? i - Calendar.SATURDAY : i; 7024612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDayNamesShort[i - mFirstDayOfWeek] = DateUtils.getDayOfWeekString(calendarDay, 7034612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette DateUtils.LENGTH_SHORTEST); 7044612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDayNamesLong[i - mFirstDayOfWeek] = DateUtils.getDayOfWeekString(calendarDay, 7054612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette DateUtils.LENGTH_LONG); 7064612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 7074612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 7084612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette TextView label = (TextView) mDayNamesHeader.getChildAt(0); 7094612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mShowWeekNumber) { 7104612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette label.setVisibility(View.VISIBLE); 7114612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 7124612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette label.setVisibility(View.GONE); 7134612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 7144612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette for (int i = 1, count = mDayNamesHeader.getChildCount(); i < count; i++) { 7154612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette label = (TextView) mDayNamesHeader.getChildAt(i); 7164612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mWeekDayTextAppearanceResId > -1) { 7174612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette label.setTextAppearance(mContext, mWeekDayTextAppearanceResId); 7184612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 7194612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (i < mDaysPerWeek + 1) { 7204612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette label.setText(mDayNamesShort[i - 1]); 7214612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette label.setContentDescription(mDayNamesLong[i - 1]); 7224612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette label.setVisibility(View.VISIBLE); 7234612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 7244612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette label.setVisibility(View.GONE); 7254612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 7264612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 7274612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDayNamesHeader.invalidate(); 7284612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 7294612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 7304612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 7314612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Sets all the required fields for the list view. 7324612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 7334612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private void setUpListView() { 7344612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Configure the listview 7354612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mListView.setDivider(null); 7364612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mListView.setItemsCanFocus(true); 7374612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mListView.setVerticalScrollBarEnabled(false); 7384612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mListView.setOnScrollListener(new AbsListView.OnScrollListener() { 7394612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void onScrollStateChanged(AbsListView view, int scrollState) { 7404612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette CalendarViewLegacyDelegate.this.onScrollStateChanged(view, scrollState); 7414612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 7424612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 7434612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void onScroll( 7444612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette AbsListView view, int firstVisibleItem, int visibleItemCount, 7454612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int totalItemCount) { 7464612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette CalendarViewLegacyDelegate.this.onScroll(view, firstVisibleItem, 7474612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette visibleItemCount, totalItemCount); 7484612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 7494612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette }); 7504612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Make the scrolling behavior nicer 7514612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mListView.setFriction(mFriction); 7524612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mListView.setVelocityScale(mVelocityScale); 7534612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 7544612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 7554612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 7564612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * This moves to the specified time in the view. If the time is not already 7574612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * in range it will move the list so that the first of the month containing 7584612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * the time is at the top of the view. If the new time is already in view 7594612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * the list will not be scrolled unless forceScroll is true. This time may 7604612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * optionally be highlighted as selected as well. 7614612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 7624612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param date The time to move to. 7634612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param animate Whether to scroll to the given time or just redraw at the 7644612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * new location. 7654612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param setSelected Whether to set the given time as selected. 7664612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param forceScroll Whether to recenter even if the time is already 7674612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * visible. 7684612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 7694612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @throws IllegalArgumentException of the provided date is before the 7704612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * range start of after the range end. 7714612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 7724612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private void goTo(Calendar date, boolean animate, boolean setSelected, 7734612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette boolean forceScroll) { 7744612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (date.before(mMinDate) || date.after(mMaxDate)) { 7754612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette throw new IllegalArgumentException("Time not between " + mMinDate.getTime() 7764612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette + " and " + mMaxDate.getTime()); 7774612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 7784612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Find the first and last entirely visible weeks 7794612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int firstFullyVisiblePosition = mListView.getFirstVisiblePosition(); 7804612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette View firstChild = mListView.getChildAt(0); 7814612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (firstChild != null && firstChild.getTop() < 0) { 7824612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette firstFullyVisiblePosition++; 7834612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 7844612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int lastFullyVisiblePosition = firstFullyVisiblePosition + mShownWeekCount - 1; 7854612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (firstChild != null && firstChild.getTop() > mBottomBuffer) { 7864612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette lastFullyVisiblePosition--; 7874612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 7884612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (setSelected) { 7894612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mAdapter.setSelectedDay(date); 7904612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 7914612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Get the week we're going to 7924612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int position = getWeeksSinceMinDate(date); 7934612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 7944612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Check if the selected day is now outside of our visible range 7954612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // and if so scroll to the month that contains it 7964612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (position < firstFullyVisiblePosition || position > lastFullyVisiblePosition 7974612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette || forceScroll) { 7984612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mFirstDayOfMonth.setTimeInMillis(date.getTimeInMillis()); 7994612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mFirstDayOfMonth.set(Calendar.DAY_OF_MONTH, 1); 8004612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 8014612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette setMonthDisplayed(mFirstDayOfMonth); 8024612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 8034612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // the earliest time we can scroll to is the min date 8044612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mFirstDayOfMonth.before(mMinDate)) { 8054612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette position = 0; 8064612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 8074612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette position = getWeeksSinceMinDate(mFirstDayOfMonth); 8084612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 8094612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 8104612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mPreviousScrollState = AbsListView.OnScrollListener.SCROLL_STATE_FLING; 8114612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (animate) { 8124612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mListView.smoothScrollToPositionFromTop(position, mListScrollTopOffset, 8134612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette GOTO_SCROLL_DURATION); 8144612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 8154612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mListView.setSelectionFromTop(position, mListScrollTopOffset); 8164612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Perform any after scroll operations that are needed 8174612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette onScrollStateChanged(mListView, AbsListView.OnScrollListener.SCROLL_STATE_IDLE); 8184612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 8194612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else if (setSelected) { 8204612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Otherwise just set the selection 8214612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette setMonthDisplayed(date); 8224612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 8234612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 8244612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 8254612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 8264612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Called when a <code>view</code> transitions to a new <code>scrollState 8274612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * </code>. 8284612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 8294612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private void onScrollStateChanged(AbsListView view, int scrollState) { 8304612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mScrollStateChangedRunnable.doScrollStateChange(view, scrollState); 8314612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 8324612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 8334612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 8344612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Updates the title and selected month if the <code>view</code> has moved to a new 8354612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * month. 8364612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 8374612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, 8384612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int totalItemCount) { 8394612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette WeekView child = (WeekView) view.getChildAt(0); 8404612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (child == null) { 8414612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return; 8424612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 8434612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 8444612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Figure out where we are 8454612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette long currScroll = 8464612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette view.getFirstVisiblePosition() * child.getHeight() - child.getBottom(); 8474612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 8484612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // If we have moved since our last call update the direction 8494612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (currScroll < mPreviousScrollPosition) { 8504612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mIsScrollingUp = true; 8514612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else if (currScroll > mPreviousScrollPosition) { 8524612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mIsScrollingUp = false; 8534612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 8544612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return; 8554612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 8564612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 8574612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Use some hysteresis for checking which month to highlight. This 8584612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // causes the month to transition when two full weeks of a month are 8594612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // visible when scrolling up, and when the first day in a month reaches 8604612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // the top of the screen when scrolling down. 8614612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int offset = child.getBottom() < mWeekMinVisibleHeight ? 1 : 0; 8624612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mIsScrollingUp) { 8634612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette child = (WeekView) view.getChildAt(SCROLL_HYST_WEEKS + offset); 8644612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else if (offset != 0) { 8654612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette child = (WeekView) view.getChildAt(offset); 8664612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 8674612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 8684612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (child != null) { 8694612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Find out which month we're moving into 8704612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int month; 8714612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mIsScrollingUp) { 8724612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette month = child.getMonthOfFirstWeekDay(); 8734612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 8744612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette month = child.getMonthOfLastWeekDay(); 8754612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 8764612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 8774612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // And how it relates to our current highlighted month 8784612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int monthDiff; 8794612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mCurrentMonthDisplayed == 11 && month == 0) { 8804612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette monthDiff = 1; 8814612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else if (mCurrentMonthDisplayed == 0 && month == 11) { 8824612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette monthDiff = -1; 8834612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 8844612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette monthDiff = month - mCurrentMonthDisplayed; 8854612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 8864612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 8874612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Only switch months if we're scrolling away from the currently 8884612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // selected month 8894612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if ((!mIsScrollingUp && monthDiff > 0) || (mIsScrollingUp && monthDiff < 0)) { 8904612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette Calendar firstDay = child.getFirstDay(); 8914612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mIsScrollingUp) { 8924612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette firstDay.add(Calendar.DAY_OF_MONTH, -DAYS_PER_WEEK); 8934612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 8944612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette firstDay.add(Calendar.DAY_OF_MONTH, DAYS_PER_WEEK); 8954612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 8964612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette setMonthDisplayed(firstDay); 8974612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 8984612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 8994612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mPreviousScrollPosition = currScroll; 9004612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mPreviousScrollState = mCurrentScrollState; 9014612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 9024612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 9034612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 9044612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Sets the month displayed at the top of this view based on time. Override 9054612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * to add custom events when the title is changed. 9064612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 9074612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param calendar A day in the new focus month. 9084612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 9094612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private void setMonthDisplayed(Calendar calendar) { 9104612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mCurrentMonthDisplayed = calendar.get(Calendar.MONTH); 9114612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mAdapter.setFocusMonth(mCurrentMonthDisplayed); 9124612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_MONTH_DAY 9134612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette | DateUtils.FORMAT_SHOW_YEAR; 9144612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette final long millis = calendar.getTimeInMillis(); 9154612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette String newMonthName = DateUtils.formatDateRange(mContext, millis, millis, flags); 9164612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mMonthName.setText(newMonthName); 9174612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mMonthName.invalidate(); 9184612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 9194612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 9204612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 9214612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @return Returns the number of weeks between the current <code>date</code> 9224612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * and the <code>mMinDate</code>. 9234612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 9244612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int getWeeksSinceMinDate(Calendar date) { 9254612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (date.before(mMinDate)) { 9264612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette throw new IllegalArgumentException("fromDate: " + mMinDate.getTime() 9274612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette + " does not precede toDate: " + date.getTime()); 9284612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 9294612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette long endTimeMillis = date.getTimeInMillis() 9304612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette + date.getTimeZone().getOffset(date.getTimeInMillis()); 9314612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette long startTimeMillis = mMinDate.getTimeInMillis() 9324612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette + mMinDate.getTimeZone().getOffset(mMinDate.getTimeInMillis()); 9334612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette long dayOffsetMillis = (mMinDate.get(Calendar.DAY_OF_WEEK) - mFirstDayOfWeek) 9344612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * MILLIS_IN_DAY; 9354612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return (int) ((endTimeMillis - startTimeMillis + dayOffsetMillis) / MILLIS_IN_WEEK); 9364612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 9374612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 9384612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 9394612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Command responsible for acting upon scroll state changes. 9404612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 9414612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private class ScrollStateRunnable implements Runnable { 9424612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private AbsListView mView; 9434612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 9444612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mNewState; 9454612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 9464612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 9474612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Sets up the runnable with a short delay in case the scroll state 9484612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * immediately changes again. 9494612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 9504612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param view The list view that changed state 9514612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param scrollState The new state it changed to 9524612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 9534612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void doScrollStateChange(AbsListView view, int scrollState) { 9544612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mView = view; 9554612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mNewState = scrollState; 9564612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDelegator.removeCallbacks(this); 9574612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDelegator.postDelayed(this, SCROLL_CHANGE_DELAY); 9584612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 9594612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 9604612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void run() { 9614612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mCurrentScrollState = mNewState; 9624612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Fix the position after a scroll or a fling ends 9634612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mNewState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE 9644612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette && mPreviousScrollState != AbsListView.OnScrollListener.SCROLL_STATE_IDLE) { 9654612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette View child = mView.getChildAt(0); 9664612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (child == null) { 9674612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // The view is no longer visible, just return 9684612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return; 9694612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 9704612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int dist = child.getBottom() - mListScrollTopOffset; 9714612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (dist > mListScrollTopOffset) { 9724612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mIsScrollingUp) { 9734612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mView.smoothScrollBy(dist - child.getHeight(), 9744612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette ADJUSTMENT_SCROLL_DURATION); 9754612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 9764612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mView.smoothScrollBy(dist, ADJUSTMENT_SCROLL_DURATION); 9774612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 9784612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 9794612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 9804612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mPreviousScrollState = mNewState; 9814612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 9824612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 9834612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 9844612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 9854612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * <p> 9864612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * This is a specialized adapter for creating a list of weeks with 9874612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * selectable days. It can be configured to display the week number, start 9884612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * the week on a given day, show a reduced number of days, or display an 9894612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * arbitrary number of weeks at a time. 9904612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * </p> 9914612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 9924612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private class WeeksAdapter extends BaseAdapter implements View.OnTouchListener { 9934612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 9944612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mSelectedWeek; 9954612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 9964612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private GestureDetector mGestureDetector; 9974612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 9984612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mFocusedMonth; 9994612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 10004612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private final Calendar mSelectedDate = Calendar.getInstance(); 10014612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 10024612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mTotalWeekCount; 10034612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 10044612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public WeeksAdapter(Context context) { 10054612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mContext = context; 10064612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mGestureDetector = new GestureDetector(mContext, new WeeksAdapter.CalendarGestureListener()); 10074612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette init(); 10084612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 10094612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 10104612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 10114612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Set up the gesture detector and selected time 10124612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 10134612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private void init() { 10144612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mSelectedWeek = getWeeksSinceMinDate(mSelectedDate); 10154612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTotalWeekCount = getWeeksSinceMinDate(mMaxDate); 10164612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mMinDate.get(Calendar.DAY_OF_WEEK) != mFirstDayOfWeek 10174612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette || mMaxDate.get(Calendar.DAY_OF_WEEK) != mFirstDayOfWeek) { 10184612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTotalWeekCount++; 10194612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 10204612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette notifyDataSetChanged(); 10214612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 10224612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 10234612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 10244612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Updates the selected day and related parameters. 10254612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 10264612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param selectedDay The time to highlight 10274612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 10284612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setSelectedDay(Calendar selectedDay) { 10294612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (selectedDay.get(Calendar.DAY_OF_YEAR) == mSelectedDate.get(Calendar.DAY_OF_YEAR) 10304612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette && selectedDay.get(Calendar.YEAR) == mSelectedDate.get(Calendar.YEAR)) { 10314612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return; 10324612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 10334612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mSelectedDate.setTimeInMillis(selectedDay.getTimeInMillis()); 10344612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mSelectedWeek = getWeeksSinceMinDate(mSelectedDate); 10354612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mFocusedMonth = mSelectedDate.get(Calendar.MONTH); 10364612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette notifyDataSetChanged(); 10374612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 10384612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 10394612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 10404612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @return The selected day of month. 10414612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 10424612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public Calendar getSelectedDay() { 10434612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mSelectedDate; 10444612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 10454612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 10464612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 10474612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public int getCount() { 10484612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mTotalWeekCount; 10494612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 10504612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 10514612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 10524612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public Object getItem(int position) { 10534612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return null; 10544612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 10554612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 10564612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 10574612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public long getItemId(int position) { 10584612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return position; 10594612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 10604612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 10614612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 10624612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public View getView(int position, View convertView, ViewGroup parent) { 10634612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette WeekView weekView = null; 10644612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (convertView != null) { 10654612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette weekView = (WeekView) convertView; 10664612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 10674612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette weekView = new WeekView(mContext); 10684612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette AbsListView.LayoutParams params = 10694612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette new AbsListView.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, 10704612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette FrameLayout.LayoutParams.WRAP_CONTENT); 10714612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette weekView.setLayoutParams(params); 10724612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette weekView.setClickable(true); 10734612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette weekView.setOnTouchListener(this); 10744612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 10754612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 10764612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int selectedWeekDay = (mSelectedWeek == position) ? mSelectedDate.get( 10774612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette Calendar.DAY_OF_WEEK) : -1; 10784612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette weekView.init(position, selectedWeekDay, mFocusedMonth); 10794612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 10804612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return weekView; 10814612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 10824612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 10834612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 10844612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Changes which month is in focus and updates the view. 10854612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 10864612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param month The month to show as in focus [0-11] 10874612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 10884612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void setFocusMonth(int month) { 10894612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mFocusedMonth == month) { 10904612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return; 10914612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 10924612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mFocusedMonth = month; 10934612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette notifyDataSetChanged(); 10944612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 10954612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 10964612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 10974612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public boolean onTouch(View v, MotionEvent event) { 10984612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mListView.isEnabled() && mGestureDetector.onTouchEvent(event)) { 10994612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette WeekView weekView = (WeekView) v; 11004612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // if we cannot find a day for the given location we are done 11014612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (!weekView.getDayFromLocation(event.getX(), mTempDate)) { 11024612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return true; 11034612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 11044612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // it is possible that the touched day is outside the valid range 11054612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // we draw whole weeks but range end can fall not on the week end 11064612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mTempDate.before(mMinDate) || mTempDate.after(mMaxDate)) { 11074612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return true; 11084612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 11094612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette onDateTapped(mTempDate); 11104612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return true; 11114612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 11124612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return false; 11134612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 11144612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11154612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 11164612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Maintains the same hour/min/sec but moves the day to the tapped day. 11174612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 11184612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param day The day that was tapped 11194612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 11204612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private void onDateTapped(Calendar day) { 11214612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette setSelectedDay(day); 11224612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette setMonthDisplayed(day); 11234612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 11244612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11254612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 11264612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * This is here so we can identify single tap events and set the 11274612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * selected day correctly 11284612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 11294612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette class CalendarGestureListener extends GestureDetector.SimpleOnGestureListener { 11304612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 11314612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public boolean onSingleTapUp(MotionEvent e) { 11324612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return true; 11334612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 11344612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 11354612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 11364612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11374612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 11384612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * <p> 11394612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * This is a dynamic view for drawing a single week. It can be configured to 11404612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * display the week number, start the week on a given day, or show a reduced 11414612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * number of days. It is intended for use as a single view within a 11424612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * ListView. See {@link WeeksAdapter} for usage. 11434612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * </p> 11444612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 11454612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private class WeekView extends View { 11464612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11474612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private final Rect mTempRect = new Rect(); 11484612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11494612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private final Paint mDrawPaint = new Paint(); 11504612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11514612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private final Paint mMonthNumDrawPaint = new Paint(); 11524612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11534612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Cache the number strings so we don't have to recompute them each time 11544612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private String[] mDayNumbers; 11554612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11564612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Quick lookup for checking which days are in the focus month 11574612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private boolean[] mFocusDay; 11584612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11594612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Whether this view has a focused day. 11604612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private boolean mHasFocusedDay; 11614612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11624612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Whether this view has only focused days. 11634612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private boolean mHasUnfocusedDay; 11644612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11654612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // The first day displayed by this item 11664612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private Calendar mFirstDay; 11674612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11684612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // The month of the first day in this week 11694612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mMonthOfFirstWeekDay = -1; 11704612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11714612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // The month of the last day in this week 11724612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mLastWeekDayMonth = -1; 11734612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11744612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // The position of this week, equivalent to weeks since the week of Jan 11754612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // 1st, 1900 11764612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mWeek = -1; 11774612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11784612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Quick reference to the width of this view, matches parent 11794612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mWidth; 11804612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11814612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // The height this view should draw at in pixels, set by height param 11824612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mHeight; 11834612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11844612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // If this view contains the selected day 11854612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private boolean mHasSelectedDay = false; 11864612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11874612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Which day is selected [0-6] or -1 if no day is selected 11884612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mSelectedDay = -1; 11894612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11904612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // The number of days + a spot for week number if it is displayed 11914612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mNumCells; 11924612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11934612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // The left edge of the selected day 11944612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mSelectedLeft = -1; 11954612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11964612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // The right edge of the selected day 11974612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private int mSelectedRight = -1; 11984612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 11994612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public WeekView(Context context) { 12004612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette super(context); 12014612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 12024612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Sets up any standard paints that will be used 12034612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette initilaizePaints(); 12044612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 12054612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 12064612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 12074612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Initializes this week view. 12084612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 12094612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param weekNumber The number of the week this view represents. The 12104612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * week number is a zero based index of the weeks since 12114612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * {@link android.widget.CalendarView#getMinDate()}. 12124612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param selectedWeekDay The selected day of the week from 0 to 6, -1 if no 12134612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * selected day. 12144612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param focusedMonth The month that is currently in focus i.e. 12154612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * highlighted. 12164612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 12174612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public void init(int weekNumber, int selectedWeekDay, int focusedMonth) { 12184612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mSelectedDay = selectedWeekDay; 12194612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mHasSelectedDay = mSelectedDay != -1; 12204612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mNumCells = mShowWeekNumber ? mDaysPerWeek + 1 : mDaysPerWeek; 12214612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mWeek = weekNumber; 12224612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempDate.setTimeInMillis(mMinDate.getTimeInMillis()); 12234612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 12244612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempDate.add(Calendar.WEEK_OF_YEAR, mWeek); 12254612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempDate.setFirstDayOfWeek(mFirstDayOfWeek); 12264612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 12274612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Allocate space for caching the day numbers and focus values 12284612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDayNumbers = new String[mNumCells]; 12294612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mFocusDay = new boolean[mNumCells]; 12304612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 12314612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // If we're showing the week number calculate it based on Monday 12324612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int i = 0; 12334612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mShowWeekNumber) { 12344612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDayNumbers[0] = String.format(Locale.getDefault(), "%d", 12354612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempDate.get(Calendar.WEEK_OF_YEAR)); 12364612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette i++; 12374612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 12384612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 12394612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Now adjust our starting day based on the start day of the week 12404612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int diff = mFirstDayOfWeek - mTempDate.get(Calendar.DAY_OF_WEEK); 12414612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempDate.add(Calendar.DAY_OF_MONTH, diff); 12424612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 12434612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mFirstDay = (Calendar) mTempDate.clone(); 12444612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mMonthOfFirstWeekDay = mTempDate.get(Calendar.MONTH); 12454612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 12464612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mHasUnfocusedDay = true; 12474612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette for (; i < mNumCells; i++) { 12484612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette final boolean isFocusedDay = (mTempDate.get(Calendar.MONTH) == focusedMonth); 12494612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mFocusDay[i] = isFocusedDay; 12504612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mHasFocusedDay |= isFocusedDay; 12514612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mHasUnfocusedDay &= !isFocusedDay; 12524612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // do not draw dates outside the valid range to avoid user confusion 12534612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mTempDate.before(mMinDate) || mTempDate.after(mMaxDate)) { 12544612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDayNumbers[i] = ""; 12554612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 12564612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDayNumbers[i] = String.format(Locale.getDefault(), "%d", 12574612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempDate.get(Calendar.DAY_OF_MONTH)); 12584612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 12594612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempDate.add(Calendar.DAY_OF_MONTH, 1); 12604612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 12614612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // We do one extra add at the end of the loop, if that pushed us to 12624612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // new month undo it 12634612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mTempDate.get(Calendar.DAY_OF_MONTH) == 1) { 12644612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempDate.add(Calendar.DAY_OF_MONTH, -1); 12654612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 12664612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mLastWeekDayMonth = mTempDate.get(Calendar.MONTH); 12674612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 12684612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette updateSelectionPositions(); 12694612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 12704612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 12714612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 12724612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Initialize the paint instances. 12734612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 12744612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private void initilaizePaints() { 12754612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDrawPaint.setFakeBoldText(false); 12764612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDrawPaint.setAntiAlias(true); 12774612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDrawPaint.setStyle(Paint.Style.FILL); 12784612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 12794612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mMonthNumDrawPaint.setFakeBoldText(true); 12804612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mMonthNumDrawPaint.setAntiAlias(true); 12814612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mMonthNumDrawPaint.setStyle(Paint.Style.FILL); 12824612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mMonthNumDrawPaint.setTextAlign(Paint.Align.CENTER); 12834612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mMonthNumDrawPaint.setTextSize(mDateTextSize); 12844612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 12854612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 12864612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 12874612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Returns the month of the first day in this week. 12884612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 12894612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @return The month the first day of this view is in. 12904612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 12914612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public int getMonthOfFirstWeekDay() { 12924612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mMonthOfFirstWeekDay; 12934612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 12944612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 12954612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 12964612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Returns the month of the last day in this week 12974612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 12984612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @return The month the last day of this view is in 12994612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 13004612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public int getMonthOfLastWeekDay() { 13014612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mLastWeekDayMonth; 13024612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 13034612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 13044612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 13054612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Returns the first day in this view. 13064612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 13074612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @return The first day in the view. 13084612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 13094612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public Calendar getFirstDay() { 13104612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return mFirstDay; 13114612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 13124612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 13134612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 13144612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Calculates the day that the given x position is in, accounting for 13154612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * week number. 13164612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 13174612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param x The x position of the touch event. 13184612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @return True if a day was found for the given location. 13194612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 13204612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette public boolean getDayFromLocation(float x, Calendar outCalendar) { 13214612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette final boolean isLayoutRtl = isLayoutRtl(); 13224612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 13234612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int start; 13244612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int end; 13254612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 13264612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (isLayoutRtl) { 13274612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette start = 0; 13284612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette end = mShowWeekNumber ? mWidth - mWidth / mNumCells : mWidth; 13294612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 13304612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette start = mShowWeekNumber ? mWidth / mNumCells : 0; 13314612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette end = mWidth; 13324612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 13334612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 13344612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (x < start || x > end) { 13354612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette outCalendar.clear(); 13364612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return false; 13374612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 13384612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 13394612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // Selection is (x - start) / (pixels/day) which is (x - start) * day / pixels 13404612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int dayPosition = (int) ((x - start) * mDaysPerWeek / (end - start)); 13414612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 13424612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (isLayoutRtl) { 13434612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette dayPosition = mDaysPerWeek - 1 - dayPosition; 13444612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 13454612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 13464612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette outCalendar.setTimeInMillis(mFirstDay.getTimeInMillis()); 13474612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette outCalendar.add(Calendar.DAY_OF_MONTH, dayPosition); 13484612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 13494612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return true; 13504612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 13514612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 13524612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 13534612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette protected void onDraw(Canvas canvas) { 13544612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette drawBackground(canvas); 13554612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette drawWeekNumbersAndDates(canvas); 13564612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette drawWeekSeparators(canvas); 13574612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette drawSelectedDateVerticalBars(canvas); 13584612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 13594612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 13604612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 13614612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * This draws the selection highlight if a day is selected in this week. 13624612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 13634612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param canvas The canvas to draw on 13644612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 13654612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private void drawBackground(Canvas canvas) { 13664612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (!mHasSelectedDay) { 13674612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return; 13684612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 13694612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDrawPaint.setColor(mSelectedWeekBackgroundColor); 13704612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 13714612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempRect.top = mWeekSeperatorLineWidth; 13724612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempRect.bottom = mHeight; 13734612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 13744612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette final boolean isLayoutRtl = isLayoutRtl(); 13754612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 13764612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (isLayoutRtl) { 13774612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempRect.left = 0; 13784612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempRect.right = mSelectedLeft - 2; 13794612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 13804612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempRect.left = mShowWeekNumber ? mWidth / mNumCells : 0; 13814612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempRect.right = mSelectedLeft - 2; 13824612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 13834612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette canvas.drawRect(mTempRect, mDrawPaint); 13844612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 13854612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (isLayoutRtl) { 13864612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempRect.left = mSelectedRight + 3; 13874612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempRect.right = mShowWeekNumber ? mWidth - mWidth / mNumCells : mWidth; 13884612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 13894612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempRect.left = mSelectedRight + 3; 13904612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mTempRect.right = mWidth; 13914612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 13924612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette canvas.drawRect(mTempRect, mDrawPaint); 13934612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 13944612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 13954612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 13964612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Draws the week and month day numbers for this week. 13974612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 13984612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param canvas The canvas to draw on 13994612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 14004612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private void drawWeekNumbersAndDates(Canvas canvas) { 14014612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette final float textHeight = mDrawPaint.getTextSize(); 14024612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette final int y = (int) ((mHeight + textHeight) / 2) - mWeekSeperatorLineWidth; 14034612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette final int nDays = mNumCells; 14044612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette final int divisor = 2 * nDays; 14054612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 14064612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDrawPaint.setTextAlign(Paint.Align.CENTER); 14074612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDrawPaint.setTextSize(mDateTextSize); 14084612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 14094612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int i = 0; 14104612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 14114612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (isLayoutRtl()) { 14124612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette for (; i < nDays - 1; i++) { 14134612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mMonthNumDrawPaint.setColor(mFocusDay[i] ? mFocusedMonthDateColor 14144612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette : mUnfocusedMonthDateColor); 14154612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int x = (2 * i + 1) * mWidth / divisor; 14164612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette canvas.drawText(mDayNumbers[nDays - 1 - i], x, y, mMonthNumDrawPaint); 14174612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 14184612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mShowWeekNumber) { 14194612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDrawPaint.setColor(mWeekNumberColor); 14204612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int x = mWidth - mWidth / divisor; 14214612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette canvas.drawText(mDayNumbers[0], x, y, mDrawPaint); 14224612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 14234612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 14244612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mShowWeekNumber) { 14254612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDrawPaint.setColor(mWeekNumberColor); 14264612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int x = mWidth / divisor; 14274612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette canvas.drawText(mDayNumbers[0], x, y, mDrawPaint); 14284612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette i++; 14294612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 14304612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette for (; i < nDays; i++) { 14314612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mMonthNumDrawPaint.setColor(mFocusDay[i] ? mFocusedMonthDateColor 14324612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette : mUnfocusedMonthDateColor); 14334612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int x = (2 * i + 1) * mWidth / divisor; 14344612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette canvas.drawText(mDayNumbers[i], x, y, mMonthNumDrawPaint); 14354612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 14364612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 14374612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 14384612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 14394612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 14404612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Draws a horizontal line for separating the weeks. 14414612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 14424612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param canvas The canvas to draw on. 14434612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 14444612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private void drawWeekSeparators(Canvas canvas) { 14454612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette // If it is the topmost fully visible child do not draw separator line 14464612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int firstFullyVisiblePosition = mListView.getFirstVisiblePosition(); 14474612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mListView.getChildAt(0).getTop() < 0) { 14484612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette firstFullyVisiblePosition++; 14494612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 14504612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (firstFullyVisiblePosition == mWeek) { 14514612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return; 14524612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 14534612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDrawPaint.setColor(mWeekSeparatorLineColor); 14544612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mDrawPaint.setStrokeWidth(mWeekSeperatorLineWidth); 14554612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette float startX; 14564612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette float stopX; 14574612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (isLayoutRtl()) { 14584612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette startX = 0; 14594612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette stopX = mShowWeekNumber ? mWidth - mWidth / mNumCells : mWidth; 14604612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 14614612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette startX = mShowWeekNumber ? mWidth / mNumCells : 0; 14624612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette stopX = mWidth; 14634612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 14644612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette canvas.drawLine(startX, 0, stopX, 0, mDrawPaint); 14654612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 14664612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 14674612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 14684612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * Draws the selected date bars if this week has a selected day. 14694612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * 14704612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * @param canvas The canvas to draw on 14714612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 14724612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private void drawSelectedDateVerticalBars(Canvas canvas) { 14734612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (!mHasSelectedDay) { 14744612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette return; 14754612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 14764612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mSelectedDateVerticalBar.setBounds( 14774612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mSelectedLeft - mSelectedDateVerticalBarWidth / 2, 14784612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mWeekSeperatorLineWidth, 14794612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mSelectedLeft + mSelectedDateVerticalBarWidth / 2, 14804612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mHeight); 14814612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mSelectedDateVerticalBar.draw(canvas); 14824612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mSelectedDateVerticalBar.setBounds( 14834612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mSelectedRight - mSelectedDateVerticalBarWidth / 2, 14844612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mWeekSeperatorLineWidth, 14854612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mSelectedRight + mSelectedDateVerticalBarWidth / 2, 14864612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mHeight); 14874612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mSelectedDateVerticalBar.draw(canvas); 14884612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 14894612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 14904612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 14914612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette protected void onSizeChanged(int w, int h, int oldw, int oldh) { 14924612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mWidth = w; 14934612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette updateSelectionPositions(); 14944612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 14954612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 14964612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette /** 14974612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette * This calculates the positions for the selected day lines. 14984612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette */ 14994612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette private void updateSelectionPositions() { 15004612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mHasSelectedDay) { 15014612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette final boolean isLayoutRtl = isLayoutRtl(); 15024612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette int selectedPosition = mSelectedDay - mFirstDayOfWeek; 15034612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (selectedPosition < 0) { 15044612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette selectedPosition += 7; 15054612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 15064612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (mShowWeekNumber && !isLayoutRtl) { 15074612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette selectedPosition++; 15084612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 15094612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette if (isLayoutRtl) { 15104612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mSelectedLeft = (mDaysPerWeek - 1 - selectedPosition) * mWidth / mNumCells; 15114612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 15124612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } else { 15134612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mSelectedLeft = selectedPosition * mWidth / mNumCells; 15144612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 15154612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mSelectedRight = mSelectedLeft + mWidth / mNumCells; 15164612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 15174612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 15184612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 15194612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette @Override 15204612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 15214612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette mHeight = (mListView.getHeight() - mListView.getPaddingTop() - mListView 15224612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette .getPaddingBottom()) / mShownWeekCount; 15234612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), mHeight); 15244612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 15254612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette } 15264612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette 15274612740ddc76b3518dc6d189d5f8b5b7f60e9d64Alan Viverette} 1528