Reputation: 1546
I want to display unlimited viewpager in my calendar when I slide the month view. How can I do that? I think I need 3 fragments to do that. However, I don't know how to update the month (fragment) when I swipe Left or right. I attached my code below. I give question marks where I have no idea to code. This is my project: https://github.com/lolyoshi/CalendarWidget
Any help is appreciated.
InfinitedPagerAdapter.java
public class InfinitePagerAdapter extends FragmentPagerAdapter{
CalendarView[] fragList;
int fragNumber = 3;
public InfinitePagerAdapter(FragmentManager fm, CalendarView[] fragList) {
super(fm);
this.fragList = fragList;
}
@Override
public int getItemPosition(Object object) {
// TODO Auto-generated method stub
return POSITION_NONE;
}
@Override
public Fragment getItem(int position) {
return fragList[position];
}
@Override
public int getCount() {
return fragNumber;
}
public void setCalendar(????) {
//Need to update 3 fragments
??????????????????????
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
// TODO Auto-generated method stub
return false;
}
}
CalendarWidget.java
public class CalendarWidget extends FragmentActivity {
ViewPager monthPage;
private static final int PAGE_MIDDLE = 1;
private int mSelectedPageIndex = 1;
public Calendar curMonth;
InfinitePagerAdapter monthPageAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.calendar_layout);
CalendarView[] fragList = new CalendarView[3];
curMonth = Calendar.getInstance();
Calendar prevMonth, nextMonth;
prevMonth = (Calendar) curMonth.clone();
nextMonth = (Calendar) curMonth.clone();
prevMonth.set(Calendar.MONTH, prevMonth.get(Calendar.MONTH) - 1);
nextMonth.set(Calendar.MONTH, nextMonth.get(Calendar.MONTH) + 1);
fragList[0] = CalendarView.newInstance(prevMonth);
fragList[1] = CalendarView.newInstance(curMonth);
fragList[2] = CalendarView.newInstance(nextMonth);
monthPage = (ViewPager)findViewById(R.id.pager);
monthPageAdapter = new InfinitePagerAdapter(getSupportFragmentManager(), fragList);
monthPage.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
if (mSelectedPageIndex < PAGE_MIDDLE) {
curMonth.add(Calendar.MONTH, -1);
} else if (mSelectedPageIndex > PAGE_MIDDLE) {
curMonth.add(Calendar.MONTH, 1);
}
//Need to update 3 fragments
monthPageAdapter.setCalendar(????);
monthPage.setCurrentItem(1, false);
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
@Override
public void onPageSelected(int arg0) {
// TODO Auto-generated method stub
mSelectedPageIndex = arg0;
}});
monthPage.setAdapter(monthPageAdapter);
monthPage.setCurrentItem(1, false);
}
}
CalendarView.java
public class CalendarView extends Fragment{
protected static Calendar calendar;
protected final Calendar itemMonth;
private CalendarAdapter calendarAdapter;
private LinearLayout calendarLayout;
public ArrayList<String> items;
ArrayList<String> event;
ArrayList<String> desc;
public Handler handler;
private int mMonth, mYear;
private static final int PAGE_LEFT = 0;
private static final int PAGE_MIDDLE = 1;
private static final int PAGE_RIGHT = 2;
static CalendarView newInstance(?????) {
//What can I put in this function?
return f;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
calendarLayout = (LinearLayout)inflater.inflate(R.layout.calendar_layout, container, false);
final GridView calendarDayGrid = (GridView)calendarLayout.findViewById(R.id.calendar_days_grid);
calendarDayGrid.setAdapter(new ArrayAdapter<String>(getActivity(), R.layout.day_cell, getResources().getStringArray(R.array.days_array)));
final GridView calendarGrid = (GridView)calendarLayout.findViewById(R.id.calendar_grid);
calendarGrid.setOnTouchListener(new OnTouchListener(){
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_MOVE){
return true;
}
return false;
}
});
calendarGrid.setOnItemClickListener(new DayItemClickListener());
DisplayMetrics displaymetrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int height = displaymetrics.heightPixels;
int width = displaymetrics.widthPixels;
float gridHeight = height*3/4 - 3*(convertDpToPixels(50, getActivity())); //fix the height of table of days in week = 25dp
calendarAdapter = new CalendarAdapter(getActivity(), calendar, gridHeight);
updateCurrentMonth();
calendarGrid.setAdapter(calendarAdapter);
return calendarLayout;
}
public CalendarView() {
calendar = Calendar.getInstance();
itemMonth = (Calendar) calendar.clone();
}
protected void updateCurrentMonth() {
calendarAdapter.refreshDays();
//handler.post(calendarUpdater);
TextView month = (TextView)calendarLayout.findViewById(R.id.month_title);
month.setTextColor(Color.BLACK);
int monthID = calendar.get(Calendar.MONTH);
int[] monthIds = {R.string.january,R.string.february,R.string.march,R.string.april,R.string.may,R.string.june,
R.string.july,R.string.august,R.string.september,R.string.october,R.string.november,R.string.december};
month.setText(monthIds[monthID]);
String tmp = (String) month.getText();
month.setText(tmp + " " + calendar.get(Calendar.YEAR));
}
protected final void onNextMonth() {
if (calendar.get(Calendar.MONTH) == Calendar.DECEMBER) {
calendar.set((calendar.get(Calendar.YEAR) + 1), Calendar.JANUARY, 1);
} else {
calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + 1);
}
updateCurrentMonth(calendar);
}
protected final void onPreviousMonth() {
if (calendar.get(Calendar.MONTH) == Calendar.JANUARY) {
calendar.set((calendar.get(Calendar.YEAR) - 1), Calendar.DECEMBER, 1);
} else {
calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH)-1);
}
updateCurrentMonth(calendar);
}
public static float convertDpToPixels(float dp,Context context){
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
float px = dp * (metrics.densityDpi/160f);
return px;
}
public static float convertPixelsToDp(float px,Context context){
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
float dp = px / (metrics.densityDpi / 160f);
return dp;
}
private final class DayItemClickListener implements OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final TextView dayView = (TextView)view.findViewById(R.id.date_in_cell);
final CharSequence text = dayView.getText();
if (text != null && !"".equals(text)) {
calendarAdapter.setSelected(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), Integer.valueOf(String.valueOf(text)));
}
}
}
}
Upvotes: 4
Views: 6797
Reputation: 7708
The reason why your month don't update when you swipe is because you have declared the protected static Calendar calendar;
static. Once you remove the static, all three pages show different months.
Keep your calendar view just as it is on github, except this change:
static CalendarView newInstance(Calendar a) {
CalendarView f = new CalendarView(a);
return f;
}
public CalendarView(Calendar cal) {
calendar = cal;
}
Your adapter will be as simple as:
public class InfinitePagerAdapter extends FragmentPagerAdapter{
CalendarView[] fragList;
public InfinitePagerAdapter(FragmentManager fm, CalendarView[] fragList) {
super(fm);
this.fragList = fragList;
}
@Override
public Fragment getItem(int position) {
return fragList[position];
}
@Override
public int getCount() {
return fragList.length;
}
}
Finally in your Calendar widget modify as below:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_calendar_widget);
final CalendarView[] fragList = new CalendarView[3];
curMonth = Calendar.getInstance();
Calendar prevMonth, nextMonth;
prevMonth = (Calendar) curMonth.clone();
nextMonth = (Calendar) curMonth.clone();
prevMonth.set(Calendar.MONTH, prevMonth.get(Calendar.MONTH) - 1);
nextMonth.set(Calendar.MONTH, nextMonth.get(Calendar.MONTH) + 1);
fragList[0] = CalendarView.newInstance(prevMonth);
fragList[1] = CalendarView.newInstance(curMonth);
fragList[2] = CalendarView.newInstance(nextMonth);
monthPage = (ViewPager) findViewById(R.id.pager);
monthPageAdapter = new InfinitePagerAdapter(getSupportFragmentManager(), fragList);
monthPage.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
if (arg0 == ViewPager.SCROLL_STATE_IDLE) {
if (mSelectedPageIndex < PAGE_MIDDLE) {
fragList[0].onPreviousMonth();
fragList[1].onPreviousMonth();
fragList[2].onPreviousMonth();
} else if (mSelectedPageIndex > PAGE_MIDDLE) {
fragList[0].onNextMonth();
fragList[1].onNextMonth();
fragList[2].onNextMonth();
}
monthPage.setCurrentItem(1, false);
}
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
@Override
public void onPageSelected(int arg0) {
// TODO Auto-generated method stub
mSelectedPageIndex = arg0;
}
});
monthPage.setAdapter(monthPageAdapter);
monthPage.setCurrentItem(1, false);
}
That is all you need to do. Everything should work as desired.
Note: Despite everything works, cloning and passing around calendar objects may not be the best thing to do. Calendar
objects are expensive. You should pass around Time
if possible. Take some motivation from here
Upvotes: 5