diff options
author | Rohit Yengisetty <rohit@cyngn.com> | 2014-11-26 19:18:49 -0800 |
---|---|---|
committer | Steve Kondik <steve@cyngn.com> | 2015-10-18 13:52:41 -0700 |
commit | 7b95358fdd3f9759a70fb4d27f2d2be4c5f796c6 (patch) | |
tree | e097afc5c52f2269436e70a7ea5ced2062017e18 /src | |
parent | 990c61ad0a076a13598660b7fa477e6c30f7b783 (diff) | |
download | android_packages_apps_Calendar-7b95358fdd3f9759a70fb4d27f2d2be4c5f796c6.tar.gz android_packages_apps_Calendar-7b95358fdd3f9759a70fb4d27f2d2be4c5f796c6.tar.bz2 android_packages_apps_Calendar-7b95358fdd3f9759a70fb4d27f2d2be4c5f796c6.zip |
Calendar : Adding Year View
Depends on changes to datetimepicker
@ http://review.cyanogenmod.org/#/c/79480/
Change-Id: Ie528d8c1753477b94a9c477f5735a198565afd4d
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/calendar/AllInOneActivity.java | 27 | ||||
-rw-r--r-- | src/com/android/calendar/CalendarController.java | 5 | ||||
-rw-r--r-- | src/com/android/calendar/CalendarViewAdapter.java | 24 | ||||
-rw-r--r-- | src/com/android/calendar/year/YearViewAdapter.java | 319 | ||||
-rw-r--r-- | src/com/android/calendar/year/YearViewPagerFragment.java | 253 |
5 files changed, 624 insertions, 4 deletions
diff --git a/src/com/android/calendar/AllInOneActivity.java b/src/com/android/calendar/AllInOneActivity.java index fcf2b0cd..7bcb6772 100644 --- a/src/com/android/calendar/AllInOneActivity.java +++ b/src/com/android/calendar/AllInOneActivity.java @@ -80,6 +80,7 @@ import com.android.calendar.CalendarController.ViewType; import com.android.calendar.agenda.AgendaFragment; import com.android.calendar.month.MonthByWeekFragment; import com.android.calendar.selectcalendars.SelectVisibleCalendarsFragment; +import com.android.calendar.year.YearViewPagerFragment; import java.io.File; import java.io.IOException; @@ -113,6 +114,7 @@ public class AllInOneActivity extends AbstractCalendarActivity implements EventH private static final int BUTTON_WEEK_INDEX = 1; private static final int BUTTON_MONTH_INDEX = 2; private static final int BUTTON_AGENDA_INDEX = 3; + private static final int BUTTON_YEAR_INDEX = 4; private CalendarController mController; private static boolean mIsMultipane; @@ -156,6 +158,7 @@ public class AllInOneActivity extends AbstractCalendarActivity implements EventH private ActionBar.Tab mDayTab; private ActionBar.Tab mWeekTab; private ActionBar.Tab mMonthTab; + private ActionBar.Tab mYearTab; private ActionBar.Tab mAgendaTab; private SearchView mSearchView; private MenuItem mSearchMenu; @@ -505,6 +508,9 @@ public class AllInOneActivity extends AbstractCalendarActivity implements EventH case ViewType.MONTH: mActionBar.setSelectedNavigationItem(BUTTON_MONTH_INDEX); break; + case ViewType.YEAR: + mActionBar.setSelectedNavigationItem(BUTTON_YEAR_INDEX); + break; default: mActionBar.setSelectedNavigationItem(BUTTON_DAY_INDEX); break; @@ -988,6 +994,16 @@ public class AllInOneActivity extends AbstractCalendarActivity implements EventH } ExtensionsFactory.getAnalyticsLogger(getBaseContext()).trackView("month"); break; + case ViewType.YEAR: + if (mActionBar != null && (mActionBar.getSelectedTab() != mYearTab)) { + mActionBar.selectTab(mYearTab); + } + if (mActionBarMenuSpinnerAdapter != null) { + mActionBar.setSelectedNavigationItem(CalendarViewAdapter.YEAR_BUTTON_INDEX); + } + frag = new YearViewPagerFragment(timeMillis); + ExtensionsFactory.getAnalyticsLogger(getBaseContext()).trackView("year"); + break; case ViewType.WEEK: default: if (mActionBar != null && (mActionBar.getSelectedTab() != mWeekTab)) { @@ -1328,13 +1344,15 @@ public class AllInOneActivity extends AbstractCalendarActivity implements EventH mController.sendEvent(this, EventType.GO_TO, null, null, -1, ViewType.WEEK); } else if (tab == mMonthTab && mCurrentView != ViewType.MONTH) { mController.sendEvent(this, EventType.GO_TO, null, null, -1, ViewType.MONTH); + } else if (tab == mYearTab && mCurrentView != ViewType.YEAR) { + mController.sendEvent(this, EventType.GO_TO, null, null, -1, ViewType.YEAR); } else if (tab == mAgendaTab && mCurrentView != ViewType.AGENDA) { mController.sendEvent(this, EventType.GO_TO, null, null, -1, ViewType.AGENDA); } else { Log.w(TAG, "TabSelected event from unknown tab: " + (tab == null ? "null" : tab.getText())); Log.w(TAG, "CurrentView:" + mCurrentView + " Tab:" + tab.toString() + " Day:" + mDayTab - + " Week:" + mWeekTab + " Month:" + mMonthTab + " Agenda:" + mAgendaTab); + + " Week:" + mWeekTab + " Month:" + mMonthTab + " Year:" + mYearTab + " Agenda:" + mAgendaTab); } } @@ -1365,6 +1383,11 @@ public class AllInOneActivity extends AbstractCalendarActivity implements EventH mController.sendEvent(this, EventType.GO_TO, null, null, -1, ViewType.MONTH); } break; + case CalendarViewAdapter.YEAR_BUTTON_INDEX: + if (mCurrentView != ViewType.YEAR) { + mController.sendEvent(this, EventType.GO_TO, null, null, -1, ViewType.YEAR); + } + break; case CalendarViewAdapter.AGENDA_BUTTON_INDEX: if (mCurrentView != ViewType.AGENDA) { mController.sendEvent(this, EventType.GO_TO, null, null, -1, ViewType.AGENDA); @@ -1374,7 +1397,7 @@ public class AllInOneActivity extends AbstractCalendarActivity implements EventH Log.w(TAG, "ItemSelected event from unknown button: " + itemPosition); Log.w(TAG, "CurrentView:" + mCurrentView + " Button:" + itemPosition + " Day:" + mDayTab + " Week:" + mWeekTab + " Month:" + mMonthTab + - " Agenda:" + mAgendaTab); + " Year:" + mYearTab + " Agenda:" + mAgendaTab); break; } return false; diff --git a/src/com/android/calendar/CalendarController.java b/src/com/android/calendar/CalendarController.java index 93b1b489..fd5392f1 100644 --- a/src/com/android/calendar/CalendarController.java +++ b/src/com/android/calendar/CalendarController.java @@ -130,7 +130,7 @@ public class CalendarController { } /** - * One of the Agenda/Day/Week/Month view types + * One of the Agenda/Day/Week/Month/Year view types */ public interface ViewType { final int DETAIL = -1; @@ -140,7 +140,8 @@ public class CalendarController { final int WEEK = 3; final int MONTH = 4; final int EDIT = 5; - final int MAX_VALUE = 5; + final int YEAR = 6; + final int MAX_VALUE = 6; } public static class EventInfo { diff --git a/src/com/android/calendar/CalendarViewAdapter.java b/src/com/android/calendar/CalendarViewAdapter.java index a2aaae0a..fa9bab4d 100644 --- a/src/com/android/calendar/CalendarViewAdapter.java +++ b/src/com/android/calendar/CalendarViewAdapter.java @@ -32,9 +32,12 @@ import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; +import java.text.SimpleDateFormat; import java.util.Calendar; +import java.util.Date; import java.util.Formatter; import java.util.Locale; +import java.util.TimeZone; /* @@ -67,6 +70,7 @@ public class CalendarViewAdapter extends BaseAdapter { public static final int WEEK_BUTTON_INDEX = 1; public static final int MONTH_BUTTON_INDEX = 2; public static final int AGENDA_BUTTON_INDEX = 3; + public static final int YEAR_BUTTON_INDEX = 4; // The current selected event's time, used to calculate the date and day of the week // for the buttons. @@ -245,6 +249,11 @@ public class CalendarViewAdapter extends BaseAdapter { weekDay.setText(buildDayOfWeek()); date.setText(buildFullDate()); break; + case ViewType.YEAR: + weekDay.setVisibility(View.GONE); + lunarInfo.setVisibility(View.GONE); + date.setText(buildYearDate()); + break; default: v = null; break; @@ -271,6 +280,9 @@ public class CalendarViewAdapter extends BaseAdapter { case ViewType.MONTH: title.setText(mButtonNames [MONTH_BUTTON_INDEX]); break; + case ViewType.YEAR: + title.setText(mButtonNames [YEAR_BUTTON_INDEX]); + break; case ViewType.AGENDA: title.setText(mButtonNames [AGENDA_BUTTON_INDEX]); break; @@ -328,6 +340,12 @@ public class CalendarViewAdapter extends BaseAdapter { date.setText(buildMonthDayDate()); } break; + case YEAR_BUTTON_INDEX: + viewType.setText(mButtonNames [YEAR_BUTTON_INDEX]); + if (mShowDate) { + date.setText(buildYearDate()); + } + break; default: v = convertView; break; @@ -394,6 +412,12 @@ public class CalendarViewAdapter extends BaseAdapter { return date; } + private String buildYearDate() { + SimpleDateFormat yearFormat = new SimpleDateFormat("yyyy"); + yearFormat.setTimeZone(TimeZone.getTimeZone(mTimeZone)); + return yearFormat.format(new Date(mMilliTime)); + } + private String buildMonthYearDate() { mStringBuilder.setLength(0); String date = DateUtils.formatDateRange( diff --git a/src/com/android/calendar/year/YearViewAdapter.java b/src/com/android/calendar/year/YearViewAdapter.java new file mode 100644 index 00000000..f4bd4964 --- /dev/null +++ b/src/com/android/calendar/year/YearViewAdapter.java @@ -0,0 +1,319 @@ +package com.android.calendar.year; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.text.format.DateUtils; +import android.text.format.Time; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.BaseAdapter; +import android.widget.LinearLayout; +import com.android.calendar.CalendarController; +import com.android.calendar.CalendarController.EventType; +import com.android.calendar.R; +import com.android.datetimepicker.date.MonthView; + +import java.util.HashMap; + +/** + * Adapter class used to display an entire year as a sequence of month views + */ +public class YearViewAdapter extends BaseAdapter implements View.OnTouchListener { + + /* Define configuration parameters for a month view */ + // fraction of the view occupied by the header + private static final double MONTH_HEADER_HEIGHT = 0.30; + + // fraction of the header to use for the month title text + private static final double MONTH_LABEL_FONT_SIZE = MONTH_HEADER_HEIGHT * 0.30; + + // fraction of the view to use as padding along one edge + private static final double PADDING = 0.05; + + // fraction of the view to use for text + private static final double MONTH_DAY_TEXT_SIZE = (1 - (2 * PADDING)) * (0.7) / 7; + + // The padding b/w the week rows. The container height sans that taken up by the header + // is equally distributed among six rows + private static final double ROW_HEIGHT = (1 - MONTH_HEADER_HEIGHT) / 6; + + private static final int NUMBER_OF_MONTHS = 12; + + /* Instance Variables */ + private final Context mContext; + private CalendarController mController; + private int mYear; + private int mCurrentMonth = -1; + + private int mColumns; // number of columns the months will be dispersed into + private int mWidth; // dimensions of the container housing the entire year view + private int mHeight; + private int mMonthWidth; // dimensions of each month inside the year view + private int mMonthHeight; + private int mCurrentMonthBgColor; + private int mMonthTitleColor; + private int mMonthClickColor; + private int mCurrentDayColor; + + private View mClickedView; + private long mClickTimestamp; + private long mClickAnimDuration = ViewConfiguration.getTapTimeout() + 100; + private int mTouchSlop; // threshold for click to scroll transition + private float mClickX; // initial ACTION_DOWN coordinates + private float mClickY; + + public YearViewAdapter(Context context, int year, int columns) { + mContext = context; + mController = CalendarController.getInstance(mContext); + mYear = year; + mColumns = columns; + + mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop(); + mMonthTitleColor = mContext.getResources().getColor(R.color.year_view_month_title_color); + mMonthClickColor = mContext.getResources().getColor(R.color.year_view_month_click_color); + mCurrentDayColor = mContext.getResources().getColor(R.color.year_view_current_day_color); + mCurrentMonthBgColor = + mContext.getResources().getColor(R.color.year_view_current_month_bg_color); + } + + /** + * Sets the container bounds that the entire year view can occupy. + * Drawing parameters are calculated based off these bounds + * + * @param width max width of the parent container + * @param height max height of the parent container + */ + public void setBounds(int width, int height) { + mWidth = width; + mHeight = height; + // calculate the dimensions of each of the months + mMonthWidth = mWidth / mColumns; + mMonthHeight = mHeight / (NUMBER_OF_MONTHS / mColumns); + } + + @Override + public int getCount() { + return NUMBER_OF_MONTHS; + } + + @Override + public Object getItem(int position) { + return null; + } + + /** + * Generates a month view + * + */ + @Override + public View getView(int position, View convertView, ViewGroup parent) { + int month = position; + // each month view is nested inside a linear layout + GreedyLinearLayout linearLayout = new GreedyLinearLayout(mContext); + AbsListView.LayoutParams params = new AbsListView.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, mMonthHeight); + linearLayout.setLayoutParams(params); + linearLayout.setId(month); + linearLayout.setOnTouchListener(this); + Time now = new Time(); + now.setToNow(); + if (now.month == month && now.year == mYear) { + mCurrentMonth = month; + linearLayout.setBackgroundColor(mCurrentMonthBgColor); + } + + // the view that actually draws the calendar month + MonthViewImpl monthView = new MonthViewImpl(mContext); + + /* set view configuration parmeters */ + HashMap<String, Integer> configureParams = new HashMap<String, Integer>(); + configureParams.put(MonthView.VIEW_PARAMS_YEAR, mYear); + configureParams.put(MonthView.VIEW_PARAMS_MONTH, month); + monthView.setMonthParams(configureParams); + + /* Customize view drawing parameters */ + // The drawing parameters are calculated based on the actual container dimensions and the + // statically defined fraction components + HashMap<String, Integer> drawingParams = new HashMap<String, Integer>(); + // padding in pixels ; applies to the left and right edges + drawingParams.put(MonthView.CONFIG_EDGE_PADDING, (int) (mMonthWidth * PADDING)); + // add Month title header height + drawingParams.put(MonthView.CONFIG_HEADER_SIZE, (int) (mMonthHeight * MONTH_HEADER_HEIGHT)); + // add Month label font size + drawingParams.put(MonthView.CONFIG_MONTH_LABEL_TEXT_SIZE, + (int) (mMonthHeight * MONTH_LABEL_FONT_SIZE)); + + // text size is chosen so that there isn't an overlap in the horizontal or vertical + // directions + double textSize = Math.min(mMonthHeight * MONTH_DAY_TEXT_SIZE, + mMonthWidth * MONTH_DAY_TEXT_SIZE); + // add text size for month days + drawingParams.put(MonthView.CONFIG_MONTH_DAY_TEXT_SIZE, (int) textSize); + + // header label flag + drawingParams.put(MonthView.CONFIG_MONTH_HEADER_LABEL_FLAGS, + DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_YEAR | + DateUtils.FORMAT_NO_MONTH_DAY); + + // add horizontal padding + drawingParams.put(MonthView.CONFIG_MONTH_ROW_HEIGHT, + (int) (mMonthHeight * ROW_HEIGHT)); + drawingParams.put(MonthView.CONFIG_FILL_PARENT_CONTAINER, 1); + drawingParams.put(MonthView.CONFIG_HEADER_TITLE_COLOR, mMonthTitleColor); + drawingParams.put(MonthView.CONFIG_DAY_SELECTED_CIRCLE_COLOR, mMonthTitleColor); + drawingParams.put(MonthView.CONFIG_DAY_SELECTED_CIRCLE_ALPHA, 255); + drawingParams.put(MonthView.CONFIG_CURRENT_DAY_COLOR, mCurrentDayColor); + + monthView.customizeViewParameters(drawingParams); + + ViewGroup.LayoutParams viewParams = new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + linearLayout.addView(monthView, viewParams); + + return linearLayout; + } + + @Override + public long getItemId(int position) { + return 0; + } + + @Override + public boolean onTouch(View v, MotionEvent event) { + int action = event.getAction(); + + switch (action) { + case MotionEvent.ACTION_DOWN: + mClickTimestamp = System.currentTimeMillis(); + mClickX = event.getX(); + mClickY = event.getY(); + mClickedView = v; + // delay click acknowledgement to avoid view highlighting during scroll + mClickedView.postDelayed(mHighlightView, ViewConfiguration.getTapTimeout()); + break; + case MotionEvent.ACTION_UP: + if (v == mClickedView) { + // avoid abrupt transitions in the UI by ensuring that the click animation + // persists for the minimum defined duration + long tapDuration = System.currentTimeMillis() - mClickTimestamp; + long delay = (tapDuration > mClickAnimDuration) ? + 0 : mClickAnimDuration - tapDuration; + v.postDelayed(mPerformClick, delay); + } + break; + case MotionEvent.ACTION_MOVE: + // clear view highlighting when the gesture becomes a scroll + if ((Math.abs(event.getX() - mClickX) > mTouchSlop) || + (Math.abs(event.getY() - mClickY) > mTouchSlop)) { + clearClickedView(v); + } + break; + case MotionEvent.ACTION_SCROLL: + case MotionEvent.ACTION_CANCEL: + clearClickedView(v); + break; + } + + return true; + } + + /** + * Undoes click acknowledgement (view highlight) + */ + private void clearClickedView(View v) { + v.removeCallbacks(mHighlightView); + synchronized (v) { + // restore the right bg color + if (v.getId() == mCurrentMonth) { + v.setBackgroundColor(mCurrentMonthBgColor); + } else { + v.setBackgroundColor(Color.TRANSPARENT); + } + } + mClickedView = null; + } + + private final Runnable mHighlightView = new Runnable() { + @Override + public void run() { + mClickedView.setBackgroundColor(mMonthClickColor); + } + }; + + /** + * A runnable that completes the action mandated by a touch event. Used to delay the action + * consequence whilst the click animation is being performed. + */ + private final Runnable mPerformClick = new Runnable() { + @Override + public void run() { + Time time = new Time(Time.getCurrentTimezone()); + time.set(1, mClickedView.getId(), mYear); // set(day, month, year) + mController.sendEvent(mContext, EventType.GO_TO, time, time, -1, + CalendarController.ViewType.MONTH, + CalendarController.EXTRA_GOTO_BACK_TO_PREVIOUS, null, null ); + } + }; + + /** + * A greedy LinearLayout that always intercepts the touch events from its children. + */ + private static class GreedyLinearLayout extends LinearLayout { + + public GreedyLinearLayout(Context context) { + super(context); + } + + /** + * Always intercept the touch events + * @param ev touch event + * @return always true indicating that the touch events won't be propagated to the children + */ + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + return true; + } + } + + /** + * Customized MonthView dictating how the days in a month are drawn onto the canvas + */ + public static class MonthViewImpl extends MonthView { + public MonthViewImpl(Context context) { + super(context); + } + + /** + * Tasked with drawing a day in the month onto the canvas + * + * @param canvas The canvas to draw on + * @param year The year of this month day + * @param month The month of this month day + * @param day The day number of this month day + * @param x The default x position to draw the day number + * @param y The default y position to draw the day number + * @param startX The left boundary of the day number rect + * @param stopX The right boundary of the day number rect + * @param startY The top boundary of the day number rect + * @param stopY The bottom boundary of the day number rect + */ + @Override + public void drawMonthDay(Canvas canvas, int year, int month, int day, + int x, int y, int startX, int stopX, int startY, int stopY) { + + if (mHasToday && mToday == day) { + int radius = mRowHeight / 2; + canvas.drawCircle(x , y - (mMiniDayNumberTextSize / 3), radius, + mSelectedCirclePaint); + mMonthNumPaint.setColor(mTodayNumberColor); + } else { + mMonthNumPaint.setColor(mDayTextColor); + } + canvas.drawText(String.format("%d", day), x, y, mMonthNumPaint); + } + } +} diff --git a/src/com/android/calendar/year/YearViewPagerFragment.java b/src/com/android/calendar/year/YearViewPagerFragment.java new file mode 100644 index 00000000..494aac69 --- /dev/null +++ b/src/com/android/calendar/year/YearViewPagerFragment.java @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2014 The CyanogenMod Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.calendar.year; + + +import android.app.Activity; +import android.app.Fragment; +import android.app.FragmentManager; +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; + +import android.support.v13.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.text.format.DateUtils; +import android.text.format.Time; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.widget.GridView; +import com.android.calendar.CalendarController; +import com.android.calendar.CalendarController.EventType; +import com.android.calendar.CalendarController.EventInfo; +import com.android.calendar.R; +import com.android.datetimepicker.date.MonthView; +import com.android.datetimepicker.date.SimpleMonthView; + +import java.util.Calendar; +import java.util.HashMap; + +/** + * Fragment encompassing a view pager to allow swiping between Years + */ +public class YearViewPagerFragment extends Fragment implements CalendarController.EventHandler { + + private static final int EPOCH_TIME_YEAR_START = 1970; + private static final int EPOCH_TIME_YEAR_END = 2036; + + private ViewPager mPager; + private YearViewPagerAdapter mPagerAdapter; + private int mCurrentYear; + private int mCurrentMonth; // the current month based on the current time + private int mCurrentPage; + private CalendarController mController; + + public YearViewPagerFragment() { + this(System.currentTimeMillis()); + } + + public YearViewPagerFragment(long timeMillis) { + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(timeMillis); + mCurrentYear = calendar.get(Calendar.YEAR); + // check + if (mCurrentYear < EPOCH_TIME_YEAR_START || mCurrentYear > EPOCH_TIME_YEAR_END) { + mCurrentYear = EPOCH_TIME_YEAR_START; + } + mCurrentMonth = calendar.get(Calendar.MONTH); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + mController = CalendarController.getInstance(activity); + } + + @Override + public void onDetach() { + super.onDetach(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.year_by_month, container, false); + mPager = (ViewPager) v.findViewById(R.id.pager); + mPagerAdapter = new YearViewPagerAdapter(getChildFragmentManager()); + mPager.setAdapter(mPagerAdapter); + + mPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener(){ + @Override + public void onPageSelected(int position) { + mCurrentPage = position; + updateTitle(EPOCH_TIME_YEAR_START + mCurrentPage); + } + }); + + return v; + } + + /** + * Interacts with the Calendar controller to update the action bar title with the current + * year + * + * @param year year the title should be updated to + */ + private void updateTitle(int year) { + Time start = new Time(Time.getCurrentTimezone()); + start.set(1, 1, year); + long formatFlags = DateUtils.FORMAT_SHOW_YEAR; + mController.sendEvent(getActivity(), EventType.UPDATE_TITLE, start, start, null, -1, + CalendarController.ViewType.CURRENT, formatFlags, null, null); + } + + @Override + public void onResume() { + super.onResume(); + goToYear(mCurrentYear); + } + + /** + * moves the pager to year specified by the input parameter + * @param year + */ + public void goToYear(int year) { + if (mPager != null) { + mPager.setCurrentItem(year - EPOCH_TIME_YEAR_START); + } + } + + @Override + public long getSupportedEventTypes() { + // support action bar navigation to the current time ("current time button") + return EventType.GO_TO; + } + + @Override + public void handleEvent(EventInfo event) { + // handle "go to current time" action bar button click + if (event.eventType == EventType.GO_TO) { + goToYear(event.selectedTime.year); + } + } + + @Override + public void eventsChanged() { + // nothing to do as this view doesn't depend on the underlying events database + } + + /** + * Adapter class for the fragment view pager that displays the year views + * + */ + public static class YearViewPagerAdapter extends FragmentPagerAdapter { + + public YearViewPagerAdapter (FragmentManager fm) { + super(fm); + } + + @Override + public Fragment getItem(int i) { + return YearViewFragment.newInstance(i); + } + + // returns the count of years from 1970 - 2036 (inclusive) + @Override + public int getCount() { + return 67; + } + } + + /** + * Fragment showing the entire year view + */ + public static class YearViewFragment extends Fragment { + private GridView mGridView; + private YearViewAdapter mAdapter; + private int mYear; + private CalendarController mController; + private int mColumns; + + static YearViewFragment newInstance(int yearOffset) { + YearViewFragment f = new YearViewFragment(); + + Bundle args = new Bundle(); + args.putInt("year", EPOCH_TIME_YEAR_START + yearOffset); + f.setArguments(args); + + return f; + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + int orientation = getActivity().getResources().getConfiguration().orientation; + if (orientation == Configuration.ORIENTATION_PORTRAIT) { + mColumns = 3; // the year view will be in a 4x3 configuration + } else { + mColumns = 4; // the year view will be in a 3x4 configuration + } + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mYear = getArguments() != null ? getArguments().getInt("year") : + EPOCH_TIME_YEAR_START; + + mController = CalendarController.getInstance(getActivity()); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + mGridView = new GridView(getActivity()); + // set layout params ? + mGridView.setStretchMode(GridView.STRETCH_COLUMN_WIDTH); + mGridView.setNumColumns(mColumns); + + // we need to wait till the gridview is laid out + // the adapter drawing the year view depends on the dimensions of the grid view to + // figure out the layout and size of each of the months and its parameters + mGridView.getViewTreeObserver().addOnGlobalLayoutListener( + new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + // remove listener + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + mGridView.getViewTreeObserver().removeOnGlobalLayoutListener(this); + } else { + mGridView.getViewTreeObserver().removeGlobalOnLayoutListener(this); + } + + int gridWidth = mGridView.getWidth(); + int gridHeight = mGridView.getHeight(); + + // prepare adapter and supply the dimensions it has to work with + mAdapter = new YearViewAdapter(getActivity(), mYear, mColumns); + mAdapter.setBounds(gridWidth, gridHeight); + + mGridView.setAdapter(mAdapter); + } + }); + + return mGridView; + } + } +} |